mesa: Make metaops use program refcounts instead of names.

Fixes failure on restoring state when the program was active but
deleted, and the name no longer exists.

Bug #31194
This commit is contained in:
Eric Anholt
2010-10-29 11:28:38 -07:00
parent 34e8801b9c
commit a974949f3b
3 changed files with 80 additions and 62 deletions

View File

@@ -52,6 +52,7 @@
#include "main/readpix.h" #include "main/readpix.h"
#include "main/scissor.h" #include "main/scissor.h"
#include "main/shaderapi.h" #include "main/shaderapi.h"
#include "main/shaderobj.h"
#include "main/state.h" #include "main/state.h"
#include "main/stencil.h" #include "main/stencil.h"
#include "main/texobj.h" #include "main/texobj.h"
@@ -143,10 +144,10 @@ struct save_state
struct gl_vertex_program *VertexProgram; struct gl_vertex_program *VertexProgram;
GLboolean FragmentProgramEnabled; GLboolean FragmentProgramEnabled;
struct gl_fragment_program *FragmentProgram; struct gl_fragment_program *FragmentProgram;
GLuint VertexShader; struct gl_shader_program *VertexShader;
GLuint GeometryShader; struct gl_shader_program *GeometryShader;
GLuint FragmentShader; struct gl_shader_program *FragmentShader;
GLuint ActiveShader; struct gl_shader_program *ActiveShader;
/** META_STENCIL_TEST */ /** META_STENCIL_TEST */
struct gl_stencil_attrib Stencil; struct gl_stencil_attrib Stencil;
@@ -436,14 +437,14 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
} }
if (ctx->Extensions.ARB_shader_objects) { if (ctx->Extensions.ARB_shader_objects) {
save->VertexShader = ctx->Shader.CurrentVertexProgram ? _mesa_reference_shader_program(ctx, &save->VertexShader,
ctx->Shader.CurrentVertexProgram->Name : 0; ctx->Shader.CurrentVertexProgram);
save->GeometryShader = ctx->Shader.CurrentGeometryProgram ? _mesa_reference_shader_program(ctx, &save->GeometryShader,
ctx->Shader.CurrentGeometryProgram->Name : 0; ctx->Shader.CurrentGeometryProgram);
save->FragmentShader = ctx->Shader.CurrentFragmentProgram ? _mesa_reference_shader_program(ctx, &save->FragmentShader,
ctx->Shader.CurrentFragmentProgram->Name : 0; ctx->Shader.CurrentFragmentProgram);
save->ActiveShader = ctx->Shader.ActiveProgram ? _mesa_reference_shader_program(ctx, &save->ActiveShader,
ctx->Shader.ActiveProgram->Name : 0; ctx->Shader.CurrentFragmentProgram);
_mesa_UseProgramObjectARB(0); _mesa_UseProgramObjectARB(0);
} }
@@ -675,16 +676,18 @@ _mesa_meta_end(struct gl_context *ctx)
} }
if (ctx->Extensions.ARB_vertex_shader) if (ctx->Extensions.ARB_vertex_shader)
_mesa_UseShaderProgramEXT(GL_VERTEX_SHADER, save->VertexShader); _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader);
if (ctx->Extensions.ARB_geometry_shader4) if (ctx->Extensions.ARB_geometry_shader4)
_mesa_UseShaderProgramEXT(GL_GEOMETRY_SHADER_ARB, _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB,
save->GeometryShader); save->GeometryShader);
if (ctx->Extensions.ARB_fragment_shader) if (ctx->Extensions.ARB_fragment_shader)
_mesa_UseShaderProgramEXT(GL_FRAGMENT_SHADER, save->FragmentShader); _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER,
save->FragmentShader);
_mesa_ActiveProgramEXT(save->ActiveShader); _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram,
save->ActiveShader);
} }
if (state & META_STENCIL_TEST) { if (state & META_STENCIL_TEST) {

View File

@@ -936,9 +936,9 @@ print_shader_info(const struct gl_shader_program *shProg)
/** /**
* Use the named shader program for subsequent glUniform calls * Use the named shader program for subsequent glUniform calls
*/ */
static void void
active_program(struct gl_context *ctx, struct gl_shader_program *shProg, _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
const char *caller) const char *caller)
{ {
if ((shProg != NULL) && !shProg->LinkStatus) { if ((shProg != NULL) && !shProg->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION, _mesa_error(ctx, GL_INVALID_OPERATION,
@@ -1003,45 +1003,16 @@ use_shader_program(struct gl_context *ctx, GLenum type,
* Use the named shader program for subsequent rendering. * Use the named shader program for subsequent rendering.
*/ */
void void
_mesa_use_program(struct gl_context *ctx, GLuint program) _mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg)
{ {
struct gl_shader_program *shProg;
struct gl_transform_feedback_object *obj =
ctx->TransformFeedback.CurrentObject;
bool changed = false; bool changed = false;
if (obj->Active) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUseProgram(transform feedback active)");
return;
}
if (program) {
shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
if (!shProg) {
return;
}
if (!shProg->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUseProgram(program %u not linked)", program);
return;
}
/* debug code */
if (ctx->Shader.Flags & GLSL_USE_PROG) {
print_shader_info(shProg);
}
}
else {
shProg = NULL;
}
changed = use_shader_program(ctx, GL_VERTEX_SHADER, shProg); changed = use_shader_program(ctx, GL_VERTEX_SHADER, shProg);
changed = use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg) changed = use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg)
|| changed; || changed;
changed = use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg) changed = use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg)
|| changed; || changed;
active_program(ctx, shProg, "glUseProgram"); _mesa_active_program(ctx, shProg, "glUseProgram");
if (changed) { if (changed) {
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
@@ -1614,8 +1585,39 @@ void GLAPIENTRY
_mesa_UseProgramObjectARB(GLhandleARB program) _mesa_UseProgramObjectARB(GLhandleARB program)
{ {
GET_CURRENT_CONTEXT(ctx); GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
struct gl_transform_feedback_object *obj =
ctx->TransformFeedback.CurrentObject;
FLUSH_VERTICES(ctx, _NEW_PROGRAM); FLUSH_VERTICES(ctx, _NEW_PROGRAM);
_mesa_use_program(ctx, program);
if (obj->Active) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUseProgram(transform feedback active)");
return;
}
if (program) {
shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
if (!shProg) {
return;
}
if (!shProg->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glUseProgram(program %u not linked)", program);
return;
}
/* debug code */
if (ctx->Shader.Flags & GLSL_USE_PROG) {
print_shader_info(shProg);
}
}
else {
shProg = NULL;
}
_mesa_use_program(ctx, shProg);
} }
@@ -1731,12 +1733,25 @@ _mesa_ProgramParameteriARB(GLuint program, GLenum pname,
#endif #endif
void
_mesa_use_shader_program(struct gl_context *ctx, GLenum type,
struct gl_shader_program *shProg)
{
bool changed;
changed = use_shader_program(ctx, type, shProg);
if (changed)
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
if (ctx->Driver.UseProgram)
ctx->Driver.UseProgram(ctx, shProg);
}
void GLAPIENTRY void GLAPIENTRY
_mesa_UseShaderProgramEXT(GLenum type, GLuint program) _mesa_UseShaderProgramEXT(GLenum type, GLuint program)
{ {
GET_CURRENT_CONTEXT(ctx); GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg = NULL; struct gl_shader_program *shProg = NULL;
bool changed = false;
if (!validate_shader_target(ctx, type)) { if (!validate_shader_target(ctx, type)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)"); _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)");
@@ -1762,13 +1777,7 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program)
} }
} }
changed = use_shader_program(ctx, type, shProg); _mesa_use_shader_program(ctx, type, shProg);
if (changed)
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
if (ctx->Driver.UseProgram)
ctx->Driver.UseProgram(ctx, shProg);
return;
} }
void GLAPIENTRY void GLAPIENTRY
@@ -1779,7 +1788,7 @@ _mesa_ActiveProgramEXT(GLuint program)
? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT") ? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT")
: NULL; : NULL;
active_program(ctx, shProg, "glActiveProgramEXT"); _mesa_active_program(ctx, shProg, "glActiveProgramEXT");
return; return;
} }

View File

@@ -39,8 +39,11 @@ _mesa_copy_string(GLchar *dst, GLsizei maxLength,
GLsizei *length, const GLchar *src); GLsizei *length, const GLchar *src);
extern void extern void
_mesa_use_program(struct gl_context *ctx, GLuint program); _mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg);
extern void
_mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
const char *caller);
extern void extern void
_mesa_init_shader_dispatch(struct _glapi_table *exec); _mesa_init_shader_dispatch(struct _glapi_table *exec);
@@ -172,6 +175,9 @@ _mesa_ShaderBinary(GLint n, const GLuint *shaders, GLenum binaryformat,
extern void GLAPIENTRY extern void GLAPIENTRY
_mesa_ProgramParameteriARB(GLuint program, GLenum pname, _mesa_ProgramParameteriARB(GLuint program, GLenum pname,
GLint value); GLint value);
void
_mesa_use_shader_program(struct gl_context *ctx, GLenum type,
struct gl_shader_program *shProg);
extern void GLAPIENTRY extern void GLAPIENTRY
_mesa_UseShaderProgramEXT(GLenum type, GLuint program); _mesa_UseShaderProgramEXT(GLenum type, GLuint program);