/** * \note This routine refers to derived texture matrix values to * compute the ENABLE_TEXMAT flags, but is only called on * _NEW_TEXTURE_OBJECT/STATE. On changes to _NEW_TEXTURE_MATRIX, * the ENABLE_TEXMAT flags are updated by _mesa_update_texture_matrices, * above. * * \param ctx GL context. */ void _mesa_update_texture_state(struct gl_context *ctx) { struct gl_program *prog[MESA_SHADER_STAGES]; int i; int old_max_unit = ctx->Texture._MaxEnabledTexImageUnit; BITSET_DECLARE(enabled_texture_units, MAX_COMBINED_TEXTURE_IMAGE_UNITS); memcpy(prog, ctx->_Shader->CurrentProgram, sizeof(prog)); if (prog[MESA_SHADER_FRAGMENT] == NULL && _mesa_arb_fragment_program_enabled(ctx)) { prog[MESA_SHADER_FRAGMENT] = ctx->FragmentProgram.Current; } /* TODO: only set this if there are actual changes */ ctx->NewState |= _NEW_TEXTURE_OBJECT | _NEW_TEXTURE_STATE; ctx->Texture._GenFlags = 0x0; ctx->Texture._TexMatEnabled = 0x0; ctx->Texture._TexGenEnabled = 0x0; ctx->Texture._MaxEnabledTexImageUnit = -1; ctx->Texture._EnabledCoordUnits = 0x0; memset(&enabled_texture_units, 0, sizeof(enabled_texture_units)); /* First, walk over our programs pulling in all the textures for them. * Programs dictate specific texture targets to be enabled, and for a draw * call to be valid they can't conflict about which texture targets are * used. */ update_program_texture_state(ctx, prog, enabled_texture_units); /* Also pull in any textures necessary for fixed function fragment shading. */ if (!prog[MESA_SHADER_FRAGMENT]) update_ff_texture_state(ctx, enabled_texture_units); /* Now, clear out the _Current of any disabled texture units. */ for (i = 0; i <= ctx->Texture._MaxEnabledTexImageUnit; i++) { if (!BITSET_TEST(enabled_texture_units, i)) _mesa_reference_texobj(&ctx->Texture.Unit[i]._Current, NULL); } for (i = ctx->Texture._MaxEnabledTexImageUnit + 1; i <= old_max_unit; i++) { _mesa_reference_texobj(&ctx->Texture.Unit[i]._Current, NULL); } /* add fallback texture for SampleMapATI if there is nothing */ if (_mesa_ati_fragment_shader_enabled(ctx) && ctx->ATIFragmentShader.Current->Program) fix_missing_textures_for_atifs(ctx, ctx->ATIFragmentShader.Current->Program, enabled_texture_units); if (!prog[MESA_SHADER_FRAGMENT] || !prog[MESA_SHADER_VERTEX]) update_texgen(ctx); }
/** * Update the ctx->*Program._Current pointers to point to the * current/active programs. * * Programs may come from 3 sources: GLSL shaders, ARB/NV_vertex/fragment * programs or programs derived from fixed-function state. * * This function needs to be called after texture state validation in case * we're generating a fragment program from fixed-function texture state. * * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex * or fragment program is being used. */ static GLbitfield update_program(struct gl_context *ctx) { struct gl_program *vsProg = ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]; struct gl_program *tcsProg = ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL]; struct gl_program *tesProg = ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; struct gl_program *gsProg = ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]; struct gl_program *fsProg = ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]; struct gl_program *csProg = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; const struct gl_program *prevVP = ctx->VertexProgram._Current; const struct gl_program *prevFP = ctx->FragmentProgram._Current; const struct gl_program *prevGP = ctx->GeometryProgram._Current; const struct gl_program *prevTCP = ctx->TessCtrlProgram._Current; const struct gl_program *prevTEP = ctx->TessEvalProgram._Current; const struct gl_program *prevCP = ctx->ComputeProgram._Current; /* * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current * pointers to the programs that should be used for rendering. If either * is NULL, use fixed-function code paths. * * These programs may come from several sources. The priority is as * follows: * 1. OpenGL 2.0/ARB vertex/fragment shaders * 2. ARB/NV vertex/fragment programs * 3. ATI fragment shader * 4. Programs derived from fixed-function state. * * Note: it's possible for a vertex shader to get used with a fragment * program (and vice versa) here, but in practice that shouldn't ever * come up, or matter. */ if (fsProg) { /* Use GLSL fragment shader */ _mesa_reference_program(ctx, &ctx->FragmentProgram._Current, fsProg); _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); } else if (_mesa_arb_fragment_program_enabled(ctx)) { /* Use user-defined fragment program */ _mesa_reference_program(ctx, &ctx->FragmentProgram._Current, ctx->FragmentProgram.Current); _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); } else if (_mesa_ati_fragment_shader_enabled(ctx) && ctx->ATIFragmentShader.Current->Program) { /* Use the enabled ATI fragment shader's associated program */ _mesa_reference_program(ctx, &ctx->FragmentProgram._Current, ctx->ATIFragmentShader.Current->Program); _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); } else if (ctx->FragmentProgram._MaintainTexEnvProgram) { /* Use fragment program generated from fixed-function state */ struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx); _mesa_reference_program(ctx, &ctx->FragmentProgram._Current, f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program); _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram, f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program); } else { /* No fragment program */ _mesa_reference_program(ctx, &ctx->FragmentProgram._Current, NULL); _mesa_reference_program(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); } if (gsProg) { /* Use GLSL geometry shader */ _mesa_reference_program(ctx, &ctx->GeometryProgram._Current, gsProg); } else { /* No geometry program */ _mesa_reference_program(ctx, &ctx->GeometryProgram._Current, NULL); } if (tesProg) { /* Use GLSL tessellation evaluation shader */ _mesa_reference_program(ctx, &ctx->TessEvalProgram._Current, tesProg); } else { /* No tessellation evaluation program */ _mesa_reference_program(ctx, &ctx->TessEvalProgram._Current, NULL); } if (tcsProg) { /* Use GLSL tessellation control shader */ _mesa_reference_program(ctx, &ctx->TessCtrlProgram._Current, tcsProg); } else { /* No tessellation control program */ _mesa_reference_program(ctx, &ctx->TessCtrlProgram._Current, NULL); } /* Examine vertex program after fragment program as * _mesa_get_fixed_func_vertex_program() needs to know active * fragprog inputs. */ if (vsProg) { /* Use GLSL vertex shader */ assert(VP_MODE_SHADER == ctx->VertexProgram._VPMode); _mesa_reference_program(ctx, &ctx->VertexProgram._Current, vsProg); } else if (_mesa_arb_vertex_program_enabled(ctx)) { /* Use user-defined vertex program */ assert(VP_MODE_SHADER == ctx->VertexProgram._VPMode); _mesa_reference_program(ctx, &ctx->VertexProgram._Current, ctx->VertexProgram.Current); } else if (ctx->VertexProgram._MaintainTnlProgram) { /* Use vertex program generated from fixed-function state */ assert(VP_MODE_FF == ctx->VertexProgram._VPMode); _mesa_reference_program(ctx, &ctx->VertexProgram._Current, _mesa_get_fixed_func_vertex_program(ctx)); _mesa_reference_program(ctx, &ctx->VertexProgram._TnlProgram, ctx->VertexProgram._Current); } else { /* no vertex program */ assert(VP_MODE_FF == ctx->VertexProgram._VPMode); _mesa_reference_program(ctx, &ctx->VertexProgram._Current, NULL); } if (csProg) { /* Use GLSL compute shader */ _mesa_reference_program(ctx, &ctx->ComputeProgram._Current, csProg); } else { /* no compute program */ _mesa_reference_program(ctx, &ctx->ComputeProgram._Current, NULL); } /* Let the driver know what's happening: */ if (ctx->FragmentProgram._Current != prevFP || ctx->VertexProgram._Current != prevVP || ctx->GeometryProgram._Current != prevGP || ctx->TessEvalProgram._Current != prevTEP || ctx->TessCtrlProgram._Current != prevTCP || ctx->ComputeProgram._Current != prevCP) return _NEW_PROGRAM; return 0; }
/** * Check if any fragment operations are in effect which might effect * glDraw/CopyPixels. */ bool intel_check_blit_fragment_ops(struct gl_context * ctx, bool src_alpha_is_one) { if (ctx->NewState) _mesa_update_state(ctx); if (_mesa_arb_fragment_program_enabled(ctx)) { DBG("fallback due to fragment program\n"); return false; } if (ctx->Color.BlendEnabled && (effective_func(ctx->Color.Blend[0].SrcRGB, src_alpha_is_one) != GL_ONE || effective_func(ctx->Color.Blend[0].DstRGB, src_alpha_is_one) != GL_ZERO || ctx->Color.Blend[0].EquationRGB != GL_FUNC_ADD || effective_func(ctx->Color.Blend[0].SrcA, src_alpha_is_one) != GL_ONE || effective_func(ctx->Color.Blend[0].DstA, src_alpha_is_one) != GL_ZERO || ctx->Color.Blend[0].EquationA != GL_FUNC_ADD)) { DBG("fallback due to blend\n"); return false; } if (ctx->Texture._MaxEnabledTexImageUnit != -1) { DBG("fallback due to texturing\n"); return false; } if (!(ctx->Color.ColorMask[0][0] && ctx->Color.ColorMask[0][1] && ctx->Color.ColorMask[0][2] && ctx->Color.ColorMask[0][3])) { DBG("fallback due to color masking\n"); return false; } if (ctx->Color.AlphaEnabled) { DBG("fallback due to alpha\n"); return false; } if (ctx->Depth.Test) { DBG("fallback due to depth test\n"); return false; } if (ctx->Fog.Enabled) { DBG("fallback due to fog\n"); return false; } if (ctx->_ImageTransferState) { DBG("fallback due to image transfer\n"); return false; } if (_mesa_stencil_is_enabled(ctx)) { DBG("fallback due to image stencil\n"); return false; } if (ctx->RenderMode != GL_RENDER) { DBG("fallback due to render mode\n"); return false; } return true; }