mesa: Track fixed-function fragment shader as a shader
authorIan Romanick <ian.d.romanick@intel.com>
Tue, 15 Nov 2011 20:01:18 +0000 (12:01 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Wed, 11 Jan 2012 20:51:24 +0000 (12:51 -0800)
Previously the fixed-function fragment shader was tracked as a
gl_program.  This means that it shows up in the driver as a Mesa IR
program instead of as a GLSL IR program.  If a driver doesn't generate
Mesa IR from the GLSL IR, that program is empty.  If the program is
empty there is either no rendering or a GPU hang.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Acked-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_wm.c
src/mesa/drivers/dri/i965/brw_wm_state.c
src/mesa/drivers/dri/i965/gen6_wm_state.c
src/mesa/drivers/dri/i965/gen7_wm_state.c
src/mesa/main/mtypes.h
src/mesa/main/shaderapi.c
src/mesa/main/state.c

index cad0af8c1acdc56c3b22500d0e474d8927194ecc..7dee20b7f926ca7b5f7b0b7da97cfb60053b6137 100644 (file)
@@ -543,7 +543,7 @@ brw_upload_wm_prog(struct brw_context *brw)
    if (!brw_search_cache(&brw->cache, BRW_WM_PROG,
                         &key, sizeof(key),
                         &brw->wm.prog_offset, &brw->wm.prog_data)) {
-      bool success = do_wm_prog(brw, ctx->Shader.CurrentFragmentProgram, fp,
+      bool success = do_wm_prog(brw, ctx->Shader._CurrentFragmentProgram, fp,
                                &key);
       (void) success;
       assert(success);
index e1791c20ea72de92b6e635f3726c6ad81ec0f353..dd67795e74311127b0fc76c7bb34d94517ceeb9e 100644 (file)
@@ -169,9 +169,9 @@ brw_upload_wm_unit(struct brw_context *brw)
     * If using the fragment shader backend, the program is always
     * 8-wide.  If not, it's always 16.
     */
-   if (ctx->Shader.CurrentFragmentProgram) {
+   if (ctx->Shader._CurrentFragmentProgram) {
       struct brw_shader *shader = (struct brw_shader *)
-        ctx->Shader.CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT];
+        ctx->Shader._CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT];
 
       if (shader != NULL && shader->ir != NULL) {
         wm->wm5.enable_8_pix = 1;
index 0547eb8a0b3628353806574878aee88e8d619e9c..3669811be5513075f7023fbe128df69fdaa66b1d 100644 (file)
@@ -135,7 +135,9 @@ upload_wm_state(struct brw_context *brw)
    dw5 |= GEN6_WM_LINE_END_CAP_AA_WIDTH_0_5;
 
    /* Use ALT floating point mode for ARB fragment programs, because they
-    * require 0^0 == 1.
+    * require 0^0 == 1.  Even though _CurrentFragmentProgram is used for
+    * rendering, CurrentFragmentProgram is used for this check to
+    * differentiate between the GLSL and non-GLSL cases.
     */
    if (ctx->Shader.CurrentFragmentProgram == NULL)
       dw2 |= GEN6_WM_FLOATING_POINT_MODE_ALT;
index 1468fcc1278e7f86523fdfc878a7b7535b40dd57..32222f922d8aedb8b8f55c6b1fad925cc854d1cb 100644 (file)
@@ -166,7 +166,9 @@ upload_ps_state(struct brw_context *brw)
    dw2 |= (ALIGN(brw->sampler.count, 4) / 4) << GEN7_PS_SAMPLER_COUNT_SHIFT;
 
    /* Use ALT floating point mode for ARB fragment programs, because they
-    * require 0^0 == 1.
+    * require 0^0 == 1.  Even though _CurrentFragmentProgram is used for
+    * rendering, CurrentFragmentProgram is used for this check to
+    * differentiate between the GLSL and non-GLSL cases.
     */
    if (intel->ctx.Shader.CurrentFragmentProgram == NULL)
       dw2 |= GEN7_PS_FLOATING_POINT_MODE_ALT;
index bb46ba0c0351fe63c5ea2f7763422072ca7d21ad..aca47379ca161df1aa637d85c4beda5547bc9419 100644 (file)
@@ -2350,6 +2350,8 @@ struct gl_shader_state
    struct gl_shader_program *CurrentGeometryProgram;
    struct gl_shader_program *CurrentFragmentProgram;
 
+   struct gl_shader_program *_CurrentFragmentProgram;
+
    /**
     * Program used by glUniform calls.
     *
index 9372d6decf6a8a8fe730804ec499ac2b76190a81..f3f13a02645e3772b34c2c14ad4bddea7de8bfa8 100644 (file)
@@ -124,6 +124,8 @@ _mesa_free_shader_state(struct gl_context *ctx)
                                  NULL);
    _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram,
                                  NULL);
+   _mesa_reference_shader_program(ctx, &ctx->Shader._CurrentFragmentProgram,
+                                 NULL);
    _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL);
 }
 
@@ -876,6 +878,33 @@ use_shader_program(struct gl_context *ctx, GLenum type,
 
    if (*target != shProg) {
       FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
+
+      /* If the shader is also bound as the current rendering shader, unbind
+       * it from that binding point as well.  This ensures that the correct
+       * semantics of glDeleteProgram are maintained.
+       */
+      switch (type) {
+#if FEATURE_ARB_vertex_shader
+      case GL_VERTEX_SHADER:
+        /* Empty for now. */
+        break;
+#endif
+#if FEATURE_ARB_geometry_shader4
+      case GL_GEOMETRY_SHADER_ARB:
+        /* Empty for now. */
+        break;
+#endif
+#if FEATURE_ARB_fragment_shader
+      case GL_FRAGMENT_SHADER:
+        if (*target == ctx->Shader._CurrentFragmentProgram) {
+           _mesa_reference_shader_program(ctx,
+                                          &ctx->Shader._CurrentFragmentProgram,
+                                          NULL);
+        }
+        break;
+#endif
+      }
+
       _mesa_reference_shader_program(ctx, target, shProg);
       return true;
    }
index 7e43563bd017e24aec7127bf230861555a95552d..56bb797e6255bcd744dabe008b4905e96ce6526d 100644 (file)
@@ -43,6 +43,7 @@
 #include "pixel.h"
 #include "program/program.h"
 #include "program/prog_parameter.h"
+#include "shaderobj.h"
 #include "state.h"
 #include "stencil.h"
 #include "texenvprogram.h"
@@ -252,12 +253,18 @@ update_program(struct gl_context *ctx)
    if (fsProg && fsProg->LinkStatus
        && fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) {
       /* Use GLSL fragment shader */
+      _mesa_reference_shader_program(ctx,
+                                    &ctx->Shader._CurrentFragmentProgram,
+                                    fsProg);
       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                               (struct gl_fragment_program *)
                               fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program);
    }
    else if (ctx->FragmentProgram._Enabled) {
       /* Use user-defined fragment program */
+      _mesa_reference_shader_program(ctx,
+                                    &ctx->Shader._CurrentFragmentProgram,
+                                    NULL);
       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                                ctx->FragmentProgram.Current);
    }
@@ -265,6 +272,9 @@ update_program(struct gl_context *ctx)
       /* Use fragment program generated from fixed-function state */
       struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx);
 
+      _mesa_reference_shader_program(ctx,
+                                    &ctx->Shader._CurrentFragmentProgram,
+                                    f);
       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current,
                               (struct gl_fragment_program *)
                                f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program);