diff options
-rw-r--r-- | src/mesa/drivers/dri/r200/r200_texstate.c | 93 |
1 files changed, 89 insertions, 4 deletions
diff --git a/src/mesa/drivers/dri/r200/r200_texstate.c b/src/mesa/drivers/dri/r200/r200_texstate.c index 433bc67e3f3..abb6af1b705 100644 --- a/src/mesa/drivers/dri/r200/r200_texstate.c +++ b/src/mesa/drivers/dri/r200/r200_texstate.c @@ -1216,6 +1216,47 @@ static void set_texgen_matrix( r200ContextPtr rmesa, } +static GLuint r200_need_dis_texgen(const GLbitfield texGenEnabled, + const GLfloat *planeS, + const GLfloat *planeT, + const GLfloat *planeR, + const GLfloat *planeQ) +{ + GLuint needtgenable = 0; + + if (!(texGenEnabled & S_BIT)) { + if (((texGenEnabled & T_BIT) && planeT[0] != 0.0) || + ((texGenEnabled & R_BIT) && planeR[0] != 0.0) || + ((texGenEnabled & Q_BIT) && planeQ[0] != 0.0)) { + needtgenable |= S_BIT; + } + } + if (!(texGenEnabled & T_BIT)) { + if (((texGenEnabled & S_BIT) && planeS[1] != 0.0) || + ((texGenEnabled & R_BIT) && planeR[1] != 0.0) || + ((texGenEnabled & Q_BIT) && planeQ[1] != 0.0)) { + needtgenable |= T_BIT; + } + } + if (!(texGenEnabled & R_BIT)) { + if (((texGenEnabled & S_BIT) && planeS[2] != 0.0) || + ((texGenEnabled & T_BIT) && planeT[2] != 0.0) || + ((texGenEnabled & Q_BIT) && planeQ[2] != 0.0)) { + needtgenable |= R_BIT; + } + } + if (!(texGenEnabled & Q_BIT)) { + if (((texGenEnabled & S_BIT) && planeS[3] != 0.0) || + ((texGenEnabled & T_BIT) && planeT[3] != 0.0) || + ((texGenEnabled & R_BIT) && planeR[3] != 0.0)) { + needtgenable |= Q_BIT; + } + } + + return needtgenable; +} + + /* * Returns GL_FALSE if fallback required. */ @@ -1285,28 +1326,72 @@ static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit ) return GL_FALSE; } +/* we CANNOT do mixed mode if the texgen mode requires a plane where the input + is not enabled for texgen, since the planes are concatenated into texmat, + and thus the input will come from texcoord rather than tex gen equation! + Either fallback or just hope that those texcoords aren't really needed... + Assuming the former will cause lots of unnecessary fallbacks, the latter will + generate bogus results sometimes - it's pretty much impossible to really know + when a fallback is needed, depends on texmat and what sort of texture is bound + etc, - for now fallback if we're missing either S or T bits, there's a high + probability we need the texcoords in that case. + That's a lot of work for some obscure texgen mixed mode fixup - why oh why + doesn't the chip just directly accept the plane parameters :-(. */ switch (mode) { - case GL_OBJECT_LINEAR: + case GL_OBJECT_LINEAR: { + GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled, + texUnit->ObjectPlaneS, texUnit->ObjectPlaneT, + texUnit->ObjectPlaneR, texUnit->ObjectPlaneQ ); + if (needtgenable & (S_BIT | T_BIT)) { + if (R200_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "fallback mixed texgen / obj plane, 0x%x\n", + texUnit->TexGenEnabled); + return GL_FALSE; + } + if (needtgenable & (R_BIT)) { + tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4)); + } + if (needtgenable & (Q_BIT)) { + tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4)); + } + tgi |= R200_TEXGEN_INPUT_OBJ << inputshift; set_texgen_matrix( rmesa, unit, (texUnit->TexGenEnabled & S_BIT) ? texUnit->ObjectPlaneS : I, (texUnit->TexGenEnabled & T_BIT) ? texUnit->ObjectPlaneT : I + 4, (texUnit->TexGenEnabled & R_BIT) ? texUnit->ObjectPlaneR : I + 8, (texUnit->TexGenEnabled & Q_BIT) ? texUnit->ObjectPlaneQ : I + 12); + } break; - case GL_EYE_LINEAR: + case GL_EYE_LINEAR: { + GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled, + texUnit->EyePlaneS, texUnit->EyePlaneT, + texUnit->EyePlaneR, texUnit->EyePlaneQ ); + if (needtgenable & (S_BIT | T_BIT)) { + if (R200_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "fallback mixed texgen / eye plane, 0x%x\n", + texUnit->TexGenEnabled); + return GL_FALSE; + } + if (needtgenable & (R_BIT)) { + tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4)); + } + if (needtgenable & (Q_BIT)) { + tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4)); + } tgi |= R200_TEXGEN_INPUT_EYE << inputshift; - set_texgen_matrix( rmesa, unit, + set_texgen_matrix( rmesa, unit, (texUnit->TexGenEnabled & S_BIT) ? texUnit->EyePlaneS : I, (texUnit->TexGenEnabled & T_BIT) ? texUnit->EyePlaneT : I + 4, (texUnit->TexGenEnabled & R_BIT) ? texUnit->EyePlaneR : I + 8, (texUnit->TexGenEnabled & Q_BIT) ? texUnit->EyePlaneQ : I + 12); + } break; case GL_REFLECTION_MAP_NV: rmesa->TexGenNeedNormals[unit] = GL_TRUE; - tgi |= R200_TEXGEN_INPUT_EYE_REFLECT<<inputshift; + tgi |= R200_TEXGEN_INPUT_EYE_REFLECT << inputshift; /* pretty weird, must only negate when lighting is enabled? */ if (ctx->Light.Enabled) set_texgen_matrix( rmesa, unit, |