/** * Use the named shader program for subsequent glUniform calls */ void _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg, const char *caller) { if ((shProg != NULL) && !shProg->LinkStatus) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program %u not linked)", caller, shProg->Name); return; } if (ctx->Shader.ActiveProgram != shProg) { _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, shProg); } }
void brw_meta_fast_clear_free(struct brw_context *brw) { struct brw_fast_clear_state *clear = brw->fast_clear_state; GET_CURRENT_CONTEXT(old_context); if (clear == NULL) return; _mesa_make_current(&brw->ctx, NULL, NULL); _mesa_DeleteVertexArrays(1, &clear->vao); _mesa_reference_buffer_object(&brw->ctx, &clear->buf_obj, NULL); _mesa_reference_shader_program(&brw->ctx, &clear->shader_prog, NULL); free(clear); if (old_context) _mesa_make_current(old_context, old_context->WinSysDrawBuffer, old_context->WinSysReadBuffer); else _mesa_make_current(NULL, NULL, NULL); }
/** * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's * DeleteProgramARB. */ static void delete_shader_program(struct gl_context *ctx, GLuint name) { /* * NOTE: deleting shaders/programs works a bit differently than * texture objects (and buffer objects, etc). Shader/program * handles/IDs exist in the hash table until the object is really * deleted (refcount==0). With texture objects, the handle/ID is * removed from the hash table in glDeleteTextures() while the tex * object itself might linger until its refcount goes to zero. */ struct gl_shader_program *shProg; shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram"); if (!shProg) return; if (!shProg->DeletePending) { shProg->DeletePending = GL_TRUE; /* effectively, decr shProg's refcount */ _mesa_reference_shader_program(ctx, &shProg, NULL); } }
/** * 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.CurrentVertexProgram; const struct gl_shader_program *gsProg = ctx->Shader.CurrentGeometryProgram; struct gl_shader_program *fsProg = ctx->Shader.CurrentFragmentProgram; 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; 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); } /* 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, MESA_GEOMETRY_PROGRAM, (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); } } return new_state; }
static bool use_shader_program(struct gl_context *ctx, GLenum type, struct gl_shader_program *shProg) { struct gl_shader_program **target; switch (type) { #if FEATURE_ARB_vertex_shader case GL_VERTEX_SHADER: target = &ctx->Shader.CurrentVertexProgram; if ((shProg == NULL) || (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)) { shProg = NULL; } break; #endif #if FEATURE_ARB_geometry_shader4 case GL_GEOMETRY_SHADER_ARB: target = &ctx->Shader.CurrentGeometryProgram; if ((shProg == NULL) || (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL)) { shProg = NULL; } break; #endif #if FEATURE_ARB_fragment_shader case GL_FRAGMENT_SHADER: target = &ctx->Shader.CurrentFragmentProgram; if ((shProg == NULL) || (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)) { shProg = NULL; } break; #endif default: return false; } if (*target != shProg) { FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); /* If the shader is also bound as the current rendering shader, unbind * it from that binding point as well. This ensures that the correct * semantics of glDeleteProgram are maintained. */ switch (type) { #if FEATURE_ARB_vertex_shader case GL_VERTEX_SHADER: /* Empty for now. */ break; #endif #if FEATURE_ARB_geometry_shader4 case GL_GEOMETRY_SHADER_ARB: /* Empty for now. */ break; #endif #if FEATURE_ARB_fragment_shader case GL_FRAGMENT_SHADER: if (*target == ctx->Shader._CurrentFragmentProgram) { _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram, NULL); } break; #endif } _mesa_reference_shader_program(ctx, target, shProg); return true; } return false; }
/** * Free the per-context shader-related state. */ void _mesa_free_shader_state(GLcontext *ctx) { _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL); }