📄 r200_texstate.c
字号:
if (use_d3d) re_cntl |= R200_VTX_STQ0_D3D << (2 * unit); if ( re_cntl != rmesa->hw.set.cmd[SET_RE_CNTL] ) { R200_STATECHANGE( rmesa, set ); rmesa->hw.set.cmd[SET_RE_CNTL] = re_cntl; }}static GLboolean enable_tex_2d( GLcontext *ctx, int unit ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData; /* Need to load the 2d images associated with this unit. */ if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) { t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2; t->base.dirty_images[0] = ~0; } ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D); if ( t->base.dirty_images[0] ) { R200_FIREVERTICES( rmesa ); r200SetTexImages( rmesa, tObj ); r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 ); if ( !t->base.memBlock && !t->image_override ) return GL_FALSE; } set_re_cntl_d3d( ctx, unit, GL_FALSE ); return GL_TRUE;}#if ENABLE_HW_3D_TEXTUREstatic GLboolean enable_tex_3d( GLcontext *ctx, int unit ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData; /* Need to load the 3d images associated with this unit. */ if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) { t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2; t->base.dirty_images[0] = ~0; } ASSERT(tObj->Target == GL_TEXTURE_3D); /* R100 & R200 do not support mipmaps for 3D textures. */ if ( (tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR) ) { return GL_FALSE; } if ( t->base.dirty_images[0] ) { R200_FIREVERTICES( rmesa ); r200SetTexImages( rmesa, tObj ); r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 ); if ( !t->base.memBlock ) return GL_FALSE; } set_re_cntl_d3d( ctx, unit, GL_TRUE ); return GL_TRUE;}#endifstatic GLboolean enable_tex_cube( GLcontext *ctx, int unit ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData; GLuint face; /* Need to load the 2d images associated with this unit. */ if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) { t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2; for (face = 0; face < 6; face++) t->base.dirty_images[face] = ~0; } ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP); if ( t->base.dirty_images[0] || t->base.dirty_images[1] || t->base.dirty_images[2] || t->base.dirty_images[3] || t->base.dirty_images[4] || t->base.dirty_images[5] ) { /* flush */ R200_FIREVERTICES( rmesa ); /* layout memory space, once for all faces */ r200SetTexImages( rmesa, tObj ); } /* upload (per face) */ for (face = 0; face < 6; face++) { if (t->base.dirty_images[face]) { r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, face ); } } if ( !t->base.memBlock ) { /* texmem alloc failed, use s/w fallback */ return GL_FALSE; } set_re_cntl_d3d( ctx, unit, GL_TRUE ); return GL_TRUE;}static GLboolean enable_tex_rect( GLcontext *ctx, int unit ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData; if (!(t->pp_txformat & R200_TXFORMAT_NON_POWER2)) { t->pp_txformat |= R200_TXFORMAT_NON_POWER2; t->base.dirty_images[0] = ~0; } ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV); if ( t->base.dirty_images[0] ) { R200_FIREVERTICES( rmesa ); r200SetTexImages( rmesa, tObj ); r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 ); if ( !t->base.memBlock && !t->image_override && !rmesa->prefer_gart_client_texturing ) return GL_FALSE; } set_re_cntl_d3d( ctx, unit, GL_FALSE ); return GL_TRUE;}static GLboolean update_tex_common( GLcontext *ctx, int unit ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData; /* Fallback if there's a texture border */ if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) return GL_FALSE; /* Update state if this is a different texture object to last * time. */ if ( rmesa->state.texture.unit[unit].texobj != t ) { if ( rmesa->state.texture.unit[unit].texobj != NULL ) { /* The old texture is no longer bound to this texture unit. * Mark it as such. */ rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit); } rmesa->state.texture.unit[unit].texobj = t; t->base.bound |= (1UL << unit); t->dirty_state |= 1<<unit; driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */ } /* Newly enabled? */ if ( 1|| !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit))) { R200_STATECHANGE( rmesa, ctx ); rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << unit; R200_STATECHANGE( rmesa, vtx ); rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3)); rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3); rmesa->recheck_texgen[unit] = GL_TRUE; } if (t->dirty_state & (1<<unit)) { import_tex_obj_state( rmesa, unit, t ); } if (rmesa->recheck_texgen[unit]) { GLboolean fallback = !r200_validate_texgen( ctx, unit ); TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback); rmesa->recheck_texgen[unit] = 0; rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; } FALLBACK( rmesa, R200_FALLBACK_BORDER_MODE, t->border_fallback ); return !t->border_fallback;}static GLboolean r200UpdateTextureUnit( GLcontext *ctx, int unit ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); GLuint unitneeded = rmesa->state.texture.unit[unit].unitneeded; if ( unitneeded & (TEXTURE_RECT_BIT) ) { return (enable_tex_rect( ctx, unit ) && update_tex_common( ctx, unit )); } else if ( unitneeded & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) { return (enable_tex_2d( ctx, unit ) && update_tex_common( ctx, unit )); }#if ENABLE_HW_3D_TEXTURE else if ( unitneeded & (TEXTURE_3D_BIT) ) { return (enable_tex_3d( ctx, unit ) && update_tex_common( ctx, unit )); }#endif else if ( unitneeded & (TEXTURE_CUBE_BIT) ) { return (enable_tex_cube( ctx, unit ) && update_tex_common( ctx, unit )); } else if ( unitneeded ) { return GL_FALSE; } else { disable_tex( ctx, unit ); return GL_TRUE; }}void r200UpdateTextureState( GLcontext *ctx ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); GLboolean ok; GLuint dbg; /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since we use these to determine if we want to emit the corresponding state atoms. */ R200_NEWPRIM( rmesa ); if (ctx->ATIFragmentShader._Enabled) { GLuint i; for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) { rmesa->state.texture.unit[i].unitneeded = ctx->Texture.Unit[i]._ReallyEnabled; } ok = GL_TRUE; } else { ok = r200UpdateAllTexEnv( ctx ); } if (ok) { ok = (r200UpdateTextureUnit( ctx, 0 ) && r200UpdateTextureUnit( ctx, 1 ) && r200UpdateTextureUnit( ctx, 2 ) && r200UpdateTextureUnit( ctx, 3 ) && r200UpdateTextureUnit( ctx, 4 ) && r200UpdateTextureUnit( ctx, 5 )); } if (ok && ctx->ATIFragmentShader._Enabled) { r200UpdateFragmentShader(ctx); } FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok ); if (rmesa->TclFallback) r200ChooseVertexState( ctx ); if (rmesa->r200Screen->chip_family == CHIP_FAMILY_R200) { /* * T0 hang workaround ------------- * not needed for r200 derivatives */ if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == R200_TEX_0_ENABLE && (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) { R200_STATECHANGE(rmesa, ctx); R200_STATECHANGE(rmesa, tex[1]); rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE; if (!(rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_1_ENABLE)) rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= R200_TXFORMAT_LOOKUP_DISABLE; } else if (!ctx->ATIFragmentShader._Enabled) { if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) && (rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] & R200_TXFORMAT_LOOKUP_DISABLE)) { R200_STATECHANGE(rmesa, tex[1]); rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~R200_TXFORMAT_LOOKUP_DISABLE; } } /* do the same workaround for the first pass of a fragment shader. * completely unknown if necessary / sufficient. */ if ((rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_ENABLE_MASK) == R200_PPX_TEX_0_ENABLE && (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) { R200_STATECHANGE(rmesa, cst); R200_STATECHANGE(rmesa, tex[1]); rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_1_ENABLE; if (!(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE)) rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; rmesa->hw.tex[1].cmd[TEX_PP_TXMULTI_CTL] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE; } /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ? looks like that's not the case, if 8500/9100 owners don't complain remove this... for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) { if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE | R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) && ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR)) { R200_STATECHANGE(rmesa, ctx); R200_STATECHANGE(rmesa, tex[i+1]); rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i); rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000; } else { if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) && (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) { R200_STATECHANGE(rmesa, tex[i+1]); rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000; } } } */ /* * Texture cache LRU hang workaround ------------- * not needed for r200 derivatives * hopefully this covers first pass of a shader as well */ /* While the cases below attempt to only enable the workaround in the * specific cases necessary, they were insufficient. See bugzilla #1519, * #729, #814. Tests with quake3 showed no impact on performance. */ dbg = 0x6; /* if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) && ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) == 0)) || ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) && ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) == 0)) || ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) && ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) == 0))) { dbg |= 0x02; } if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) && ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) == 0)) || ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) && ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) == 0)) || ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) && ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) == 0))) { dbg |= 0x04; }*/ if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) { R200_STATECHANGE( rmesa, tam ); rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg; if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -