/** * Update the ctx->Vertex/Geometry/FragmentProgram._Current pointers to point * to the current/active programs. Then call ctx->Driver.BindProgram() to * tell the driver which programs to use. * * 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) { const struct gl_shader_program *vsProg = ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]; const struct gl_shader_program *gsProg = ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]; struct gl_shader_program *fsProg = ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]; const struct gl_shader_program *csProg = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current; const struct gl_compute_program *prevCP = ctx->ComputeProgram._Current; GLbitfield new_state = 0x0; /* * 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. 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 && fsProg->LinkStatus && fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) { /* Use GLSL fragment shader */ _mesa_reference_shader_program(ctx, &ctx->_Shader->_CurrentFragmentProgram, fsProg); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, gl_fragment_program(fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); } else if (ctx->FragmentProgram._Enabled) { /* Use user-defined fragment program */ _mesa_reference_shader_program(ctx, &ctx->_Shader->_CurrentFragmentProgram, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, ctx->FragmentProgram.Current); _mesa_reference_fragprog(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_shader_program(ctx, &ctx->_Shader->_CurrentFragmentProgram, f); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, gl_fragment_program(f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, gl_fragment_program(f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); } else { /* No fragment program */ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL); } if (gsProg && gsProg->LinkStatus && gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) { /* Use GLSL geometry shader */ _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, gl_geometry_program(gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program)); } else { /* No geometry program */ _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); } /* Examine vertex program after fragment program as * _mesa_get_fixed_func_vertex_program() needs to know active * fragprog inputs. */ if (vsProg && vsProg->LinkStatus && vsProg->_LinkedShaders[MESA_SHADER_VERTEX]) { /* Use GLSL vertex shader */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, gl_vertex_program(vsProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program)); } else if (ctx->VertexProgram._Enabled) { /* Use user-defined vertex program */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, ctx->VertexProgram.Current); } else if (ctx->VertexProgram._MaintainTnlProgram) { /* Use vertex program generated from fixed-function state */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, _mesa_get_fixed_func_vertex_program(ctx)); _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, ctx->VertexProgram._Current); } else { /* no vertex program */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); } if (csProg && csProg->LinkStatus && csProg->_LinkedShaders[MESA_SHADER_COMPUTE]) { /* Use GLSL compute shader */ _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current, gl_compute_program(csProg->_LinkedShaders[MESA_SHADER_COMPUTE]->Program)); } else { /* no compute program */ _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current, NULL); } /* Let the driver know what's happening: */ if (ctx->FragmentProgram._Current != prevFP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, (struct gl_program *) ctx->FragmentProgram._Current); } } if (ctx->GeometryProgram._Current != prevGP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { ctx->Driver.BindProgram(ctx, GL_GEOMETRY_PROGRAM_NV, (struct gl_program *) ctx->GeometryProgram._Current); } } if (ctx->VertexProgram._Current != prevVP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, (struct gl_program *) ctx->VertexProgram._Current); } } if (ctx->ComputeProgram._Current != prevCP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { ctx->Driver.BindProgram(ctx, GL_COMPUTE_PROGRAM_NV, (struct gl_program *) ctx->ComputeProgram._Current); } } return new_state; }
/** * Update vertex/fragment program state. In particular, update these fields: * ctx->VertexProgram._Current * ctx->VertexProgram._TnlProgram, * These point to the highest priority enabled vertex/fragment program or are * NULL if fixed-function processing is to be done. * * 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(GLcontext *ctx) { const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; GLbitfield new_state = 0x0; /* * 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. 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 (shProg && shProg->LinkStatus && shProg->FragmentProgram) { /* Use shader programs */ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, shProg->FragmentProgram); } else if (ctx->FragmentProgram._Enabled) { /* use user-defined vertex program */ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, ctx->FragmentProgram.Current); } else if (ctx->FragmentProgram._MaintainTexEnvProgram) { /* Use fragment program generated from fixed-function state. */ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, _mesa_get_fixed_func_fragment_program(ctx)); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, ctx->FragmentProgram._Current); } else { /* no fragment program */ _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); } /* Examine vertex program after fragment program as * _mesa_get_fixed_func_vertex_program() needs to know active * fragprog inputs. */ if (shProg && shProg->LinkStatus && shProg->VertexProgram) { /* Use shader programs */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, shProg->VertexProgram); } else if (ctx->VertexProgram._Enabled) { /* use user-defined vertex program */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, ctx->VertexProgram.Current); } else if (ctx->VertexProgram._MaintainTnlProgram) { /* Use vertex program generated from fixed-function state. */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, _mesa_get_fixed_func_vertex_program(ctx)); _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, ctx->VertexProgram._Current); } else { /* no vertex program */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); } /* Let the driver know what's happening: */ if (ctx->FragmentProgram._Current != prevFP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, (struct gl_program *) ctx->FragmentProgram._Current); } } if (ctx->VertexProgram._Current != prevVP) { new_state |= _NEW_PROGRAM; if (ctx->Driver.BindProgram) { ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, (struct gl_program *) ctx->VertexProgram._Current); } } return new_state; }
/** * 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; }