mesa: Validate assembly shaders when GLSL shaders are used
authorIan Romanick <ian.d.romanick@intel.com>
Tue, 12 Oct 2010 17:51:47 +0000 (10:51 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Tue, 12 Oct 2010 17:54:28 +0000 (10:54 -0700)
If an GLSL shader is used that does not provide all stages and
assembly shaders are provided for the missing stages, validate the
assembly shaders.

Fixes bugzilla #30787 and piglit tests glsl-invalid-asm0[12].

NOTE: this is a candidate for the 7.9 branch.

src/mesa/main/context.c

index 00132514d77d5e971cf245ca782f747e273eed8e..284c8b1d37bbfe12cd77cebff36ac5a9fb80ef82 100644 (file)
 #endif
 
 #include "glsl_parser_extras.h"
-
+#include <stdbool.h>
 
 
 #ifndef MESA_VERBOSE
@@ -1699,11 +1699,17 @@ _mesa_set_mvp_with_dp4( GLcontext *ctx,
 GLboolean
 _mesa_valid_to_render(GLcontext *ctx, const char *where)
 {
+   bool vert_from_glsl_shader = false;
+   bool geom_from_glsl_shader = false;
+   bool frag_from_glsl_shader = false;
+
    /* This depends on having up to date derived state (shaders) */
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
    if (ctx->Shader.CurrentProgram) {
+      unsigned i;
+
       /* using shaders */
       if (!ctx->Shader.CurrentProgram->LinkStatus) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
@@ -1720,20 +1726,42 @@ _mesa_valid_to_render(GLcontext *ctx, const char *where)
          }
       }
 #endif
-   }
-   else {
-      if (ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "%s(vertex program not valid)", where);
-         return GL_FALSE;
-      }
-      if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "%s(fragment program not valid)", where);
-         return GL_FALSE;
+
+      /* Figure out which shader stages are provided by the GLSL program.  For
+       * any stages that are not provided, the corresponding assembly shader
+       * target will be validated below.
+       */
+      for (i = 0; i < ctx->Shader.CurrentProgram->_NumLinkedShaders; i++) {
+        switch (ctx->Shader.CurrentProgram->_LinkedShaders[i]->Type) {
+        case GL_VERTEX_SHADER: vert_from_glsl_shader = true; break;
+        case GL_GEOMETRY_SHADER_ARB: geom_from_glsl_shader = true; break;
+        case GL_FRAGMENT_SHADER: frag_from_glsl_shader = true; break;
+        }
       }
    }
 
+
+   /* Any shader stages that are not supplied by the GLSL shader and have
+    * assembly shaders enabled must now be validated.
+    */
+   if (!vert_from_glsl_shader
+       && ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                 "%s(vertex program not valid)", where);
+      return GL_FALSE;
+   }
+
+   /* FINISHME: If GL_NV_geometry_program4 is ever supported, the current
+    * FINISHME: geometry program should validated here.
+    */
+
+   if (!frag_from_glsl_shader
+       && ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                 "%s(fragment program not valid)", where);
+      return GL_FALSE;
+   }
+
    if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                   "%s(incomplete framebuffer)", where);