/** * \note This routine refers to derived texture matrix values to * compute the ENABLE_TEXMAT flags, but is only called on * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT * flags are updated by _mesa_update_texture_matrices, above. * * \param ctx GL context. */ static void update_texture_state( GLcontext *ctx ) { GLuint unit; struct gl_fragment_program *fprog = NULL; struct gl_vertex_program *vprog = NULL; GLbitfield enabledFragUnits = 0x0; if (ctx->Shader.CurrentProgram && ctx->Shader.CurrentProgram->LinkStatus) { fprog = ctx->Shader.CurrentProgram->FragmentProgram; vprog = ctx->Shader.CurrentProgram->VertexProgram; } else { if (ctx->FragmentProgram._Enabled) { fprog = ctx->FragmentProgram.Current; } if (ctx->VertexProgram._Enabled) { /* XXX enable this if/when non-shader vertex programs get * texture fetches: vprog = ctx->VertexProgram.Current; */ } } /* TODO: only set this if there are actual changes */ ctx->NewState |= _NEW_TEXTURE; ctx->Texture._EnabledUnits = 0x0; ctx->Texture._GenFlags = 0x0; ctx->Texture._TexMatEnabled = 0x0; ctx->Texture._TexGenEnabled = 0x0; /* * Update texture unit state. */ for (unit = 0; unit < ctx->Const.MaxTextureImageUnits; unit++) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLbitfield enabledVertTargets = 0x0; GLbitfield enabledFragTargets = 0x0; GLbitfield enabledTargets = 0x0; GLuint texIndex; /* Get the bitmask of texture target enables. * enableBits will be a mask of the TEXTURE_*_BIT flags indicating * which texture targets are enabled (fixed function) or referenced * by a fragment shader/program. When multiple flags are set, we'll * settle on the one with highest priority (see below). */ if (vprog) { enabledVertTargets |= vprog->Base.TexturesUsed[unit]; } if (fprog) { enabledFragTargets |= fprog->Base.TexturesUsed[unit]; } else { /* fixed-function fragment program */ enabledFragTargets |= texUnit->Enabled; } enabledTargets = enabledVertTargets | enabledFragTargets; texUnit->_ReallyEnabled = 0x0; if (enabledTargets == 0x0) { /* neither vertex nor fragment processing uses this unit */ continue; } /* Look for the highest priority texture target that's enabled (or used * by the vert/frag shaders) and "complete". That's the one we'll use * for texturing. If we're using vert/frag program we're guaranteed * that bitcount(enabledBits) <= 1. * Note that the TEXTURE_x_INDEX values are in high to low priority. */ for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) { if (enabledTargets & (1 << texIndex)) { struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex]; if (!texObj->_Complete) { _mesa_test_texobj_completeness(ctx, texObj); } if (texObj->_Complete) { texUnit->_ReallyEnabled = 1 << texIndex; _mesa_reference_texobj(&texUnit->_Current, texObj); break; } } } if (!texUnit->_ReallyEnabled) { if (fprog) { /* If we get here it means the shader is expecting a texture * object, but there isn't one (or it's incomplete). Use the * fallback texture. */ struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx); texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX; _mesa_reference_texobj(&texUnit->_Current, texObj); } else { /* fixed-function: texture unit is really disabled */ continue; } } /* if we get here, we know this texture unit is enabled */ ctx->Texture._EnabledUnits |= (1 << unit); if (enabledFragTargets) enabledFragUnits |= (1 << unit); update_tex_combine(ctx, texUnit); } /* Determine which texture coordinate sets are actually needed */ if (fprog) { const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1; ctx->Texture._EnabledCoordUnits = (fprog->Base.InputsRead >> FRAG_ATTRIB_TEX0) & coordMask; } else {
static void update_ff_texture_state(struct gl_context *ctx, BITSET_WORD *enabled_texture_units) { int unit; for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLbitfield mask; bool complete; if (texUnit->Enabled == 0x0) continue; /* If a shader already dictated what texture target was used for this * unit, just go along with it. */ if (BITSET_TEST(enabled_texture_units, unit)) continue; /* From the GL 4.4 compat specification, section 16.2 ("Texture Application"): * * "Texturing is enabled or disabled using the generic Enable and * Disable commands, respectively, with the symbolic constants * TEXTURE_1D, TEXTURE_2D, TEXTURE_RECTANGLE, TEXTURE_3D, or * TEXTURE_CUBE_MAP to enable the one-, two-, rectangular, * three-dimensional, or cube map texture, respectively. If more * than one of these textures is enabled, the first one enabled * from the following list is used: * * • cube map texture * • three-dimensional texture * • rectangular texture * • two-dimensional texture * • one-dimensional texture" * * Note that the TEXTURE_x_INDEX values are in high to low priority. * Also: * * "If a texture unit is disabled or has an invalid or incomplete * texture (as defined in section 8.17) bound to it, then blending * is disabled for that texture unit. If the texture environment * for a given enabled texture unit references a disabled texture * unit, or an invalid or incomplete texture that is bound to * another unit, then the results of texture blending are * undefined." */ complete = false; mask = texUnit->Enabled; while (mask) { const int texIndex = u_bit_scan(&mask); struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex]; struct gl_sampler_object *sampler = texUnit->Sampler ? texUnit->Sampler : &texObj->Sampler; if (!_mesa_is_texture_complete(texObj, sampler)) { _mesa_test_texobj_completeness(ctx, texObj); } if (_mesa_is_texture_complete(texObj, sampler)) { _mesa_reference_texobj(&texUnit->_Current, texObj); complete = true; break; } } if (!complete) continue; /* if we get here, we know this texture unit is enabled */ BITSET_SET(enabled_texture_units, unit); ctx->Texture._MaxEnabledTexImageUnit = MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit); ctx->Texture._EnabledCoordUnits |= 1 << unit; update_tex_combine(ctx, texUnit); } }
/** * \note This routine refers to derived texture matrix values to * compute the ENABLE_TEXMAT flags, but is only called on * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT * flags are updated by _mesa_update_texture_matrices, above. * * \param ctx GL context. */ static void update_texture_state( struct gl_context *ctx ) { GLuint unit; struct gl_program *fprog = NULL; struct gl_program *vprog = NULL; struct gl_program *gprog = NULL; GLbitfield enabledFragUnits = 0x0; if (ctx->Shader.CurrentVertexProgram && ctx->Shader.CurrentVertexProgram->LinkStatus) { vprog = ctx->Shader.CurrentVertexProgram->_LinkedShaders[MESA_SHADER_VERTEX]->Program; } if (ctx->Shader.CurrentGeometryProgram && ctx->Shader.CurrentGeometryProgram->LinkStatus) { gprog = ctx->Shader.CurrentGeometryProgram->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program; } if (ctx->Shader.CurrentFragmentProgram && ctx->Shader.CurrentFragmentProgram->LinkStatus) { fprog = ctx->Shader.CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program; } else if (ctx->FragmentProgram._Enabled) { fprog = &ctx->FragmentProgram.Current->Base; } /* TODO: only set this if there are actual changes */ ctx->NewState |= _NEW_TEXTURE; ctx->Texture._EnabledUnits = 0x0; ctx->Texture._GenFlags = 0x0; ctx->Texture._TexMatEnabled = 0x0; ctx->Texture._TexGenEnabled = 0x0; /* * Update texture unit state. */ for (unit = 0; unit < ctx->Const.MaxCombinedTextureImageUnits; unit++) { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLbitfield enabledVertTargets = 0x0; GLbitfield enabledFragTargets = 0x0; GLbitfield enabledGeomTargets = 0x0; GLbitfield enabledTargets = 0x0; GLuint texIndex; /* Get the bitmask of texture target enables. * enableBits will be a mask of the TEXTURE_*_BIT flags indicating * which texture targets are enabled (fixed function) or referenced * by a fragment program/program. When multiple flags are set, we'll * settle on the one with highest priority (see below). */ if (vprog) { enabledVertTargets |= vprog->TexturesUsed[unit]; } if (gprog) { enabledGeomTargets |= gprog->TexturesUsed[unit]; } if (fprog) { enabledFragTargets |= fprog->TexturesUsed[unit]; } else { /* fixed-function fragment program */ enabledFragTargets |= texUnit->Enabled; } enabledTargets = enabledVertTargets | enabledFragTargets | enabledGeomTargets; texUnit->_ReallyEnabled = 0x0; if (enabledTargets == 0x0) { /* neither vertex nor fragment processing uses this unit */ continue; } /* Look for the highest priority texture target that's enabled (or used * by the vert/frag shaders) and "complete". That's the one we'll use * for texturing. * * Note that the TEXTURE_x_INDEX values are in high to low priority. */ for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) { if (enabledTargets & (1 << texIndex)) { struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex]; struct gl_sampler_object *sampler = texUnit->Sampler ? texUnit->Sampler : &texObj->Sampler; if (!_mesa_is_texture_complete(texObj, sampler)) { _mesa_test_texobj_completeness(ctx, texObj); } if (_mesa_is_texture_complete(texObj, sampler)) { texUnit->_ReallyEnabled = 1 << texIndex; _mesa_reference_texobj(&texUnit->_Current, texObj); break; } } } if (!texUnit->_ReallyEnabled) { if (fprog) { /* If we get here it means the shader is expecting a texture * object, but there isn't one (or it's incomplete). Use the * fallback texture. */ struct gl_texture_object *texObj; gl_texture_index texTarget; texTarget = (gl_texture_index) (ffs(enabledTargets) - 1); texObj = _mesa_get_fallback_texture(ctx, texTarget); assert(texObj); if (!texObj) { /* invalid fallback texture: don't enable the texture unit */ continue; } _mesa_reference_texobj(&texUnit->_Current, texObj); texUnit->_ReallyEnabled = 1 << texTarget; } else { /* fixed-function: texture unit is really disabled */ continue; } } /* if we get here, we know this texture unit is enabled */ ctx->Texture._EnabledUnits |= (1 << unit); if (enabledFragTargets) enabledFragUnits |= (1 << unit); if (!fprog) update_tex_combine(ctx, texUnit); } /* Determine which texture coordinate sets are actually needed */ if (fprog) { const GLuint coordMask = (1 << MAX_TEXTURE_COORD_UNITS) - 1; ctx->Texture._EnabledCoordUnits = (fprog->InputsRead >> VARYING_SLOT_TEX0) & coordMask; } else {