Mesa (master): Track separate programs for each stage

Ian Romanick idr at kemper.freedesktop.org
Wed Oct 27 20:47:14 UTC 2010


Module: Mesa
Branch: master
Commit: 84eba3ef71dfa822e5ff0463032cdd2e3515b888
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=84eba3ef71dfa822e5ff0463032cdd2e3515b888

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Wed Oct 13 13:58:44 2010 -0700

Track separate programs for each stage

The assumption is that all stages are the same program or that
varyings are passed between stages using built-in varyings.

---

 src/mesa/drivers/common/meta.c              |   30 +++++-
 src/mesa/drivers/dri/i965/brw_fs.cpp        |    6 +-
 src/mesa/drivers/dri/i965/brw_wm_state.c    |    4 +-
 src/mesa/main/context.c                     |  150 ++++++++++++++++++---------
 src/mesa/main/mtypes.h                      |   10 ++-
 src/mesa/main/shaderapi.c                   |   89 +++++++++++++---
 src/mesa/main/state.c                       |   16 ++--
 src/mesa/main/texenvprogram.c               |    9 +-
 src/mesa/main/texstate.c                    |   33 ++++---
 src/mesa/state_tracker/st_atom_rasterizer.c |    5 +-
 src/mesa/state_tracker/st_draw.c            |   20 +++-
 src/mesa/state_tracker/st_program.c         |   38 ++++++-
 src/mesa/swrast/s_fragprog.c                |    2 +-
 13 files changed, 297 insertions(+), 115 deletions(-)

diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index 9946bf1..1bfd76a 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -143,7 +143,10 @@ struct save_state
    struct gl_vertex_program *VertexProgram;
    GLboolean FragmentProgramEnabled;
    struct gl_fragment_program *FragmentProgram;
-   GLuint Shader;
+   GLuint VertexShader;
+   GLuint GeometryShader;
+   GLuint FragmentShader;
+   GLuint ActiveShader;
 
    /** META_STENCIL_TEST */
    struct gl_stencil_attrib Stencil;
@@ -433,8 +436,15 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
       }
 
       if (ctx->Extensions.ARB_shader_objects) {
-         save->Shader = ctx->Shader.CurrentProgram ?
-            ctx->Shader.CurrentProgram->Name : 0;
+         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_UseProgramObjectARB(0);
       }
    }
@@ -664,9 +674,17 @@ _mesa_meta_end(struct gl_context *ctx)
 	 _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL);
       }
 
-      if (ctx->Extensions.ARB_shader_objects) {
-         _mesa_UseProgramObjectARB(save->Shader);
-      }
+      if (ctx->Extensions.ARB_vertex_shader)
+	 _mesa_UseShaderProgramEXT(GL_VERTEX_SHADER, save->VertexShader);
+
+      if (ctx->Extensions.ARB_geometry_shader4)
+	 _mesa_UseShaderProgramEXT(GL_GEOMETRY_SHADER_ARB,
+				   save->GeometryShader);
+
+      if (ctx->Extensions.ARB_fragment_shader)
+	 _mesa_UseShaderProgramEXT(GL_FRAGMENT_SHADER, save->FragmentShader);
+
+      _mesa_ActiveProgramEXT(save->ActiveShader);
    }
 
    if (state & META_STENCIL_TEST) {
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 4919394..5f6deb8 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -1186,7 +1186,7 @@ fs_visitor::visit(ir_texture *ir)
    assert(!ir->projector);
 
    sampler = _mesa_get_sampler_uniform_value(ir->sampler,
-					     ctx->Shader.CurrentProgram,
+					     ctx->Shader.CurrentFragmentProgram,
 					     &brw->fragment_program->Base);
    sampler = c->fp->program.Base.SamplerUnits[sampler];
 
@@ -3093,7 +3093,7 @@ fs_visitor::generate_code()
 
    if (INTEL_DEBUG & DEBUG_WM) {
       printf("Native code for fragment shader %d:\n",
-	     ctx->Shader.CurrentProgram->Name);
+	     ctx->Shader.CurrentFragmentProgram->Name);
    }
 
    if_depth_in_loop[loop_stack_depth] = 0;
@@ -3320,7 +3320,7 @@ brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c)
 {
    struct intel_context *intel = &brw->intel;
    struct gl_context *ctx = &intel->ctx;
-   struct gl_shader_program *prog = ctx->Shader.CurrentProgram;
+   struct gl_shader_program *prog = ctx->Shader.CurrentFragmentProgram;
 
    if (!prog)
       return GL_FALSE;
diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c
index 433ccc6..9a27b93 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_state.c
@@ -137,9 +137,9 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key)
    /* If using the fragment shader backend, the program is always
     * 8-wide.
     */
-   if (ctx->Shader.CurrentProgram) {
+   if (ctx->Shader.CurrentFragmentProgram) {
       struct brw_shader *shader = (struct brw_shader *)
-	 ctx->Shader.CurrentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT];
+	 ctx->Shader.CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT];
 
       if (shader != NULL && shader->ir != NULL) {
 	 key->is_glsl = GL_TRUE;
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 3e265fb..3ebe549 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -1697,11 +1697,10 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
-   if (ctx->Shader.CurrentProgram) {
-      struct gl_shader_program *const prog = ctx->Shader.CurrentProgram;
+   if (ctx->Shader.CurrentVertexProgram) {
+      vert_from_glsl_shader = true;
 
-      /* The current shader program must be successfully linked */
-      if (!prog->LinkStatus) {
+      if (!ctx->Shader.CurrentVertexProgram->LinkStatus) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "%s(shader not linked)", where);
          return GL_FALSE;
@@ -1709,34 +1708,56 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
 #if 0 /* not normally enabled */
       {
          char errMsg[100];
-         if (!_mesa_validate_shader_program(ctx, prog, errMsg)) {
+         if (!_mesa_validate_shader_program(ctx,
+					    ctx->Shader.CurrentVertexProgram,
+                                            errMsg)) {
             _mesa_warning(ctx, "Shader program %u is invalid: %s",
-                          prog->Name, errMsg);
+                          ctx->Shader.CurrentVertexProgram->Name, errMsg);
          }
       }
 #endif
+   }
 
-      /* 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.
-       */
-      vert_from_glsl_shader =
-	 prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL;
-      geom_from_glsl_shader =
-	 prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL;
-      frag_from_glsl_shader =
-	 prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL;
+   if (ctx->Shader.CurrentGeometryProgram) {
+      geom_from_glsl_shader = true;
+
+      if (!ctx->Shader.CurrentGeometryProgram->LinkStatus) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(shader not linked)", where);
+         return GL_FALSE;
+      }
+#if 0 /* not normally enabled */
+      {
+         char errMsg[100];
+         if (!_mesa_validate_shader_program(ctx,
+					    ctx->Shader.CurrentGeometryProgram,
+                                            errMsg)) {
+            _mesa_warning(ctx, "Shader program %u is invalid: %s",
+                          ctx->Shader.CurrentGeometryProgram->Name, errMsg);
+         }
+      }
+#endif
    }
 
-   /* If drawing to integer-valued color buffers, there must be an
-    * active fragment shader (GL_EXT_texture_integer).
-    */
-   if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) {
-      if (!frag_from_glsl_shader) {
+   if (ctx->Shader.CurrentFragmentProgram) {
+      frag_from_glsl_shader = true;
+
+      if (!ctx->Shader.CurrentFragmentProgram->LinkStatus) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "%s(integer format but no fragment shader)", where);
+                     "%s(shader not linked)", where);
          return GL_FALSE;
       }
+#if 0 /* not normally enabled */
+      {
+         char errMsg[100];
+         if (!_mesa_validate_shader_program(ctx,
+					    ctx->Shader.CurrentFragmentProgram,
+                                            errMsg)) {
+            _mesa_warning(ctx, "Shader program %u is invalid: %s",
+                          ctx->Shader.CurrentFragmentProgram->Name, errMsg);
+         }
+      }
+#endif
    }
 
    /* Any shader stages that are not supplied by the GLSL shader and have
@@ -1754,11 +1775,21 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
     */
    (void) geom_from_glsl_shader;
 
-   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 (!frag_from_glsl_shader) {
+      if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+	 _mesa_error(ctx, GL_INVALID_OPERATION,
+		     "%s(fragment program not valid)", where);
+	 return GL_FALSE;
+      }
+
+      /* If drawing to integer-valued color buffers, there must be an
+       * active fragment shader (GL_EXT_texture_integer).
+       */
+      if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "%s(integer format but no fragment shader)", where);
+         return GL_FALSE;
+      }
    }
 
    if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
@@ -1769,26 +1800,51 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
 
 #ifdef DEBUG
    if (ctx->Shader.Flags & GLSL_LOG) {
-      struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
-      if (shProg) {
-         if (!shProg->_Used) {
-            /* This is the first time this shader is being used.
-             * Append shader's constants/uniforms to log file.
-             */
-            GLuint i;
-            for (i = 0; i < shProg->NumShaders; i++) {
-               struct gl_shader *sh = shProg->Shaders[i];
-               if (sh->Type == GL_VERTEX_SHADER) {
-                  _mesa_append_uniforms_to_file(sh,
-                                                &shProg->VertexProgram->Base);
-               }
-               else if (sh->Type == GL_FRAGMENT_SHADER) {
-                  _mesa_append_uniforms_to_file(sh,
-                                                &shProg->FragmentProgram->Base);
-               }
-            }
-            shProg->_Used = GL_TRUE;
-         }
+      struct gl_shader_program *shProg[MESA_SHADER_TYPES];
+      unsigned i;
+
+      shProg[MESA_SHADER_VERTEX] = ctx->Shader.CurrentVertexProgram;
+      shProg[MESA_SHADER_GEOMETRY] = ctx->Shader.CurrentGeometryProgram;
+      shProg[MESA_SHADER_FRAGMENT] = ctx->Shader.CurrentFragmentProgram;
+
+      for (i = 0; i < MESA_SHADER_TYPES; i++) {
+	 struct gl_shader *sh;
+
+	 if (shProg[i] == NULL || shProg[i]->_Used
+	     || shProg[i]->_LinkedShaders[i] == NULL)
+	    continue;
+
+	 /* This is the first time this shader is being used.
+	  * Append shader's constants/uniforms to log file.
+	  *
+	  * The logic is a little odd here.  We only want to log data for each
+	  * shader target that will actually be used, and we only want to log
+	  * it once.  It's possible to have a program bound to the vertex
+	  * shader target that also supplied a fragment shader.  If that
+	  * program isn't also bound to the fragment shader target we don't
+	  * want to log its fragment data.
+	  */
+	 sh = shProg[i]->_LinkedShaders[i];
+	 switch (sh->Type) {
+	 case GL_VERTEX_SHADER:
+	    _mesa_append_uniforms_to_file(sh, &shProg[i]->VertexProgram->Base);
+	    break;
+
+	 case GL_GEOMETRY_SHADER_ARB:
+	    _mesa_append_uniforms_to_file(sh,
+					  &shProg[i]->GeometryProgram->Base);
+	    break;
+
+	 case GL_FRAGMENT_SHADER:
+	    _mesa_append_uniforms_to_file(sh,
+					  &shProg[i]->FragmentProgram->Base);
+	    break;
+	 }
+      }
+
+      for (i = 0; i < MESA_SHADER_TYPES; i++) {
+	 if (shProg[i] != NULL)
+	    shProg[i]->_Used = GL_TRUE;
       }
    }
 #endif
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 7863ef3..1b8a804 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2142,9 +2142,15 @@ struct gl_shader_program
 struct gl_shader_state
 {
    /**
-    * Program used for rendering.
+    * Programs used for rendering
+    *
+    * There is a separate program set for each shader stage.  If
+    * GL_EXT_separate_shader_objects is not supported, each of these must point
+    * to \c NULL or to the same program.
     */
-   struct gl_shader_program *CurrentProgram;
+   struct gl_shader_program *CurrentVertexProgram;
+   struct gl_shader_program *CurrentGeometryProgram;
+   struct gl_shader_program *CurrentFragmentProgram;
 
    /**
     * Program used by glUniform calls.
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 26c9a18..e6c7f7a 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -116,7 +116,11 @@ _mesa_init_shader_state(struct gl_context *ctx)
 void
 _mesa_free_shader_state(struct gl_context *ctx)
 {
-   _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
+   _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentVertexProgram, NULL);
+   _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentGeometryProgram,
+				  NULL);
+   _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram,
+				  NULL);
    _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL);
 }
 
@@ -846,7 +850,10 @@ link_program(struct gl_context *ctx, GLuint program)
    if (!shProg)
       return;
 
-   if (obj->Active && shProg == ctx->Shader.CurrentProgram) {
+   if (obj->Active
+       && (shProg == ctx->Shader.CurrentVertexProgram
+	   || shProg == ctx->Shader.CurrentGeometryProgram
+	   || shProg == ctx->Shader.CurrentFragmentProgram)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glLinkProgram(transform feedback active");
       return;
@@ -927,6 +934,54 @@ active_program(struct gl_context *ctx, struct gl_shader_program *shProg,
 }
 
 /**
+ */
+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) {
+      _mesa_reference_shader_program(ctx, target, shProg);
+      return true;
+   }
+
+   return false;
+}
+
+/**
  * Use the named shader program for subsequent rendering.
  */
 void
@@ -935,6 +990,7 @@ _mesa_use_program(struct gl_context *ctx, GLuint program)
    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,
@@ -942,12 +998,6 @@ _mesa_use_program(struct gl_context *ctx, GLuint program)
       return;
    }
 
-   if (ctx->Shader.CurrentProgram &&
-       ctx->Shader.CurrentProgram->Name == program) {
-      /* no-op */
-      return;
-   }
-
    if (program) {
       shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
       if (!shProg) {
@@ -959,8 +1009,6 @@ _mesa_use_program(struct gl_context *ctx, GLuint program)
          return;
       }
 
-      active_program(ctx, shProg, "glUseProgram");
-
       /* debug code */
       if (ctx->Shader.Flags & GLSL_USE_PROG) {
          print_shader_info(shProg);
@@ -970,9 +1018,15 @@ _mesa_use_program(struct gl_context *ctx, GLuint program)
       shProg = NULL;
    }
 
-   if (ctx->Shader.CurrentProgram != shProg) {
+   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");
+
+   if (changed) {
       FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
-      _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
    }
 
    if (ctx->Driver.UseProgram)
@@ -1643,7 +1697,8 @@ void GLAPIENTRY
 _mesa_UseShaderProgramEXT(GLenum type, GLuint program)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_shader_program *shProg;
+   struct gl_shader_program *shProg = NULL;
+   bool changed = false;
 
    if (!validate_shader_target(ctx, type)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)");
@@ -1669,8 +1724,12 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program)
       }
    }
 
-   _mesa_error(ctx, GL_INVALID_OPERATION,
-	       "glUseShaderProgramEXT(NOT YET IMPLEMENTED)");
+   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;
 }
 
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index 5529732..05f4165 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -247,7 +247,9 @@ update_program_enables(struct gl_context *ctx)
 static GLbitfield
 update_program(struct gl_context *ctx)
 {
-   const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
+   const struct gl_shader_program *vsProg = ctx->Shader.CurrentVertexProgram;
+   const struct gl_shader_program *gsProg = ctx->Shader.CurrentGeometryProgram;
+   const 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;
@@ -269,10 +271,10 @@ update_program(struct gl_context *ctx)
     * come up, or matter.
     */
 
-   if (shProg && shProg->LinkStatus && shProg->FragmentProgram) {
+   if (fsProg && fsProg->LinkStatus && fsProg->FragmentProgram) {
       /* Use shader programs */
       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
-                               shProg->FragmentProgram);
+                               fsProg->FragmentProgram);
    }
    else if (ctx->FragmentProgram._Enabled) {
       /* use user-defined vertex program */
@@ -292,10 +294,10 @@ update_program(struct gl_context *ctx)
       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
    }
 
-   if (shProg && shProg->LinkStatus && shProg->GeometryProgram) {
+   if (gsProg && gsProg->LinkStatus && gsProg->GeometryProgram) {
       /* Use shader programs */
       _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current,
-                               shProg->GeometryProgram);
+                               gsProg->GeometryProgram);
    } else {
       /* no fragment program */
       _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL);
@@ -305,10 +307,10 @@ update_program(struct gl_context *ctx)
     * _mesa_get_fixed_func_vertex_program() needs to know active
     * fragprog inputs.
     */
-   if (shProg && shProg->LinkStatus && shProg->VertexProgram) {
+   if (vsProg && vsProg->LinkStatus && vsProg->VertexProgram) {
       /* Use shader programs */
       _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current,
-                            shProg->VertexProgram);
+                            vsProg->VertexProgram);
    }
    else if (ctx->VertexProgram._Enabled) {
       /* use user-defined vertex program */
diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c
index 4647a9c..a8bffe4 100644
--- a/src/mesa/main/texenvprogram.c
+++ b/src/mesa/main/texenvprogram.c
@@ -310,9 +310,10 @@ static GLuint translate_tex_src_bit( GLbitfield bit )
 static GLbitfield get_fp_input_mask( struct gl_context *ctx )
 {
    /* _NEW_PROGRAM */
-   const GLboolean vertexShader = (ctx->Shader.CurrentProgram &&
-				   ctx->Shader.CurrentProgram->LinkStatus &&
-                                   ctx->Shader.CurrentProgram->VertexProgram);
+   const GLboolean vertexShader =
+      (ctx->Shader.CurrentVertexProgram &&
+       ctx->Shader.CurrentVertexProgram->LinkStatus &&
+       ctx->Shader.CurrentVertexProgram->VertexProgram);
    const GLboolean vertexProgram = ctx->VertexProgram._Enabled;
    GLbitfield fp_inputs = 0x0;
 
@@ -377,7 +378,7 @@ static GLbitfield get_fp_input_mask( struct gl_context *ctx )
        * validation (see additional comments in state.c).
        */
       if (vertexShader)
-         vprog = ctx->Shader.CurrentProgram->VertexProgram;
+         vprog = ctx->Shader.CurrentVertexProgram->VertexProgram;
       else
          vprog = ctx->VertexProgram.Current;
 
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 1b0d760..f4d7718 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -496,23 +496,28 @@ update_texture_state( struct gl_context *ctx )
    struct gl_vertex_program *vprog = NULL;
    GLbitfield enabledFragUnits = 0x0;
 
-   if (ctx->Shader.CurrentProgram &&
-       ctx->Shader.CurrentProgram->LinkStatus) {
-      fprog = ctx->Shader.CurrentProgram->FragmentProgram;
-      vprog = ctx->Shader.CurrentProgram->VertexProgram;
+   if (ctx->Shader.CurrentVertexProgram &&
+       ctx->Shader.CurrentVertexProgram->LinkStatus) {
+      vprog = ctx->Shader.CurrentVertexProgram->VertexProgram;
+   } else if (ctx->VertexProgram._Enabled) {
+      /* XXX enable this if/when non-shader vertex programs get
+       * texture fetches:
+       vprog = ctx->VertexProgram.Current;
+       */
    }
-   else {
-      if (ctx->FragmentProgram._Enabled) {
-         fprog = ctx->FragmentProgram.Current;
-      }
-      if (ctx->VertexProgram._Enabled) {
-         /* XXX enable this if/when non-shader vertex programs get
-          * texture fetches:
-         vprog = ctx->VertexProgram.Current;
-         */
-      }
+
+   if (ctx->Shader.CurrentFragmentProgram &&
+       ctx->Shader.CurrentFragmentProgram->LinkStatus) {
+      fprog = ctx->Shader.CurrentFragmentProgram->FragmentProgram;
+   }
+   else if (ctx->FragmentProgram._Enabled) {
+      fprog = ctx->FragmentProgram.Current;
    }
 
+   /* FINISHME: Geometry shader texture accesses should also be considered
+    * FINISHME: here.
+    */
+
    /* TODO: only set this if there are actual changes */
    ctx->NewState |= _NEW_TEXTURE;
 
diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c
index 451299c..f92ca13 100644
--- a/src/mesa/state_tracker/st_atom_rasterizer.c
+++ b/src/mesa/state_tracker/st_atom_rasterizer.c
@@ -96,9 +96,8 @@ static void update_raster_state( struct st_context *st )
     */
    if (ctx->VertexProgram._Current) {
       if (ctx->VertexProgram._Enabled ||
-          (ctx->Shader.CurrentProgram &&
-           ctx->Shader.CurrentProgram->VertexProgram &&
-           ctx->Shader.CurrentProgram->LinkStatus)) {
+          (ctx->Shader.CurrentVertexProgram &&
+           ctx->Shader.CurrentVertexProgram->LinkStatus)) {
          /* user-defined vertex program or shader */
          raster->light_twoside = ctx->VertexProgram.TwoSideEnabled;
       }
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
index 5387499..61a0e1b 100644
--- a/src/mesa/state_tracker/st_draw.c
+++ b/src/mesa/state_tracker/st_draw.c
@@ -547,11 +547,21 @@ setup_index_buffer(struct gl_context *ctx,
 static void
 check_uniforms(struct gl_context *ctx)
 {
-   const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
-   if (shProg && shProg->LinkStatus) {
-      GLuint i;
-      for (i = 0; i < shProg->Uniforms->NumUniforms; i++) {
-         const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i];
+   struct gl_shader_program *shProg[3] = {
+      ctx->Shader.CurrentVertexProgram,
+      ctx->Shader.CurrentGeometryProgram,
+      ctx->Shader.CurrentFragmentProgram,
+   };
+   unsigned j;
+
+   for (j = 0; j < 3; j++) {
+      unsigned i;
+
+      if (shProg[j] == NULL || !shProg[j]->LinkStatus)
+	 continue;
+
+      for (i = 0; i < shProg[j]->Uniforms->NumUniforms; i++) {
+         const struct gl_uniform *u = &shProg[j]->Uniforms->Uniforms[i];
          if (!u->Initialized) {
             _mesa_warning(ctx,
                           "Using shader with uninitialized uniform: %s",
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 95e6bd7..6a5d741 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -718,12 +718,38 @@ st_translate_geometry_program(struct st_context *st,
 void
 st_print_shaders(struct gl_context *ctx)
 {
-   struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
-   if (shProg) {
-      GLuint i;
-      for (i = 0; i < shProg->NumShaders; i++) {
-         printf("GLSL shader %u of %u:\n", i, shProg->NumShaders);
-         printf("%s\n", shProg->Shaders[i]->Source);
+   struct gl_shader_program *shProg[3] = {
+      ctx->Shader.CurrentVertexProgram,
+      ctx->Shader.CurrentGeometryProgram,
+      ctx->Shader.CurrentFragmentProgram,
+   };
+   unsigned j;
+
+   for (j = 0; j < 3; j++) {
+      unsigned i;
+
+      if (shProg[j] == NULL)
+	 continue;
+
+      for (i = 0; i < shProg[j]->NumShaders; i++) {
+	 struct gl_shader *sh;
+
+	 switch (shProg[j]->Shaders[i]->Type) {
+	 case GL_VERTEX_SHADER:
+	    sh = (i != 0) ? NULL : shProg[j]->Shaders[i];
+	    break;
+	 case GL_GEOMETRY_SHADER_ARB:
+	    sh = (i != 1) ? NULL : shProg[j]->Shaders[i];
+	    break;
+	 case GL_FRAGMENT_SHADER:
+	    sh = (i != 2) ? NULL : shProg[j]->Shaders[i];
+	    break;
+	 }
+
+	 if (sh != NULL) {
+	    printf("GLSL shader %u of %u:\n", i, shProg[j]->NumShaders);
+	    printf("%s\n", sh->Source);
+	 }
       }
    }
 }
diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c
index e421d21..e391043 100644
--- a/src/mesa/swrast/s_fragprog.c
+++ b/src/mesa/swrast/s_fragprog.c
@@ -169,7 +169,7 @@ init_machine(struct gl_context *ctx, struct gl_program_machine *machine,
    machine->Samplers = program->Base.SamplerUnits;
 
    /* if running a GLSL program (not ARB_fragment_program) */
-   if (ctx->Shader.CurrentProgram) {
+   if (ctx->Shader.CurrentFragmentProgram) {
       /* Store front/back facing value */
       machine->Attribs[FRAG_ATTRIB_FACE][col][0] = 1.0F - span->facing;
    }




More information about the mesa-commit mailing list