示例#1
0
/**
 * Emit the sequence to pacify R300.
 */
static __inline__ void r300_pacify(drm_radeon_private_t* dev_priv)
{
	RING_LOCALS;

	BEGIN_RING(6);
	OUT_RING( CP_PACKET0( R300_RB3D_DSTCACHE_CTLSTAT, 0 ) );
	OUT_RING( 0xa );
	OUT_RING( CP_PACKET0( 0x4f18, 0 ) );
	OUT_RING( 0x3 );
	OUT_RING( CP_PACKET3( RADEON_CP_NOP, 0 ) );
	OUT_RING( 0x0 );
	ADVANCE_RING();
}
static void tex_emit_cs(struct gl_context *ctx, struct radeon_state_atom *atom)
{
   r100ContextPtr r100 = R100_CONTEXT(ctx);
   BATCH_LOCALS(&r100->radeon);
   uint32_t dwords = atom->cmd_size;
   int i = atom->idx;
   radeonTexObj *t = r100->state.texture.unit[i].texobj;
   radeon_mipmap_level *lvl;
   int hastexture = 1;

   if (!t)
	hastexture = 0;
   else {
	if (!t->mt && !t->bo)
		hastexture = 0;
   }
   dwords += 1;
   if (hastexture)
     dwords += 2;
   else
     dwords -= 2;
   BEGIN_BATCH_NO_AUTOSTATE(dwords);

   OUT_BATCH(CP_PACKET0(RADEON_PP_TXFILTER_0 + (24 * i), 1));
   OUT_BATCH_TABLE((atom->cmd + 1), 2);

   if (hastexture) {
     OUT_BATCH(CP_PACKET0(RADEON_PP_TXOFFSET_0 + (24 * i), 0));
     if (t->mt && !t->image_override) {
        if ((ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT)) {
            lvl = &t->mt->levels[t->minLod];
	    OUT_BATCH_RELOC(lvl->faces[5].offset, t->mt->bo, lvl->faces[5].offset,
			RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
        } else {
           OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, get_base_teximage_offset(t),
		     RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
        }
      } else {
	if (t->bo)
            OUT_BATCH_RELOC(t->tile_bits, t->bo, 0,
                            RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
      }
   }

   OUT_BATCH(CP_PACKET0(RADEON_PP_TXCBLEND_0 + (i * 24), 1));
   OUT_BATCH_TABLE((atom->cmd+4), 2);
   OUT_BATCH(CP_PACKET0(RADEON_PP_BORDER_COLOR_0 + (i * 4), 0));
   OUT_BATCH((atom->cmd[TEX_PP_BORDER_COLOR]));
   END_BATCH();
}
示例#3
0
static inline uint32_t cmdpacket0(struct radeon_screen *rscrn,
                                  int reg, int count)
{
    if (count)
	    return CP_PACKET0(reg, count - 1);
    return CP_PACKET2;
}
static void cube_emit_cs(struct gl_context *ctx, struct radeon_state_atom *atom)
{
   r100ContextPtr r100 = R100_CONTEXT(ctx);
   BATCH_LOCALS(&r100->radeon);
   uint32_t dwords = atom->check(ctx, atom);
   int i = atom->idx, j;
   radeonTexObj *t = r100->state.texture.unit[i].texobj;
   radeon_mipmap_level *lvl;
   uint32_t base_reg;

   if (!(ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT))
	return;

   if (!t)
	return;

   if (!t->mt)
	return;

   switch(i) {
	case 1: base_reg = RADEON_PP_CUBIC_OFFSET_T1_0; break;
	case 2: base_reg = RADEON_PP_CUBIC_OFFSET_T2_0; break;
	default:
	case 0: base_reg = RADEON_PP_CUBIC_OFFSET_T0_0; break;
   };
   BEGIN_BATCH_NO_AUTOSTATE(dwords);
   OUT_BATCH_TABLE(atom->cmd, 2);
   lvl = &t->mt->levels[0];
   for (j = 0; j < 5; j++) {
	OUT_BATCH(CP_PACKET0(base_reg + (4 * j), 0));
	OUT_BATCH_RELOC(lvl->faces[j].offset, t->mt->bo, lvl->faces[j].offset,
			RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
   }
   END_BATCH();
}
示例#5
0
void r200EmitMaxVtxIndex(r200ContextPtr rmesa, int count)
{
   BATCH_LOCALS(&rmesa->radeon);

   BEGIN_BATCH_NO_AUTOSTATE(2);
   OUT_BATCH(CP_PACKET0(R200_SE_VF_MAX_VTX_INDX, 0));
   OUT_BATCH(count);
   END_BATCH();
}
示例#6
0
static void radeonEmitScissor(r100ContextPtr rmesa)
{
    BATCH_LOCALS(&rmesa->radeon);
    if (rmesa->radeon.state.scissor.enabled) {
        BEGIN_BATCH(6);
        OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 0));
        OUT_BATCH(rmesa->hw.ctx.cmd[CTX_PP_CNTL] | RADEON_SCISSOR_ENABLE);
        OUT_BATCH(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
        OUT_BATCH((rmesa->radeon.state.scissor.rect.y1 << 16) |
                  rmesa->radeon.state.scissor.rect.x1);
        OUT_BATCH(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
        OUT_BATCH(((rmesa->radeon.state.scissor.rect.y2) << 16) |
                  (rmesa->radeon.state.scissor.rect.x2));
        END_BATCH();
    } else {
        BEGIN_BATCH(2);
        OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 0));
        OUT_BATCH(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ~RADEON_SCISSOR_ENABLE);
        END_BATCH();
    }
}
示例#7
0
static void r100_emit_query_finish(radeonContextPtr radeon)
{
   BATCH_LOCALS(radeon);
   struct radeon_query_object *query = radeon->query.current;

   BEGIN_BATCH_NO_AUTOSTATE(4);
   OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZPASS_ADDR, 0));
   OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
   END_BATCH();
   query->curr_offset += sizeof(uint32_t);
   assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
   query->emitted_begin = GL_FALSE;
}
/* =============================================================
 * State initialization
 */
static int cmdpkt( r100ContextPtr rmesa, int id ) 
{
   drm_radeon_cmd_header_t h;

   if (rmesa->radeon.radeonScreen->kernel_mm) {
     return CP_PACKET0(packet[id].start, packet[id].len - 1);
   } else {
     h.i = 0;
     h.packet.cmd_type = RADEON_CMD_PACKET;
     h.packet.packet_id = id;
   }
   return h.i;
}
示例#9
0
static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t* dev_priv,
						drm_radeon_cmd_buffer_t* cmdbuf,
						drm_r300_cmd_header_t header)
{
	int reg;
	int sz;
	int i;
	int values[64];
	RING_LOCALS;

	sz = header.packet0.count;
	reg = (header.packet0.reghi << 8) | header.packet0.reglo;
	
	if((sz>64)||(sz<0)){
		DRM_ERROR("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n", reg, sz);
		return DRM_ERR(EINVAL);
		}
	for(i=0;i<sz;i++){
		values[i]=((int __user*)cmdbuf->buf)[i];
		switch(r300_reg_flags[(reg>>2)+i]){
		case MARK_SAFE:
			break;
		case MARK_CHECK_OFFSET:
			if(r300_check_offset(dev_priv, (u32)values[i])){
				DRM_ERROR("Offset failed range check (reg=%04x sz=%d)\n", reg, sz);
				return DRM_ERR(EINVAL);
				}
			break;
		default:
			DRM_ERROR("Register %04x failed check as flag=%02x\n", reg+i*4, r300_reg_flags[(reg>>2)+i]);
			return DRM_ERR(EINVAL);
			}
		}
		
	BEGIN_RING(1+sz);
	OUT_RING( CP_PACKET0( reg, sz-1 ) );
	OUT_RING_TABLE( values, sz );
	ADVANCE_RING();

	cmdbuf->buf += sz*4;
	cmdbuf->bufsz -= sz*4;

	return 0;
}
示例#10
0
/**
 * Emits a packet0 setting arbitrary registers.
 * Called by r300_do_cp_cmdbuf.
 *
 * Note that checks are performed on contents and addresses of the registers
 */
static __inline__ int r300_emit_packet0(drm_radeon_private_t* dev_priv,
						drm_radeon_cmd_buffer_t* cmdbuf,
						drm_r300_cmd_header_t header)
{
	int reg;
	int sz;
	RING_LOCALS;

	sz = header.packet0.count;
	reg = (header.packet0.reghi << 8) | header.packet0.reglo;

	if (!sz)
		return 0;

	if (sz*4 > cmdbuf->bufsz)
		return DRM_ERR(EINVAL);
		
	if (reg+sz*4 >= 0x10000){
		DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg, sz);
		return DRM_ERR(EINVAL);
		}

	if(r300_check_range(reg, sz)){
		/* go and check everything */
		return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf, header);
		}
	/* the rest of the data is safe to emit, whatever the values the user passed */

	BEGIN_RING(1+sz);
	OUT_RING( CP_PACKET0( reg, sz-1 ) );
	OUT_RING_TABLE( (int __user*)cmdbuf->buf, sz );
	ADVANCE_RING();

	cmdbuf->buf += sz*4;
	cmdbuf->bufsz -= sz*4;

	return 0;
}
/* Initialize the context's hardware state.
 */
void radeonInitState( r100ContextPtr rmesa )
{
   struct gl_context *ctx = rmesa->radeon.glCtx;
   GLuint i;

   rmesa->radeon.Fallback = 0;


   rmesa->radeon.hw.max_state_size = 0;

#define ALLOC_STATE_IDX( ATOM, CHK, SZ, NM, FLAG, IDX )		\
   do {								\
      rmesa->hw.ATOM.cmd_size = SZ;				\
      rmesa->hw.ATOM.cmd = (GLuint *)CALLOC(SZ * sizeof(int));	\
      rmesa->hw.ATOM.lastcmd = (GLuint *)CALLOC(SZ * sizeof(int)); \
      rmesa->hw.ATOM.name = NM;						\
      rmesa->hw.ATOM.is_tcl = FLAG;					\
      rmesa->hw.ATOM.check = check_##CHK;				\
      rmesa->hw.ATOM.dirty = GL_TRUE;					\
      rmesa->hw.ATOM.idx = IDX;					\
      rmesa->radeon.hw.max_state_size += SZ * sizeof(int);		\
   } while (0)

#define ALLOC_STATE( ATOM, CHK, SZ, NM, FLAG )		\
   ALLOC_STATE_IDX(ATOM, CHK, SZ, NM, FLAG, 0)

   /* Allocate state buffers:
    */
   ALLOC_STATE( ctx, always_add4, CTX_STATE_SIZE, "CTX/context", 0 );
   rmesa->hw.ctx.emit = ctx_emit_cs;
   rmesa->hw.ctx.check = check_always_ctx;
   ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 );
   ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 );
   ALLOC_STATE( vpt, always, VPT_STATE_SIZE, "VPT/viewport", 0 );
   ALLOC_STATE( set, always, SET_STATE_SIZE, "SET/setup", 0 );
   ALLOC_STATE( msc, always, MSC_STATE_SIZE, "MSC/misc", 0 );
   ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 );
   ALLOC_STATE( tcl, always, TCL_STATE_SIZE, "TCL/tcl", 1 );
   ALLOC_STATE( mtl, tcl_lighting, MTL_STATE_SIZE, "MTL/material", 1 );
   ALLOC_STATE( grd, always_add2, GRD_STATE_SIZE, "GRD/guard-band", 1 );
   ALLOC_STATE( fog, fog_add4, FOG_STATE_SIZE, "FOG/fog", 1 );
   ALLOC_STATE( glt, tcl_lighting_add4, GLT_STATE_SIZE, "GLT/light-global", 1 );
   ALLOC_STATE( eye, tcl_lighting_add4, EYE_STATE_SIZE, "EYE/eye-vector", 1 );
   ALLOC_STATE_IDX( tex[0], tex0_mm, TEX_STATE_SIZE, "TEX/tex-0", 0, 0);
   ALLOC_STATE_IDX( tex[1], tex1_mm, TEX_STATE_SIZE, "TEX/tex-1", 0, 1);
   ALLOC_STATE_IDX( tex[2], tex2_mm, TEX_STATE_SIZE, "TEX/tex-2", 0, 2);
   ALLOC_STATE( mat[0], tcl_add4, MAT_STATE_SIZE, "MAT/modelproject", 1 );
   ALLOC_STATE( mat[1], tcl_eyespace_or_fog_add4, MAT_STATE_SIZE, "MAT/modelview", 1 );
   ALLOC_STATE( mat[2], tcl_eyespace_or_lighting_add4, MAT_STATE_SIZE, "MAT/it-modelview", 1 );
   ALLOC_STATE( mat[3], tcl_tex0_add4, MAT_STATE_SIZE, "MAT/texmat0", 1 );
   ALLOC_STATE( mat[4], tcl_tex1_add4, MAT_STATE_SIZE, "MAT/texmat1", 1 );
   ALLOC_STATE( mat[5], tcl_tex2_add4, MAT_STATE_SIZE, "MAT/texmat2", 1 );
   ALLOC_STATE( lit[0], tcl_lit0_add6, LIT_STATE_SIZE, "LIT/light-0", 1 );
   ALLOC_STATE( lit[1], tcl_lit1_add6, LIT_STATE_SIZE, "LIT/light-1", 1 );
   ALLOC_STATE( lit[2], tcl_lit2_add6, LIT_STATE_SIZE, "LIT/light-2", 1 );
   ALLOC_STATE( lit[3], tcl_lit3_add6, LIT_STATE_SIZE, "LIT/light-3", 1 );
   ALLOC_STATE( lit[4], tcl_lit4_add6, LIT_STATE_SIZE, "LIT/light-4", 1 );
   ALLOC_STATE( lit[5], tcl_lit5_add6, LIT_STATE_SIZE, "LIT/light-5", 1 );
   ALLOC_STATE( lit[6], tcl_lit6_add6, LIT_STATE_SIZE, "LIT/light-6", 1 );
   ALLOC_STATE( lit[7], tcl_lit7_add6, LIT_STATE_SIZE, "LIT/light-7", 1 );
   ALLOC_STATE( ucp[0], tcl_ucp0_add4, UCP_STATE_SIZE, "UCP/userclip-0", 1 );
   ALLOC_STATE( ucp[1], tcl_ucp1_add4, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
   ALLOC_STATE( ucp[2], tcl_ucp2_add4, UCP_STATE_SIZE, "UCP/userclip-2", 1 );
   ALLOC_STATE( ucp[3], tcl_ucp3_add4, UCP_STATE_SIZE, "UCP/userclip-3", 1 );
   ALLOC_STATE( ucp[4], tcl_ucp4_add4, UCP_STATE_SIZE, "UCP/userclip-4", 1 );
   ALLOC_STATE( ucp[5], tcl_ucp5_add4, UCP_STATE_SIZE, "UCP/userclip-5", 1 );
   ALLOC_STATE( stp, always, STP_STATE_SIZE, "STP/stp", 0 );

   for (i = 0; i < 3; i++) {
      rmesa->hw.tex[i].emit = tex_emit_cs;
   }
   ALLOC_STATE_IDX( cube[0], cube0_mm, CUBE_STATE_SIZE, "CUBE/cube-0", 0, 0 );
   ALLOC_STATE_IDX( cube[1], cube1_mm, CUBE_STATE_SIZE, "CUBE/cube-1", 0, 1 );
   ALLOC_STATE_IDX( cube[2], cube2_mm, CUBE_STATE_SIZE, "CUBE/cube-2", 0, 2 );
   for (i = 0; i < 3; i++)
       rmesa->hw.cube[i].emit = cube_emit_cs;

   ALLOC_STATE_IDX( txr[0], txr0, TXR_STATE_SIZE, "TXR/txr-0", 0, 0 );
   ALLOC_STATE_IDX( txr[1], txr1, TXR_STATE_SIZE, "TXR/txr-1", 0, 1 );
   ALLOC_STATE_IDX( txr[2], txr2, TXR_STATE_SIZE, "TXR/txr-2", 0, 2 );

   radeonSetUpAtomList( rmesa );

   /* Fill in the packet headers:
    */
   rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_MISC);
   rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CNTL);
   rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(rmesa, RADEON_EMIT_RB3D_COLORPITCH);
   rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RE_LINE_PATTERN);
   rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_SE_LINE_WIDTH);
   rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RB3D_STENCILREFMASK);
   rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_VPORT_XSCALE);
   rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_CNTL);
   rmesa->hw.set.cmd[SET_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_SE_CNTL_STATUS);
   rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RE_MISC);
   rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TXFILTER_0);
   rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_BORDER_COLOR_0);
   rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TXFILTER_1);
   rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_BORDER_COLOR_1);
   rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TXFILTER_2);
   rmesa->hw.tex[2].cmd[TEX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_BORDER_COLOR_2);
   rmesa->hw.cube[0].cmd[CUBE_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_FACES_0);
   rmesa->hw.cube[0].cmd[CUBE_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_OFFSETS_T0);
   rmesa->hw.cube[1].cmd[CUBE_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_FACES_1);
   rmesa->hw.cube[1].cmd[CUBE_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_OFFSETS_T1);
   rmesa->hw.cube[2].cmd[CUBE_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_FACES_2);
   rmesa->hw.cube[2].cmd[CUBE_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_OFFSETS_T2);
   rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_ZBIAS_FACTOR);
   rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT);
   rmesa->hw.mtl.cmd[MTL_CMD_0] = 
      cmdpkt(rmesa, RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED);
   rmesa->hw.txr[0].cmd[TXR_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TEX_SIZE_0);
   rmesa->hw.txr[1].cmd[TXR_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TEX_SIZE_1);
   rmesa->hw.txr[2].cmd[TXR_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TEX_SIZE_2);
   rmesa->hw.grd.cmd[GRD_CMD_0] = 
      cmdscl( RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, 1, 4 );
   rmesa->hw.fog.cmd[FOG_CMD_0] = 
      cmdvec( RADEON_VS_FOG_PARAM_ADDR, 1, 4 );
   rmesa->hw.glt.cmd[GLT_CMD_0] = 
      cmdvec( RADEON_VS_GLOBAL_AMBIENT_ADDR, 1, 4 );
   rmesa->hw.eye.cmd[EYE_CMD_0] = 
      cmdvec( RADEON_VS_EYE_VECTOR_ADDR, 1, 4 );

   for (i = 0 ; i < 6; i++) {
      rmesa->hw.mat[i].cmd[MAT_CMD_0] = 
	 cmdvec( RADEON_VS_MATRIX_0_ADDR + i*4, 1, 16);
   }

   for (i = 0 ; i < 8; i++) {
      rmesa->hw.lit[i].cmd[LIT_CMD_0] = 
	 cmdvec( RADEON_VS_LIGHT_AMBIENT_ADDR + i, 8, 24 );
      rmesa->hw.lit[i].cmd[LIT_CMD_1] = 
	 cmdscl( RADEON_SS_LIGHT_DCD_ADDR + i, 8, 6 );
   }

   for (i = 0 ; i < 6; i++) {
      rmesa->hw.ucp[i].cmd[UCP_CMD_0] = 
	 cmdvec( RADEON_VS_UCP_ADDR + i, 1, 4 );
   }

   rmesa->hw.stp.cmd[STP_CMD_0] = CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0);
   rmesa->hw.stp.cmd[STP_DATA_0] = 0;
   rmesa->hw.stp.cmd[STP_CMD_1] = CP_PACKET0_ONE(RADEON_RE_STIPPLE_DATA, 31);

   rmesa->hw.grd.emit = scl_emit;
   rmesa->hw.fog.emit = vec_emit;
   rmesa->hw.glt.emit = vec_emit;
   rmesa->hw.eye.emit = vec_emit;
   for (i = 0; i < 6; i++)
      rmesa->hw.mat[i].emit = vec_emit;

   for (i = 0; i < 8; i++)
      rmesa->hw.lit[i].emit = lit_emit;

   for (i = 0; i < 6; i++)
      rmesa->hw.ucp[i].emit = vec_emit;

   rmesa->last_ReallyEnabled = -1;

   /* Initial Harware state:
    */
   rmesa->hw.ctx.cmd[CTX_PP_MISC] = (RADEON_ALPHA_TEST_PASS |
				     RADEON_CHROMA_FUNC_FAIL |
				     RADEON_CHROMA_KEY_NEAREST |
				     RADEON_SHADOW_FUNC_EQUAL |
				     RADEON_SHADOW_PASS_1 /*|
				     RADEON_RIGHT_HAND_CUBE_OGL */);

   rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (RADEON_FOG_VERTEX |
					  /* this bit unused for vertex fog */
					  RADEON_FOG_USE_DEPTH);

   rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000;

   rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (RADEON_COMB_FCN_ADD_CLAMP |
					    RADEON_SRC_BLEND_GL_ONE |
					    RADEON_DST_BLEND_GL_ZERO );

   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (RADEON_Z_TEST_LESS |
					       RADEON_STENCIL_TEST_ALWAYS |
					       RADEON_STENCIL_FAIL_KEEP |
					       RADEON_STENCIL_ZPASS_KEEP |
					       RADEON_STENCIL_ZFAIL_KEEP |
					       RADEON_Z_WRITE_ENABLE);

   if (rmesa->using_hyperz) {
       rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_COMPRESSION_ENABLE |
						   RADEON_Z_DECOMPRESSION_ENABLE;
      if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
	 /* works for q3, but slight rendering errors with glxgears ? */
/*	 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_HIERARCHY_ENABLE;*/
	 /* need this otherwise get lots of lockups with q3 ??? */
	 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_FORCE_Z_DIRTY;
      } 
   }

   rmesa->hw.ctx.cmd[CTX_PP_CNTL] = (RADEON_SCISSOR_ENABLE |
				     RADEON_ANTI_ALIAS_NONE);

   rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = (RADEON_PLANE_MASK_ENABLE |
				       RADEON_ZBLOCK16);

   switch ( driQueryOptioni( &rmesa->radeon.optionCache, "dither_mode" ) ) {
   case DRI_CONF_DITHER_XERRORDIFFRESET:
      rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_INIT;
      break;
   case DRI_CONF_DITHER_ORDERED:
      rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_SCALE_DITHER_ENABLE;
      break;
   }
   if ( driQueryOptioni( &rmesa->radeon.optionCache, "round_mode" ) ==
	DRI_CONF_ROUND_ROUND )
      rmesa->radeon.state.color.roundEnable = RADEON_ROUND_ENABLE;
   else
      rmesa->radeon.state.color.roundEnable = 0;
   if ( driQueryOptioni (&rmesa->radeon.optionCache, "color_reduction" ) ==
	DRI_CONF_COLOR_REDUCTION_DITHER )
      rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE;
   else
      rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable;


   rmesa->hw.set.cmd[SET_SE_CNTL] = (RADEON_FFACE_CULL_CCW |
				     RADEON_BFACE_SOLID |
				     RADEON_FFACE_SOLID |
/*  			     RADEON_BADVTX_CULL_DISABLE | */
				     RADEON_FLAT_SHADE_VTX_LAST |
				     RADEON_DIFFUSE_SHADE_GOURAUD |
				     RADEON_ALPHA_SHADE_GOURAUD |
				     RADEON_SPECULAR_SHADE_GOURAUD |
				     RADEON_FOG_SHADE_GOURAUD |
				     RADEON_VPORT_XY_XFORM_ENABLE |
				     RADEON_VPORT_Z_XFORM_ENABLE |
				     RADEON_VTX_PIX_CENTER_OGL |
				     RADEON_ROUND_MODE_TRUNC |
				     RADEON_ROUND_PREC_8TH_PIX);

   rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] =
#ifdef MESA_BIG_ENDIAN
					    RADEON_VC_32BIT_SWAP;
#else
  					    RADEON_VC_NO_SWAP;
#endif

   if (!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
     rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] |= RADEON_TCL_BYPASS;
   }

   rmesa->hw.set.cmd[SET_SE_COORDFMT] = (
      RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
      RADEON_TEX1_W_ROUTING_USE_Q1);


   rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = ((1 << 16) | 0xffff);

   rmesa->hw.lin.cmd[LIN_RE_LINE_STATE] = 
      ((0 << RADEON_LINE_CURRENT_PTR_SHIFT) |
       (1 << RADEON_LINE_CURRENT_COUNT_SHIFT));

   rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (1 << 4);

   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] = 
      ((0x00 << RADEON_STENCIL_REF_SHIFT) |
       (0xff << RADEON_STENCIL_MASK_SHIFT) |
       (0xff << RADEON_STENCIL_WRITEMASK_SHIFT));

   rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = RADEON_ROP_COPY;
   rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = 0xffffffff;

   rmesa->hw.msc.cmd[MSC_RE_MISC] = 
      ((0 << RADEON_STIPPLE_X_OFFSET_SHIFT) |
       (0 << RADEON_STIPPLE_Y_OFFSET_SHIFT) |
       RADEON_STIPPLE_BIG_BIT_ORDER);

   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = 0x00000000;
   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = 0x00000000;
   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE]  = 0x00000000;
   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = 0x00000000;
   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = 0x00000000;
   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = 0x00000000;

   for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
      rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL;
      rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT] = 
	  (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
	   RADEON_TXFORMAT_PERSPECTIVE_ENABLE |
	   (i << 24) | /* This is one of RADEON_TXFORMAT_ST_ROUTE_STQ[012] */
	   (2 << RADEON_TXFORMAT_WIDTH_SHIFT) |
	   (2 << RADEON_TXFORMAT_HEIGHT_SHIFT));

      /* Initialize the texture offset to the start of the card texture heap */
      //      rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET] =
      //	  rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];

      rmesa->hw.tex[i].cmd[TEX_PP_BORDER_COLOR] = 0;
      rmesa->hw.tex[i].cmd[TEX_PP_TXCBLEND] =  
	  (RADEON_COLOR_ARG_A_ZERO |
	   RADEON_COLOR_ARG_B_ZERO |
	   RADEON_COLOR_ARG_C_CURRENT_COLOR |
	   RADEON_BLEND_CTL_ADD |
	   RADEON_SCALE_1X |
	   RADEON_CLAMP_TX);
      rmesa->hw.tex[i].cmd[TEX_PP_TXABLEND] = 
	  (RADEON_ALPHA_ARG_A_ZERO |
	   RADEON_ALPHA_ARG_B_ZERO |
	   RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
	   RADEON_BLEND_CTL_ADD |
	   RADEON_SCALE_1X |
	   RADEON_CLAMP_TX);
      rmesa->hw.tex[i].cmd[TEX_PP_TFACTOR] = 0;

      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_FACES] = 0;
      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_0] =
	  rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_1] =
	  rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_2] =
	  rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_3] =
	  rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
      rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_4] =
	  rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP];
   }

   /* Can only add ST1 at the time of doing some multitex but can keep
    * it after that.  Errors if DIFFUSE is missing.
    */
   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = 
      (RADEON_TCL_VTX_Z0 |
       RADEON_TCL_VTX_W0 |
       RADEON_TCL_VTX_PK_DIFFUSE
	 );	/* need to keep this uptodate */
						   
   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] =
      ( RADEON_TCL_COMPUTE_XYZW 	|
	(RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
	(RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
	(RADEON_TCL_TEX_INPUT_TEX_2 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));


   /* XXX */
   rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_0] = 
      ((MODEL << RADEON_MODELVIEW_0_SHIFT) |
       (MODEL_IT << RADEON_IT_MODELVIEW_0_SHIFT));

   rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_1] = 
      ((MODEL_PROJ << RADEON_MODELPROJECT_0_SHIFT) |
       (TEXMAT_0 << RADEON_TEXMAT_0_SHIFT) |
       (TEXMAT_1 << RADEON_TEXMAT_1_SHIFT) |
       (TEXMAT_2 << RADEON_TEXMAT_2_SHIFT));

   rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = 
      (RADEON_UCP_IN_CLIP_SPACE |
       RADEON_CULL_FRONT_IS_CCW);

   rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = 0; 

   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = 
      (RADEON_SPECULAR_LIGHTS |
       RADEON_DIFFUSE_SPECULAR_COMBINE |
       RADEON_LOCAL_LIGHT_VEC_GL |
       (RADEON_LM_SOURCE_STATE_MULT << RADEON_EMISSIVE_SOURCE_SHIFT) |
       (RADEON_LM_SOURCE_STATE_MULT << RADEON_AMBIENT_SOURCE_SHIFT) |
       (RADEON_LM_SOURCE_STATE_MULT << RADEON_DIFFUSE_SOURCE_SHIFT) |
       (RADEON_LM_SOURCE_STATE_MULT << RADEON_SPECULAR_SOURCE_SHIFT));

   for (i = 0 ; i < 8; i++) {
      struct gl_light *l = &ctx->Light.Light[i];
      GLenum p = GL_LIGHT0 + i;
      *(float *)&(rmesa->hw.lit[i].cmd[LIT_RANGE_CUTOFF]) = FLT_MAX;

      ctx->Driver.Lightfv( ctx, p, GL_AMBIENT, l->Ambient );
      ctx->Driver.Lightfv( ctx, p, GL_DIFFUSE, l->Diffuse );
      ctx->Driver.Lightfv( ctx, p, GL_SPECULAR, l->Specular );
      ctx->Driver.Lightfv( ctx, p, GL_POSITION, NULL );
      ctx->Driver.Lightfv( ctx, p, GL_SPOT_DIRECTION, NULL );
      ctx->Driver.Lightfv( ctx, p, GL_SPOT_EXPONENT, &l->SpotExponent );
      ctx->Driver.Lightfv( ctx, p, GL_SPOT_CUTOFF, &l->SpotCutoff );
      ctx->Driver.Lightfv( ctx, p, GL_CONSTANT_ATTENUATION,
			   &l->ConstantAttenuation );
      ctx->Driver.Lightfv( ctx, p, GL_LINEAR_ATTENUATION, 
			   &l->LinearAttenuation );
      ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION, 
		     &l->QuadraticAttenuation );
      *(float *)&(rmesa->hw.lit[i].cmd[LIT_ATTEN_XXX]) = 0.0;
   }

   ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT, 
			     ctx->Light.Model.Ambient );

   TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );

   for (i = 0 ; i < 6; i++) {
      ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, NULL );
   }

   ctx->Driver.Fogfv( ctx, GL_FOG_MODE, NULL );
   ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
   ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
   ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
   ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
   ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, NULL );
   
   rmesa->hw.grd.cmd[GRD_VERT_GUARD_CLIP_ADJ] = IEEE_ONE;
   rmesa->hw.grd.cmd[GRD_VERT_GUARD_DISCARD_ADJ] = IEEE_ONE;
   rmesa->hw.grd.cmd[GRD_HORZ_GUARD_CLIP_ADJ] = IEEE_ONE;
   rmesa->hw.grd.cmd[GRD_HORZ_GUARD_DISCARD_ADJ] = IEEE_ONE;

   rmesa->hw.eye.cmd[EYE_X] = 0;
   rmesa->hw.eye.cmd[EYE_Y] = 0;
   rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE;
   rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE;

   radeon_init_query_stateobj(&rmesa->radeon, R100_QUERYOBJ_CMDSIZE);
   rmesa->radeon.query.queryobj.cmd[R100_QUERYOBJ_CMD_0] = CP_PACKET0(RADEON_RB3D_ZPASS_DATA, 0);
   rmesa->radeon.query.queryobj.cmd[R100_QUERYOBJ_DATA_0] = 0;
     
   rmesa->radeon.hw.all_dirty = GL_TRUE;

   rcommonInitCmdBuf(&rmesa->radeon);
}
static void ctx_emit_cs(struct gl_context *ctx, struct radeon_state_atom *atom)
{
   r100ContextPtr r100 = R100_CONTEXT(ctx);
   BATCH_LOCALS(&r100->radeon);
   struct radeon_renderbuffer *rrb, *drb;
   uint32_t cbpitch = 0;
   uint32_t zbpitch = 0;
   uint32_t dwords = atom->check(ctx, atom);
   uint32_t depth_fmt;

   rrb = radeon_get_colorbuffer(&r100->radeon);
   if (!rrb || !rrb->bo) {
      fprintf(stderr, "no rrb\n");
      return;
   }

   atom->cmd[CTX_RB3D_CNTL] &= ~(0xf << 10);
   if (rrb->cpp == 4)
	atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB8888;
   else switch (rrb->base.Base.Format) {
   case MESA_FORMAT_RGB565:
	atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_RGB565;
	break;
   case MESA_FORMAT_ARGB4444:
	atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB4444;
	break;
   case MESA_FORMAT_ARGB1555:
	atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB1555;
	break;
   default:
	_mesa_problem(ctx, "unexpected format in ctx_emit_cs()");
   }

   cbpitch = (rrb->pitch / rrb->cpp);
   if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE)
       cbpitch |= R200_COLOR_TILE_ENABLE;
   if (rrb->bo->flags & RADEON_BO_FLAGS_MICRO_TILE)
       cbpitch |= RADEON_COLOR_MICROTILE_ENABLE;

   drb = radeon_get_depthbuffer(&r100->radeon);
   if (drb) {
     zbpitch = (drb->pitch / drb->cpp);
     if (drb->cpp == 4)
        depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
     else
        depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
     atom->cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_DEPTH_FORMAT_MASK;
     atom->cmd[CTX_RB3D_ZSTENCILCNTL] |= depth_fmt;
     
   }

   BEGIN_BATCH_NO_AUTOSTATE(dwords);

   /* In the CS case we need to split this up */
   OUT_BATCH(CP_PACKET0(packet[0].start, 3));
   OUT_BATCH_TABLE((atom->cmd + 1), 4);

   if (drb) {
     OUT_BATCH(CP_PACKET0(RADEON_RB3D_DEPTHOFFSET, 0));
     OUT_BATCH_RELOC(0, drb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);

     OUT_BATCH(CP_PACKET0(RADEON_RB3D_DEPTHPITCH, 0));
     OUT_BATCH(zbpitch);
   }

   OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZSTENCILCNTL, 0));
   OUT_BATCH(atom->cmd[CTX_RB3D_ZSTENCILCNTL]);
   OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 1));
   OUT_BATCH(atom->cmd[CTX_PP_CNTL]);
   OUT_BATCH(atom->cmd[CTX_RB3D_CNTL]);

   if (rrb) {
     OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLOROFFSET, 0));
     OUT_BATCH_RELOC(rrb->draw_offset, rrb->bo, rrb->draw_offset, 0, RADEON_GEM_DOMAIN_VRAM, 0);

     OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
     OUT_BATCH_RELOC(cbpitch, rrb->bo, cbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0);
   }

   // if (atom->cmd_size == CTX_STATE_SIZE_NEWDRM) {
   //   OUT_BATCH_TABLE((atom->cmd + 14), 4);
   // }

   END_BATCH();
   BEGIN_BATCH_NO_AUTOSTATE(4);
   OUT_BATCH(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
   OUT_BATCH(0);
   OUT_BATCH(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
   if (rrb) {
       OUT_BATCH(((rrb->base.Base.Width - 1) << RADEON_RE_WIDTH_SHIFT) |
                 ((rrb->base.Base.Height - 1) << RADEON_RE_HEIGHT_SHIFT));
   } else {
       OUT_BATCH(0);
   }
   END_BATCH();
}
/* =============================================================
 * State initialization
 */
static int cmdpkt( r100ContextPtr rmesa, int id ) 
{
   return CP_PACKET0(packet[id].start, packet[id].len - 1);
}
示例#14
0
/**
 * Parses and validates a user-supplied command buffer and emits appropriate
 * commands on the DMA ring buffer.
 * Called by the ioctl handler function radeon_cp_cmdbuf.
 */
int r300_do_cp_cmdbuf(drm_device_t* dev,
			  DRMFILE filp,
		      drm_file_t* filp_priv,
		      drm_radeon_cmd_buffer_t* cmdbuf)
{
	drm_radeon_private_t *dev_priv = dev->dev_private;
        drm_device_dma_t *dma = dev->dma;
        drm_buf_t *buf = NULL;
	int emit_dispatch_age = 0;
	int ret = 0;

	DRM_DEBUG("\n");

	/* See the comment above r300_emit_begin3d for why this call must be here,
	 * and what the cleanup gotos are for. */
	r300_pacify(dev_priv);

	if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
		ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
		if (ret)
			goto cleanup;
		}

	while(cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
		int idx;
		drm_r300_cmd_header_t header;

		header.u = *(unsigned int *)cmdbuf->buf;

		cmdbuf->buf += sizeof(header);
		cmdbuf->bufsz -= sizeof(header);

		switch(header.header.cmd_type) {
		case R300_CMD_PACKET0: 
			DRM_DEBUG("R300_CMD_PACKET0\n");
			ret = r300_emit_packet0(dev_priv, cmdbuf, header);
			if (ret) {
				DRM_ERROR("r300_emit_packet0 failed\n");
				goto cleanup;
				}
			break;

		case R300_CMD_VPU:
			DRM_DEBUG("R300_CMD_VPU\n");
			ret = r300_emit_vpu(dev_priv, cmdbuf, header);
			if (ret) {
				DRM_ERROR("r300_emit_vpu failed\n");
				goto cleanup;
				}
			break;

		case R300_CMD_PACKET3:
			DRM_DEBUG("R300_CMD_PACKET3\n");
			ret = r300_emit_packet3(dev_priv, cmdbuf, header);
			if (ret) {
				DRM_ERROR("r300_emit_packet3 failed\n");
				goto cleanup;
				}
			break;

		case R300_CMD_END3D:
			DRM_DEBUG("R300_CMD_END3D\n");
			/* TODO: 
				Ideally userspace driver should not need to issue this call, 
				i.e. the drm driver should issue it automatically and prevent
				lockups.
				
				In practice, we do not understand why this call is needed and what
				it does (except for some vague guesses that it has to do with cache
				coherence) and so the user space driver does it. 
				
				Once we are sure which uses prevent lockups the code could be moved
				into the kernel and the userspace driver will not
				need to use this command.

				Note that issuing this command does not hurt anything
				except, possibly, performance */
			r300_pacify(dev_priv);
			break;

		case R300_CMD_CP_DELAY:
			/* simple enough, we can do it here */
			DRM_DEBUG("R300_CMD_CP_DELAY\n");
			{
				int i;
				RING_LOCALS;

				BEGIN_RING(header.delay.count);
				for(i=0;i<header.delay.count;i++)
					OUT_RING(RADEON_CP_PACKET2);
				ADVANCE_RING();
			}
			break;

		case R300_CMD_DMA_DISCARD:
			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
            		idx = header.dma.buf_idx;
            		if (idx < 0 || idx >= dma->buf_count) {
                		DRM_ERROR("buffer index %d (of %d max)\n",
                      			idx, dma->buf_count - 1);
				ret = DRM_ERR(EINVAL);
                		goto cleanup;
            			}

	                buf = dma->buflist[idx];
            		if (buf->filp != filp || buf->pending) {
                		DRM_ERROR("bad buffer %p %p %d\n",
                      		buf->filp, filp, buf->pending);
                		ret = DRM_ERR(EINVAL);
				goto cleanup;
            			}

			emit_dispatch_age = 1;
			r300_discard_buffer(dev, buf);
            		break;

		case R300_CMD_WAIT:
			/* simple enough, we can do it here */
			DRM_DEBUG("R300_CMD_WAIT\n");
			if(header.wait.flags==0)break; /* nothing to do */

			{
				RING_LOCALS;

				BEGIN_RING(2);
				OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );
				OUT_RING( (header.wait.flags & 0xf)<<14 );
				ADVANCE_RING();
			}
			break;

		default:
			DRM_ERROR("bad cmd_type %i at %p\n",
			          header.header.cmd_type,
				  cmdbuf->buf - sizeof(header));
			ret = DRM_ERR(EINVAL);
			goto cleanup;
			}
	}

	DRM_DEBUG("END\n");

cleanup:
	r300_pacify(dev_priv);

	/* We emit the vertex buffer age here, outside the pacifier "brackets"
	 * for two reasons:
	 *  (1) This may coalesce multiple age emissions into a single one and
	 *  (2) more importantly, some chips lock up hard when scratch registers
	 *      are written inside the pacifier bracket.
	 */
	if (emit_dispatch_age) {
		RING_LOCALS;

		/* Emit the vertex buffer age */
		BEGIN_RING(2);
		RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
		ADVANCE_RING();
		}

	COMMIT_RING();

	return ret;
}
示例#15
0
/**
 * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
 * buffer, starting with index n.
 */
static int r300_emit_cliprects(drm_radeon_private_t* dev_priv,
			       drm_radeon_cmd_buffer_t* cmdbuf,
			       int n)
{
	drm_clip_rect_t box;
	int nr;
	int i;
	RING_LOCALS;

	nr = cmdbuf->nbox - n;
	if (nr > R300_SIMULTANEOUS_CLIPRECTS)
		nr = R300_SIMULTANEOUS_CLIPRECTS;

	DRM_DEBUG("%i cliprects\n", nr);

	if (nr) {
		BEGIN_RING(6 + nr*2);
		OUT_RING( CP_PACKET0( R300_RE_CLIPRECT_TL_0, nr*2 - 1 ) );

		for(i = 0; i < nr; ++i) {
			if (DRM_COPY_FROM_USER_UNCHECKED(&box, &cmdbuf->boxes[n+i], sizeof(box))) {
				DRM_ERROR("copy cliprect faulted\n");
				return DRM_ERR(EFAULT);
			}

			box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
			box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
			box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
			box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;

			OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
					(box.y1 << R300_CLIPRECT_Y_SHIFT));
			OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
					(box.y2 << R300_CLIPRECT_Y_SHIFT));
		}

		OUT_RING_REG( R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr-1] );

		/* TODO/SECURITY: Force scissors to a safe value, otherwise the
		* client might be able to trample over memory.
		* The impact should be very limited, but I'd rather be safe than
		* sorry.
		*/
		OUT_RING( CP_PACKET0( R300_RE_SCISSORS_TL, 1 ) );
		OUT_RING( 0 );
		OUT_RING( R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK );
		ADVANCE_RING();
		} else {
		/* Why we allow zero cliprect rendering:
		 * There are some commands in a command buffer that must be submitted
		 * even when there are no cliprects, e.g. DMA buffer discard
		 * or state setting (though state setting could be avoided by
		 * simulating a loss of context).
		 *
		 * Now since the cmdbuf interface is so chaotic right now (and is
		 * bound to remain that way for a bit until things settle down),
		 * it is basically impossible to filter out the commands that are
		 * necessary and those that aren't.
		 *
		 * So I choose the safe way and don't do any filtering at all;
		 * instead, I simply set up the engine so that all rendering
		 * can't produce any fragments.
		 */
		BEGIN_RING(2);
		OUT_RING_REG( R300_RE_CLIPRECT_CNTL, 0 );
		ADVANCE_RING();
		}

	return 0;
}