mesa: Make metaops use program refcounts instead of names.
authorEric Anholt <eric@anholt.net>
Fri, 29 Oct 2010 18:28:38 +0000 (11:28 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 29 Oct 2010 18:28:38 +0000 (11:28 -0700)
Fixes failure on restoring state when the program was active but
deleted, and the name no longer exists.

Bug #31194

src/mesa/drivers/common/meta.c
src/mesa/main/shaderapi.c
src/mesa/main/shaderapi.h

index 1bfd76a665dfc73242461e01d579a92e47b47aff..c48709714d74a8dc1c4f849b994884343774cdff 100644 (file)
@@ -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) {
index 622285debb3edc982cb49348b0baf1a21c30ca72..9717e005597f7360912cc5183811b616a4d1cc52 100644 (file)
@@ -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;
 }
 
index db316ab6a75c3d447fb3459d9806c9567ce9c45d..df78351411c6dbb0e3694e00bff6b659582630b4 100644 (file)
@@ -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);