📄 r200_texstate.c
字号:
case GL_MODULATE_SIGNED_ADD_ATI: alpha_combine = (R200_TXA_BIAS_ARG_C | /* new */ R200_TXA_OP_MADD); /* was ADDSIGNED */ R200_ALPHA_ARG( 0, A ); R200_ALPHA_ARG( 1, C ); R200_ALPHA_ARG( 2, B ); break; case GL_MODULATE_SUBTRACT_ATI: alpha_combine = (R200_TXA_NEG_ARG_C | R200_TXA_OP_MADD); R200_ALPHA_ARG( 0, A ); R200_ALPHA_ARG( 1, C ); R200_ALPHA_ARG( 2, B ); break; default: return GL_FALSE; } if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT) || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) { alpha_scale |= R200_TXA_DOT_ALPHA; Ashift = RGBshift; } /* Step 3: * Apply the scale factor. */ color_scale |= (RGBshift << R200_TXC_SCALE_SHIFT); alpha_scale |= (Ashift << R200_TXA_SCALE_SHIFT); /* All done! */ } if ( rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] != color_combine || rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] != alpha_combine || rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] != color_scale || rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] != alpha_scale) { R200_STATECHANGE( rmesa, pix[slot] ); rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] = color_combine; rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] = alpha_combine; rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] = color_scale; rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] = alpha_scale; } return GL_TRUE;}#define REF_COLOR 1#define REF_ALPHA 2static GLboolean r200UpdateAllTexEnv( GLcontext *ctx ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); GLint i, j, currslot; GLint maxunitused = -1; GLboolean texregfree[6] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}; GLubyte stageref[7] = {0, 0, 0, 0, 0, 0, 0}; GLint nextunit[R200_MAX_TEXTURE_UNITS] = {0, 0, 0, 0, 0, 0}; GLint currentnext = -1; GLboolean ok; /* find highest used unit */ for ( j = 0; j < R200_MAX_TEXTURE_UNITS; j++) { if (ctx->Texture.Unit[j]._ReallyEnabled) { maxunitused = j; } } stageref[maxunitused + 1] = REF_COLOR | REF_ALPHA; for ( j = maxunitused; j >= 0; j-- ) { const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[j]; rmesa->state.texture.unit[j].outputreg = -1; if (stageref[j + 1]) { /* use the lowest available reg. That gets us automatically reg0 for the last stage. need this even for disabled units, as it may get referenced due to the replace optimization */ for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS; i++ ) { if (texregfree[i]) { rmesa->state.texture.unit[j].outputreg = i; break; } } if (rmesa->state.texture.unit[j].outputreg == -1) { /* no more free regs we can use. Need a fallback :-( */ return GL_FALSE; } nextunit[j] = currentnext; if (!texUnit->_ReallyEnabled) { /* the not enabled stages are referenced "indirectly", must not cut off the lower stages */ stageref[j] = REF_COLOR | REF_ALPHA; continue; } currentnext = j; const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB; const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA; const GLboolean isdot3rgba = (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT); /* check if we need the color part, special case for dot3_rgba as if only the alpha part is referenced later on it still is using the color part */ if ((stageref[j + 1] & REF_COLOR) || isdot3rgba) { for ( i = 0 ; i < numColorArgs ; i++ ) { const GLuint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i]; const GLuint op = texUnit->_CurrentCombine->OperandRGB[i]; switch ( srcRGBi ) { case GL_PREVIOUS: /* op 0/1 are referencing color, op 2/3 alpha */ stageref[j] |= (op >> 1) + 1; break; case GL_TEXTURE: texregfree[j] = GL_FALSE; break; case GL_TEXTURE0: case GL_TEXTURE1: case GL_TEXTURE2: case GL_TEXTURE3: case GL_TEXTURE4: case GL_TEXTURE5: texregfree[srcRGBi - GL_TEXTURE0] = GL_FALSE; break; default: /* don't care about other sources here */ break; } } } /* alpha args are ignored for dot3_rgba */ if ((stageref[j + 1] & REF_ALPHA) && !isdot3rgba) { for ( i = 0 ; i < numAlphaArgs ; i++ ) { const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i]; switch ( srcAi ) { case GL_PREVIOUS: stageref[j] |= REF_ALPHA; break; case GL_TEXTURE: texregfree[j] = GL_FALSE; break; case GL_TEXTURE0: case GL_TEXTURE1: case GL_TEXTURE2: case GL_TEXTURE3: case GL_TEXTURE4: case GL_TEXTURE5: texregfree[srcAi - GL_TEXTURE0] = GL_FALSE; break; default: /* don't care about other sources here */ break; } } } } } /* don't enable texture sampling for units if the result is not used */ for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) { if (ctx->Texture.Unit[i]._ReallyEnabled && !texregfree[i]) rmesa->state.texture.unit[i].unitneeded = ctx->Texture.Unit[i]._ReallyEnabled; else rmesa->state.texture.unit[i].unitneeded = 0; } ok = GL_TRUE; currslot = 0; rmesa->state.envneeded = 1; i = 0; while ((i <= maxunitused) && (i >= 0)) { /* only output instruction if the results are referenced */ if (ctx->Texture.Unit[i]._ReallyEnabled && stageref[i+1]) { GLuint replaceunit = i; /* try to optimize GL_REPLACE away (only one level deep though) */ if ( (ctx->Texture.Unit[i]._CurrentCombine->ModeRGB == GL_REPLACE) && (ctx->Texture.Unit[i]._CurrentCombine->ModeA == GL_REPLACE) && (ctx->Texture.Unit[i]._CurrentCombine->ScaleShiftRGB == 0) && (ctx->Texture.Unit[i]._CurrentCombine->ScaleShiftA == 0) && (nextunit[i] > 0) ) { /* yippie! can optimize it away! */ replaceunit = i; i = nextunit[i]; } /* need env instruction slot */ rmesa->state.envneeded |= 1 << currslot; ok = r200UpdateTextureEnv( ctx, i, currslot, replaceunit ); if (!ok) return GL_FALSE; currslot++; } i = i + 1; } if (currslot == 0) { /* need one stage at least */ rmesa->state.texture.unit[0].outputreg = 0; ok = r200UpdateTextureEnv( ctx, 0, 0, 0 ); } R200_STATECHANGE( rmesa, ctx ); rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_BLEND_ENABLE_MASK | R200_MULTI_PASS_ENABLE); rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= rmesa->state.envneeded << R200_TEX_BLEND_0_ENABLE_SHIFT; return ok;}#undef REF_COLOR#undef REF_ALPHA#define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \ R200_MIN_FILTER_MASK | \ R200_MAG_FILTER_MASK | \ R200_MAX_ANISO_MASK | \ R200_YUV_TO_RGB | \ R200_YUV_TEMPERATURE_MASK | \ R200_CLAMP_S_MASK | \ R200_CLAMP_T_MASK | \ R200_BORDER_MODE_D3D )#define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \ R200_TXFORMAT_HEIGHT_MASK | \ R200_TXFORMAT_FORMAT_MASK | \ R200_TXFORMAT_F5_WIDTH_MASK | \ R200_TXFORMAT_F5_HEIGHT_MASK | \ R200_TXFORMAT_ALPHA_IN_MAP | \ R200_TXFORMAT_CUBIC_MAP_ENABLE | \ R200_TXFORMAT_NON_POWER2)#define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \ R200_TEXCOORD_MASK | \ R200_CLAMP_Q_MASK | \ R200_VOLUME_FILTER_MASK)static void import_tex_obj_state( r200ContextPtr rmesa, int unit, r200TexObjPtr texobj ){ GLuint *cmd = R200_DB_STATE( tex[unit] ); cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK; cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK; cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK; cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK; cmd[TEX_PP_TXFORMAT_X] |= texobj->pp_txformat_x & TEXOBJ_TXFORMAT_X_MASK; cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */ cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */ cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color; if (rmesa->r200Screen->drmSupportsFragShader) { cmd[TEX_PP_TXOFFSET_NEWDRM] = texobj->pp_txoffset; } else { cmd[TEX_PP_TXOFFSET_OLDDRM] = texobj->pp_txoffset; } if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) { GLuint *cube_cmd = R200_DB_STATE( cube[unit] ); GLuint bytesPerFace = texobj->base.totalSize / 6; ASSERT(texobj->base.totalSize % 6 == 0); cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces; if (rmesa->r200Screen->drmSupportsFragShader) { /* that value is submitted twice. could change cube atom to not include that command when new drm is used */ cmd[TEX_PP_CUBIC_FACES] = texobj->pp_cubic_faces; } cube_cmd[CUBE_PP_CUBIC_OFFSET_F1] = texobj->pp_txoffset + 1 * bytesPerFace; cube_cmd[CUBE_PP_CUBIC_OFFSET_F2] = texobj->pp_txoffset + 2 * bytesPerFace; cube_cmd[CUBE_PP_CUBIC_OFFSET_F3] = texobj->pp_txoffset + 3 * bytesPerFace; cube_cmd[CUBE_PP_CUBIC_OFFSET_F4] = texobj->pp_txoffset + 4 * bytesPerFace; cube_cmd[CUBE_PP_CUBIC_OFFSET_F5] = texobj->pp_txoffset + 5 * bytesPerFace; R200_DB_STATECHANGE( rmesa, &rmesa->hw.cube[unit] ); } R200_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] ); texobj->dirty_state &= ~(1<<unit);}static void set_texgen_matrix( r200ContextPtr rmesa, GLuint unit, const GLfloat *s_plane, const GLfloat *t_plane, const GLfloat *r_plane, const GLfloat *q_plane ){ GLfloat m[16]; m[0] = s_plane[0]; m[4] = s_plane[1]; m[8] = s_plane[2]; m[12] = s_plane[3]; m[1] = t_plane[0]; m[5] = t_plane[1]; m[9] = t_plane[2]; m[13] = t_plane[3]; m[2] = r_plane[0]; m[6] = r_plane[1]; m[10] = r_plane[2]; m[14] = r_plane[3]; m[3] = q_plane[0]; m[7] = q_plane[1]; m[11] = q_plane[2]; m[15] = q_plane[3]; _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m); _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) ); rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;}/* * Returns GL_FALSE if fallback required. */static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit ){ r200ContextPtr rmesa = R200_CONTEXT(ctx); const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4; GLuint tgi, tgcm; GLuint mode = 0; GLboolean mixed_fallback = GL_FALSE; static const GLfloat I[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; static const GLfloat reflect[16] = { -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 }; rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit); rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit); rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit); rmesa->TexGenNeedNormals[unit] = GL_FALSE; tgi = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] & ~(R200_TEXGEN_INPUT_MASK << inputshift); tgcm = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] & ~(R200_TEXGEN_COMP_MASK << (unit * 4)); if (0) fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit); if (texUnit->TexGenEnabled & S_BIT) { mode = texUnit->GenModeS; } else { tgcm |= R200_TEXGEN_COMP_S << (unit * 4); } if (texUnit->TexGenEnabled & T_BIT) { if (texUnit->GenModeT != mode) mixed_fallback = GL_TRUE; } else { tgcm |= R200_TEXGEN_COMP_T << (unit * 4); } if (texUnit->TexGenEnabled & R_BIT) { if (texUnit->GenModeR != mode) mixed_fallback = GL_TRUE; } else { tgcm |= R200_TEXGEN_COMP_R << (unit * 4); } if (texUnit->TexGenEnabled & Q_BIT) { if (texUnit->GenModeQ != mode) mixed_fallback = GL_TRUE; } else { tgcm |= R200_TEXGEN_COMP_Q << (unit * 4); } if (mixed_fallback) { if (R200_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n", texUnit->TexGenEnabled, texUnit->GenModeS, texUnit->GenModeT, texUnit->GenModeR, texUnit->GenModeQ); return GL_FALSE; } switch (mode) { case GL_OBJECT_LINEAR: 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: tgi |= R200_TEXGEN_INPUT_EYE << inputshift; 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; set_texgen_matrix( rmesa, unit, (texUnit->TexGenEnabled & S_BIT) ? reflect : I, (texUnit->TexGenEnabled & T_BIT) ? reflect + 4 : I + 4, (texUnit->TexGenEnabled & R_BIT) ? reflect + 8 : I + 8, I + 12); break; case GL_NORMAL_MAP_NV: rmesa->TexGenNeedNormals[unit] = GL_TRUE; tgi |= R200_TEXGEN_INPUT_EYE_NORMAL<<inputshift; break; case GL_SPHERE_MAP: rmesa->TexGenNeedNormals[unit] = GL_TRUE; tgi |= R200_TEXGEN_INPUT_SPHERE<<inputshift; break; case 0: /* All texgen units were disabled, so just pass coords through. */ tgi |= unit << inputshift; break; default: /* Unsupported mode, fallback: */ if (R200_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "fallback unsupported texgen, %d\n", texUnit->GenModeS); return GL_FALSE; } rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit; rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit; if (tgi != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -