summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-10-29 11:28:38 -0700
committerEric Anholt <[email protected]>2010-10-29 11:28:38 -0700
commita974949f3b586eee2bc8d6d97d3adb71796fe167 (patch)
tree0fcda3bff1e1ebf89a1bd65a61a7b0dfeb7255de /src/mesa
parent34e8801b9c04960337fa59d4b24f9df68a06a0d9 (diff)
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
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/drivers/common/meta.c37
-rw-r--r--src/mesa/main/shaderapi.c97
-rw-r--r--src/mesa/main/shaderapi.h8
3 files changed, 80 insertions, 62 deletions
diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index 1bfd76a665d..c48709714d7 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -52,6 +52,7 @@
#include "main/readpix.h"
#include "main/scissor.h"
#include "main/shaderapi.h"
+#include "main/shaderobj.h"
#include "main/state.h"
#include "main/stencil.h"
#include "main/texobj.h"
@@ -143,10 +144,10 @@ struct save_state
struct gl_vertex_program *VertexProgram;
GLboolean FragmentProgramEnabled;
struct gl_fragment_program *FragmentProgram;
- GLuint VertexShader;
- GLuint GeometryShader;
- GLuint FragmentShader;
- GLuint ActiveShader;
+ struct gl_shader_program *VertexShader;
+ struct gl_shader_program *GeometryShader;
+ struct gl_shader_program *FragmentShader;
+ struct gl_shader_program *ActiveShader;
/** META_STENCIL_TEST */
struct gl_stencil_attrib Stencil;
@@ -436,14 +437,14 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
}
if (ctx->Extensions.ARB_shader_objects) {
- save->VertexShader = ctx->Shader.CurrentVertexProgram ?
- ctx->Shader.CurrentVertexProgram->Name : 0;
- save->GeometryShader = ctx->Shader.CurrentGeometryProgram ?
- ctx->Shader.CurrentGeometryProgram->Name : 0;
- save->FragmentShader = ctx->Shader.CurrentFragmentProgram ?
- ctx->Shader.CurrentFragmentProgram->Name : 0;
- save->ActiveShader = ctx->Shader.ActiveProgram ?
- ctx->Shader.ActiveProgram->Name : 0;
+ _mesa_reference_shader_program(ctx, &save->VertexShader,
+ ctx->Shader.CurrentVertexProgram);
+ _mesa_reference_shader_program(ctx, &save->GeometryShader,
+ ctx->Shader.CurrentGeometryProgram);
+ _mesa_reference_shader_program(ctx, &save->FragmentShader,
+ ctx->Shader.CurrentFragmentProgram);
+ _mesa_reference_shader_program(ctx, &save->ActiveShader,
+ ctx->Shader.CurrentFragmentProgram);
_mesa_UseProgramObjectARB(0);
}
@@ -675,16 +676,18 @@ _mesa_meta_end(struct gl_context *ctx)
}
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)
- _mesa_UseShaderProgramEXT(GL_GEOMETRY_SHADER_ARB,
- save->GeometryShader);
+ _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB,
+ save->GeometryShader);
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) {
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 622285debb3..9717e005597 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -936,9 +936,9 @@ print_shader_info(const struct gl_shader_program *shProg)
/**
* Use the named shader program for subsequent glUniform calls
*/
-static void
-active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
- const char *caller)
+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,
@@ -1003,45 +1003,16 @@ use_shader_program(struct gl_context *ctx, GLenum type,
* Use the named shader program for subsequent rendering.
*/
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;
- 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_GEOMETRY_SHADER_ARB, shProg)
|| changed;
changed = use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg)
|| changed;
- active_program(ctx, shProg, "glUseProgram");
+ _mesa_active_program(ctx, shProg, "glUseProgram");
if (changed) {
FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
@@ -1614,8 +1585,39 @@ void GLAPIENTRY
_mesa_UseProgramObjectARB(GLhandleARB program)
{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg;
+ struct gl_transform_feedback_object *obj =
+ ctx->TransformFeedback.CurrentObject;
+
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
+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
_mesa_UseShaderProgramEXT(GLenum type, GLuint program)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg = NULL;
- bool changed = false;
if (!validate_shader_target(ctx, 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);
- if (changed)
- FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
-
- if (ctx->Driver.UseProgram)
- ctx->Driver.UseProgram(ctx, shProg);
- return;
+ _mesa_use_shader_program(ctx, type, shProg);
}
void GLAPIENTRY
@@ -1779,7 +1788,7 @@ _mesa_ActiveProgramEXT(GLuint program)
? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT")
: NULL;
- active_program(ctx, shProg, "glActiveProgramEXT");
+ _mesa_active_program(ctx, shProg, "glActiveProgramEXT");
return;
}
diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h
index db316ab6a75..df78351411c 100644
--- a/src/mesa/main/shaderapi.h
+++ b/src/mesa/main/shaderapi.h
@@ -39,8 +39,11 @@ _mesa_copy_string(GLchar *dst, GLsizei maxLength,
GLsizei *length, const GLchar *src);
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
_mesa_init_shader_dispatch(struct _glapi_table *exec);
@@ -172,6 +175,9 @@ _mesa_ShaderBinary(GLint n, const GLuint *shaders, GLenum binaryformat,
extern void GLAPIENTRY
_mesa_ProgramParameteriARB(GLuint program, GLenum pname,
GLint value);
+void
+_mesa_use_shader_program(struct gl_context *ctx, GLenum type,
+ struct gl_shader_program *shProg);
extern void GLAPIENTRY
_mesa_UseShaderProgramEXT(GLenum type, GLuint program);