/** * Scan program instructions to update the program's InputsRead and * OutputsWritten fields. */ static void _slang_update_inputs_outputs(struct gl_program *prog) { GLuint i, j; GLuint maxAddrReg = 0; prog->InputsRead = 0x0; prog->OutputsWritten = 0x0; for (i = 0; i < prog->NumInstructions; i++) { const struct prog_instruction *inst = prog->Instructions + i; const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); for (j = 0; j < numSrc; j++) { if (inst->SrcReg[j].File == PROGRAM_INPUT) { prog->InputsRead |= 1 << inst->SrcReg[j].Index; } else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) { maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1)); } } if (inst->DstReg.File == PROGRAM_OUTPUT) { prog->OutputsWritten |= BITFIELD64_BIT(inst->DstReg.Index); if (inst->DstReg.RelAddr) { /* If the output attribute is indexed with relative addressing * we know that it must be a varying or texcoord such as * gl_TexCoord[i] = v; In this case, mark all the texcoords * or varying outputs as being written. It's not an error if * a vertex shader writes varying vars that aren't used by the * fragment shader. But it is an error for a fragment shader * to use varyings that are not written by the vertex shader. */ if (prog->Target == GL_VERTEX_PROGRAM_ARB) { if (inst->DstReg.Index == VERT_RESULT_TEX0) { /* mark all texcoord outputs as written */ const GLbitfield64 mask = BITFIELD64_RANGE(VERT_RESULT_TEX0, (VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS - 1)); prog->OutputsWritten |= mask; } else if (inst->DstReg.Index == VERT_RESULT_VAR0) { /* mark all generic varying outputs as written */ const GLbitfield64 mask = BITFIELD64_RANGE(VERT_RESULT_VAR0, (VERT_RESULT_VAR0 + MAX_VARYING - 1)); prog->OutputsWritten |= mask; } } } } else if (inst->DstReg.File == PROGRAM_ADDRESS) { maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1); } } prog->NumAddressRegs = maxAddrReg; }
/** * Set vertex state for SW TCL. The primary purpose of this function is to * determine in advance whether or not the hardware can / should do the * projection divide or Mesa should do it. */ void radeonChooseVertexState( struct gl_context *ctx ) { r100ContextPtr rmesa = R100_CONTEXT( ctx ); TNLcontext *tnl = TNL_CONTEXT(ctx); GLuint se_coord_fmt = rmesa->hw.set.cmd[SET_SE_COORDFMT]; GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide; se_coord_fmt &= ~(RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | RADEON_VTX_Z_PRE_MULT_1_OVER_W0 | RADEON_VTX_W0_IS_NOT_1_OVER_W0); /* We must ensure that we don't do _tnl_need_projected_coords while in a * rasterization fallback. As this function will be called again when we * leave a rasterization fallback, we can just skip it for now. */ if (rmesa->radeon.Fallback != 0) return; /* HW perspective divide is a win, but tiny vertex formats are a * bigger one. */ if ((0 == (tnl->render_inputs_bitset & (BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX) | BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)))) || twosided || unfilled) { rmesa->swtcl.needproj = GL_TRUE; se_coord_fmt |= (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | RADEON_VTX_Z_PRE_MULT_1_OVER_W0); } else { rmesa->swtcl.needproj = GL_FALSE; se_coord_fmt |= (RADEON_VTX_W0_IS_NOT_1_OVER_W0); } _tnl_need_projected_coords( ctx, rmesa->swtcl.needproj ); if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) { RADEON_STATECHANGE( rmesa, set ); rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt; } }
/** * Tell the tnl module how to build SWvertex objects for swrast. * We'll build the map[] array with that info and pass it to * _tnl_install_attrs(). */ static void setup_vertex_format(struct gl_context *ctx) { TNLcontext *tnl = TNL_CONTEXT(ctx); SScontext *swsetup = SWSETUP_CONTEXT(ctx); GLboolean intColors = !ctx->FragmentProgram._Current && !ctx->ATIFragmentShader._Enabled && ctx->RenderMode == GL_RENDER && CHAN_TYPE != GL_FLOAT; if (intColors != swsetup->intColors || tnl->render_inputs_bitset != swsetup->last_index_bitset) { GLbitfield64 index_bitset = tnl->render_inputs_bitset; struct tnl_attr_map map[_TNL_ATTRIB_MAX]; unsigned int i, e = 0; swsetup->intColors = intColors; EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, attrib[VARYING_SLOT_POS] ); if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR0)) { if (swsetup->intColors) EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4CHAN_4F_RGBA, color ); else EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4F, attrib[VARYING_SLOT_COL0]); } if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_4F, attrib[VARYING_SLOT_COL1]); } if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) { const GLint emit = ctx->FragmentProgram._Current ? EMIT_4F : EMIT_1F; EMIT_ATTR( _TNL_ATTRIB_FOG, emit, attrib[VARYING_SLOT_FOGC]); } if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) { if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) { EMIT_ATTR( _TNL_ATTRIB_TEX(i), EMIT_4F, attrib[VARYING_SLOT_TEX0 + i] ); } } } /* shader varying vars */ if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_GENERIC0, _TNL_NUM_GENERIC)) { for (i = 0; i < ctx->Const.MaxVarying; i++) { if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_GENERIC(i))) { EMIT_ATTR( _TNL_ATTRIB_GENERIC(i), VARYING_EMIT_STYLE, attrib[VARYING_SLOT_VAR0 + i] ); } } } if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE)) EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, pointSize ); _tnl_install_attrs( ctx, map, e, ctx->Viewport._WindowMap.m, sizeof(SWvertex) ); swsetup->last_index_bitset = index_bitset; } }
static void radeonSetVertexFormat( struct gl_context *ctx ) { r100ContextPtr rmesa = R100_CONTEXT( ctx ); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; GLbitfield64 index_bitset = tnl->render_inputs_bitset; int fmt_0 = 0; int offset = 0; /* Important: */ if ( VB->NdcPtr != NULL ) { VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; } else { VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr; } assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL ); rmesa->radeon.swtcl.vertex_attr_count = 0; /* EMIT_ATTR's must be in order as they tell t_vertex.c how to * build up a hardware vertex. */ if ( !rmesa->swtcl.needproj || (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX))) { /* for projtex */ EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_Z | RADEON_CP_VC_FRMT_W0 ); offset = 4; } else { EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F, RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_Z ); offset = 3; } rmesa->swtcl.coloroffset = offset; #if MESA_LITTLE_ENDIAN EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, RADEON_CP_VC_FRMT_PKCOLOR ); #else EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR, RADEON_CP_VC_FRMT_PKCOLOR ); #endif offset += 1; rmesa->swtcl.specoffset = 0; if (index_bitset & (BITFIELD64_BIT(_TNL_ATTRIB_COLOR1) | BITFIELD64_BIT(_TNL_ATTRIB_FOG))) { #if MESA_LITTLE_ENDIAN if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { rmesa->swtcl.specoffset = offset; EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, RADEON_CP_VC_FRMT_PKSPEC ); } else { EMIT_PAD( 3 ); } if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) { EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, RADEON_CP_VC_FRMT_PKSPEC ); } else { EMIT_PAD( 1 ); } #else if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) { EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, RADEON_CP_VC_FRMT_PKSPEC ); } else { EMIT_PAD( 1 ); } if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { rmesa->swtcl.specoffset = offset; EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, RADEON_CP_VC_FRMT_PKSPEC ); } else { EMIT_PAD( 3 ); } #endif } if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { int i; for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) { GLuint sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size; switch (sz) { case 1: case 2: EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_2F, radeon_cp_vc_frmts[i][0] ); break; case 3: if (ctx->Texture.Unit[i]._Current && ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_CUBE_MAP) { EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F, radeon_cp_vc_frmts[i][1] ); } else { EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_2F, radeon_cp_vc_frmts[i][0] ); } break; case 4: if (ctx->Texture.Unit[i]._Current && ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_CUBE_MAP) { EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F, radeon_cp_vc_frmts[i][1] ); } else { EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F_XYW, radeon_cp_vc_frmts[i][1] ); } break; default: continue; }; } } } if (rmesa->radeon.tnl_index_bitset != index_bitset || fmt_0 != rmesa->swtcl.vertex_format) { RADEON_NEWPRIM(rmesa); rmesa->swtcl.vertex_format = fmt_0; rmesa->radeon.swtcl.vertex_size = _tnl_install_attrs( ctx, rmesa->radeon.swtcl.vertex_attrs, rmesa->radeon.swtcl.vertex_attr_count, NULL, 0 ); rmesa->radeon.swtcl.vertex_size /= 4; rmesa->radeon.tnl_index_bitset = index_bitset; radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s: vertex_size= %d floats\n", __func__, rmesa->radeon.swtcl.vertex_size); } }
static void i830_render_start(struct intel_context *intel) { struct gl_context *ctx = &intel->ctx; struct i830_context *i830 = i830_context(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; GLbitfield64 index_bitset = tnl->render_inputs_bitset; GLuint v0 = _3DSTATE_VFT0_CMD; GLuint v2 = _3DSTATE_VFT1_CMD; GLuint mcsb1 = 0; /* Important: */ VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; intel->vertex_attr_count = 0; /* EMIT_ATTR's must be in order as they tell t_vertex.c how to * build up a hardware vertex. */ if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW); intel->coloroffset = 4; } else { EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VFT0_XYZ); intel->coloroffset = 3; } if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE)) { EMIT_ATTR(_TNL_ATTRIB_POINTSIZE, EMIT_1F, VFT0_POINT_WIDTH); } EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VFT0_DIFFUSE); intel->specoffset = 0; if (index_bitset & (BITFIELD64_BIT(_TNL_ATTRIB_COLOR1) | BITFIELD64_BIT(_TNL_ATTRIB_FOG))) { if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { intel->specoffset = intel->coloroffset + 1; EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC); } else EMIT_PAD(3); if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC); else EMIT_PAD(1); } if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { int i, count = 0; for (i = 0; i < I830_TEX_UNITS; i++) { if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) { GLuint sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size; GLuint emit; GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] & ~TEXCOORDTYPE_MASK); switch (sz) { case 1: case 2: emit = EMIT_2F; sz = 2; mcs |= TEXCOORDTYPE_CARTESIAN; break; case 3: emit = EMIT_3F; sz = 3; mcs |= TEXCOORDTYPE_VECTOR; break; case 4: emit = EMIT_3F_XYW; sz = 3; mcs |= TEXCOORDTYPE_HOMOGENEOUS; break; default: continue; }; EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, emit, 0); v2 |= VRTX_TEX_SET_FMT(count, SZ_TO_HW(sz)); mcsb1 |= (count + 8) << (i * 4); if (mcs != i830->state.Tex[i][I830_TEXREG_MCS]) { I830_STATECHANGE(i830, I830_UPLOAD_TEX(i)); i830->state.Tex[i][I830_TEXREG_MCS] = mcs; } count++; } } v0 |= VFT0_TEX_COUNT(count); } /* Only need to change the vertex emit code if there has been a * statechange to a new hardware vertex format: */ if (v0 != i830->state.Ctx[I830_CTXREG_VF] || v2 != i830->state.Ctx[I830_CTXREG_VF2] || mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] || index_bitset != i830->last_index_bitset) { I830_STATECHANGE(i830, I830_UPLOAD_CTX); /* Must do this *after* statechange, so as not to affect * buffered vertices reliant on the old state: */ intel->vertex_size = _tnl_install_attrs(ctx, intel->vertex_attrs, intel->vertex_attr_count, intel->ViewportMatrix.m, 0); intel->vertex_size >>= 2; i830->state.Ctx[I830_CTXREG_VF] = v0; i830->state.Ctx[I830_CTXREG_VF2] = v2; i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1; i830->last_index_bitset = index_bitset; assert(i830_check_vertex_size(intel, intel->vertex_size)); }