📄 radeon_texstate.c
字号:
if (texobj->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) { GLuint *txr_cmd = RADEON_DB_STATE( txr[unit] ); txr_cmd[TXR_PP_TEX_SIZE] = texobj->pp_txsize; /* NPOT only! */ txr_cmd[TXR_PP_TEX_PITCH] = texobj->pp_txpitch; /* NPOT only! */ RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.txr[unit] ); se_coord_fmt |= RADEON_VTX_ST0_NONPARAMETRIC << unit; } else { se_coord_fmt &= ~(RADEON_VTX_ST0_NONPARAMETRIC << unit); if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) { int *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0]; GLuint bytesPerFace = texobj->base.totalSize / 6; ASSERT(texobj->base.totalSize % 6 == 0); RADEON_STATECHANGE( rmesa, cube[unit] ); cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces; /* dont know if this setup conforms to OpenGL.. * at least it matches the behavior of mesa software renderer */ cube_cmd[CUBE_PP_CUBIC_OFFSET_0] = texobj->pp_txoffset; /* right */ cube_cmd[CUBE_PP_CUBIC_OFFSET_1] = texobj->pp_txoffset + 1 * bytesPerFace; /* left */ cube_cmd[CUBE_PP_CUBIC_OFFSET_2] = texobj->pp_txoffset + 2 * bytesPerFace; /* top */ cube_cmd[CUBE_PP_CUBIC_OFFSET_3] = texobj->pp_txoffset + 3 * bytesPerFace; /* bottom */ cube_cmd[CUBE_PP_CUBIC_OFFSET_4] = texobj->pp_txoffset + 4 * bytesPerFace; /* front */ cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset + 5 * bytesPerFace; /* back */ } } 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; } texobj->dirty_state &= ~(1<<unit);}static void set_texgen_matrix( radeonContextPtr rmesa, GLuint unit, const GLfloat *s_plane, const GLfloat *t_plane, const GLfloat *r_plane, const GLfloat *q_plane ){ rmesa->TexGenMatrix[unit].m[0] = s_plane[0]; rmesa->TexGenMatrix[unit].m[4] = s_plane[1]; rmesa->TexGenMatrix[unit].m[8] = s_plane[2]; rmesa->TexGenMatrix[unit].m[12] = s_plane[3]; rmesa->TexGenMatrix[unit].m[1] = t_plane[0]; rmesa->TexGenMatrix[unit].m[5] = t_plane[1]; rmesa->TexGenMatrix[unit].m[9] = t_plane[2]; rmesa->TexGenMatrix[unit].m[13] = t_plane[3]; rmesa->TexGenMatrix[unit].m[2] = r_plane[0]; rmesa->TexGenMatrix[unit].m[6] = r_plane[1]; rmesa->TexGenMatrix[unit].m[10] = r_plane[2]; rmesa->TexGenMatrix[unit].m[14] = r_plane[3]; rmesa->TexGenMatrix[unit].m[3] = q_plane[0]; rmesa->TexGenMatrix[unit].m[7] = q_plane[1]; rmesa->TexGenMatrix[unit].m[11] = q_plane[2]; rmesa->TexGenMatrix[unit].m[15] = q_plane[3]; rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE << unit; rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;}/* Returns GL_FALSE if fallback required. */static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4; GLuint tmp = rmesa->TexGenEnabled; static const GLfloat reflect[16] = { -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 }; rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE << unit); rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE << unit); rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK << inputshift); rmesa->TexGenNeedNormals[unit] = 0; if ((texUnit->TexGenEnabled & (S_BIT|T_BIT|R_BIT|Q_BIT)) == 0) { /* Disabled, no fallback: */ rmesa->TexGenEnabled |= (RADEON_TEXGEN_INPUT_TEXCOORD_0 + unit) << inputshift; return GL_TRUE; } /* the r100 cannot do texgen for some coords and not for others * we do not detect such cases (certainly can't do it here) and just * ASSUME that when S and T are texgen enabled we do not need other * non-texgen enabled coords, no matter if the R and Q bits are texgen * enabled. Still check for mixed mode texgen for all coords. */ else if ( (texUnit->TexGenEnabled & S_BIT) && (texUnit->TexGenEnabled & T_BIT) && (texUnit->GenModeS == texUnit->GenModeT) ) { if ( ((texUnit->TexGenEnabled & R_BIT) && (texUnit->GenModeS != texUnit->GenModeR)) || ((texUnit->TexGenEnabled & Q_BIT) && (texUnit->GenModeS != texUnit->GenModeQ)) ) { /* Mixed modes, fallback: */ if (RADEON_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "fallback mixed texgen\n"); return GL_FALSE; } rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit; } else { /* some texgen mode not including both S and T bits */ if (RADEON_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "fallback mixed texgen/nontexgen\n"); return GL_FALSE; } if ((texUnit->TexGenEnabled & (R_BIT | Q_BIT)) != 0) { /* need this here for vtxfmt presumably. Argh we need to set this from way too many places, would be much easier if we could leave tcl q coord always enabled as on r200) */ RADEON_STATECHANGE( rmesa, tcl ); rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_Q_BIT(unit); } switch (texUnit->GenModeS) { case GL_OBJECT_LINEAR: rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_OBJ << inputshift; set_texgen_matrix( rmesa, unit, texUnit->ObjectPlaneS, texUnit->ObjectPlaneT, texUnit->ObjectPlaneR, texUnit->ObjectPlaneQ); break; case GL_EYE_LINEAR: rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE << inputshift; set_texgen_matrix( rmesa, unit, texUnit->EyePlaneS, texUnit->EyePlaneT, texUnit->EyePlaneR, texUnit->EyePlaneQ); break; case GL_REFLECTION_MAP_NV: rmesa->TexGenNeedNormals[unit] = GL_TRUE; rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_REFLECT << inputshift; /* TODO: unknown if this is needed/correct */ set_texgen_matrix( rmesa, unit, reflect, reflect + 4, reflect + 8, reflect + 12 ); break; case GL_NORMAL_MAP_NV: rmesa->TexGenNeedNormals[unit] = GL_TRUE; rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_NORMAL << inputshift; break; case GL_SPHERE_MAP: /* the mode which everyone uses :-( */ default: /* Unsupported mode, fallback: */ if (RADEON_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "fallback GL_SPHERE_MAP\n"); return GL_FALSE; } if (tmp != rmesa->TexGenEnabled) { rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; } return GL_TRUE;}static void disable_tex( GLcontext *ctx, int unit ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit)) { /* Texture unit disabled */ 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 = NULL; } RADEON_STATECHANGE( rmesa, ctx ); rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~((RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit); RADEON_STATECHANGE( rmesa, tcl ); rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_ST_BIT(unit) | RADEON_Q_BIT(unit)); if (rmesa->TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0<<unit)) { TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE); rmesa->recheck_texgen[unit] = GL_TRUE; } if (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) { /* this seems to be a genuine (r100 only?) hw bug. Need to remove the cubic_map bit on unit 2 when the unit is disabled, otherwise every 2nd (2d) mipmap on unit 0 will be broken (may not be needed for other units, better be safe than sorry though).*/ RADEON_STATECHANGE( rmesa, tex[unit] ); rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= ~RADEON_TXFORMAT_CUBIC_MAP_ENABLE; } { GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4; GLuint tmp = rmesa->TexGenEnabled; rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit); rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit); rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift); rmesa->TexGenNeedNormals[unit] = 0; rmesa->TexGenEnabled |= (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift; if (tmp != rmesa->TexGenEnabled) { rmesa->recheck_texgen[unit] = GL_TRUE; rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; } } }}static GLboolean enable_tex_2d( GLcontext *ctx, int unit ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData; /* Need to load the 2d images associated with this unit. */ if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) { t->pp_txformat &= ~RADEON_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] ) { RADEON_FIREVERTICES( rmesa ); radeonSetTexImages( rmesa, tObj ); radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 ); if ( !t->base.memBlock && !t->image_override ) return GL_FALSE; } return GL_TRUE;}static GLboolean enable_tex_cube( GLcontext *ctx, int unit ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData; GLuint face; /* Need to load the 2d images associated with this unit. */ if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) { t->pp_txformat &= ~RADEON_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 */ RADEON_FIREVERTICES( rmesa ); /* layout memory space, once for all faces */ radeonSetTexImages( rmesa, tObj ); } /* upload (per face) */ for (face = 0; face < 6; face++) { if (t->base.dirty_images[face]) { radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, face ); } } if ( !t->base.memBlock ) { /* texmem alloc failed, use s/w fallback */ return GL_FALSE; } return GL_TRUE;}static GLboolean enable_tex_rect( GLcontext *ctx, int unit ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData; if (!(t->pp_txformat & RADEON_TXFORMAT_NON_POWER2)) { t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2; t->base.dirty_images[0] = ~0; } ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV); if ( t->base.dirty_images[0] ) { RADEON_FIREVERTICES( rmesa ); radeonSetTexImages( rmesa, tObj ); radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 ); if ( !t->base.memBlock && !t->image_override /* && !rmesa->prefer_gart_client_texturing FIXME */ ) { fprintf(stderr, "%s: upload failed\n", __FUNCTION__); return GL_FALSE; } } return GL_TRUE;}static GLboolean update_tex_common( GLcontext *ctx, int unit ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *tObj = texUnit->_Current; radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData; GLenum format; /* Fallback if there's a texture border */ if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) { fprintf(stderr, "%s: border\n", __FUNCTION__); return GL_FALSE; } /* yuv conversion only works in first unit */ if (unit != 0 && (t->pp_txfilter & RADEON_YUV_TO_RGB)) 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 ( !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit))) { RADEON_STATECHANGE( rmesa, ctx ); rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit; RADEON_STATECHANGE( rmesa, tcl ); rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_ST_BIT(unit); rmesa->recheck_texgen[unit] = GL_TRUE; } if (t->dirty_state & (1<<unit)) { import_tex_obj_state( rmesa, unit, t ); /* may need to update texture matrix (for texrect adjustments) */ rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; } if (rmesa->recheck_texgen[unit]) { GLboolean fallback = !radeon_validate_texgen( ctx, unit ); TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), fallback); rmesa->recheck_texgen[unit] = 0; rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; } format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; if ( rmesa->state.texture.unit[unit].format != format || rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) { rmesa->state.texture.unit[unit].format = format; rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode; if ( ! radeonUpdateTextureEnv( ctx, unit ) ) { return GL_FALSE; } } FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback ); return !t->border_fallback;}static GLboolean radeonUpdateTextureUnit( GLcontext *ctx, int unit ){ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) { return (enable_tex_rect( ctx, unit ) && update_tex_common( ctx, unit )); } else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) { return (enable_tex_2d( ctx, unit ) && update_tex_common( ctx, unit )); } else if ( texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT) ) { return (enable_tex_cube( ctx, unit ) && update_tex_common( ctx, unit )); } else if ( texUnit->_ReallyEnabled ) { return GL_FALSE; } else { disable_tex( ctx, unit ); return GL_TRUE; }}void radeonUpdateTextureState( GLcontext *ctx ){ radeonContextPtr rmesa = RADEON_CONTEXT(ctx); GLboolean ok; ok = (radeonUpdateTextureUnit( ctx, 0 ) && radeonUpdateTextureUnit( ctx, 1 ) && radeonUpdateTextureUnit( ctx, 2 )); FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok ); if (rmesa->TclFallback) radeonChooseVertexState( ctx );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -