swrast: Fix fixed-function fragment processing
authorChad Versace <chad.versace@linux.intel.com>
Thu, 26 Jan 2012 03:38:10 +0000 (19:38 -0800)
committerChad Versace <chad.versace@linux.intel.com>
Fri, 27 Jan 2012 21:34:26 +0000 (13:34 -0800)
On i965, _mesa_ir_link_shader is never called. As a consequence, the
current fragment program (ctx->FragmentProgram->_Current) exists but is
invalid because it has no instructions. Yet swrast continued to attempt to
use the empty program.

To avoid using the empty program, this patch 1) defines a new function,
_swrast_use_fragment_program, which checks if the current fragment program
exists and differs from the fixed function fragment program, and, when
appropriate, 2) replaces checks of the form
    if (ctx->FragmentProgram->_Current == NULL)
with
    if (_swrast_use_fragment_program(ctx))

Fixes the following oglconform regressions on i965/gen6:
    api-fogcoord(basic.allCases.log)
    api-mtexcoord(basic.allCases.log)
    api-seccolor(basic.allCases.log)
    api-texcoord(basic.allCases.log)
    blend-separate(basic.allCases)
    colorsum(basic.allCases.log)

The tests were ran with the GLXFBConfig:
    visual  x   bf lv rg d st  colorbuffer  sr ax dp st accumbuffer ms  cav
  id dep cl sp  sz l  ci b ro  r  g  b  a F gb bf th cl  r  g  b  a ns b eat
----------------------------------------------------------------------------
0x021 24 tc  0  32  0 r  y .   8  8  8  8 .  .  0 24 8  0  0  0  0  0 0 None

(Note: I originally believed that the hunk in
_swrast_update_fragment_program was unnecessary. But it is required to fix
blend-separate.)

Note: This is a candidate for the 8.0 branch.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=43327
Reveiwed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <idr@freedesktop.org>
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
src/mesa/swrast/s_aaline.c
src/mesa/swrast/s_aalinetemp.h
src/mesa/swrast/s_aatriangle.c
src/mesa/swrast/s_context.c
src/mesa/swrast/s_fragprog.c
src/mesa/swrast/s_fragprog.h
src/mesa/swrast/s_lines.c
src/mesa/swrast/s_span.c
src/mesa/swrast/s_triangle.c

index d4b1805d9ec276ed33ad77a4e3040ebea4919e4f..d36d876974e3301919d97a78c53ce08c4f7a7bde 100644 (file)
@@ -479,7 +479,7 @@ _swrast_choose_aa_line_function(struct gl_context *ctx)
    ASSERT(ctx->Line.SmoothFlag);
 
    if (ctx->Texture._EnabledCoordUnits != 0
-       || ctx->FragmentProgram._Current
+       || _swrast_use_fragment_program(ctx)
        || (ctx->Light.Enabled &&
            ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
        || ctx->Fog.ColorSumEnabled
index 376ef32d06edb0de598a94985c02a78306235ab7..ba9f8abb9c34a0bf47cdc456e2da01f687950cf4 100644 (file)
@@ -67,7 +67,7 @@ NAME(plot)(struct gl_context *ctx, struct LineInfo *line, int ix, int iy)
    ATTRIB_LOOP_BEGIN
       GLfloat (*attribArray)[4] = line->span.array->attribs[attr];
       if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0
-          && !ctx->FragmentProgram._Current) {
+          && !_swrast_use_fragment_program(ctx)) {
          /* texcoord w/ divide by Q */
          const GLuint unit = attr - FRAG_ATTRIB_TEX0;
          const GLfloat invQ = solve_plane_recip(fx, fy, line->attrPlane[attr][3]);
index c68fdf63b681dcdb5b2d9bdf01afb71c791b3090..b59177fa76228634c8d0113a8563f51fb5a7c682 100644 (file)
@@ -299,7 +299,7 @@ _swrast_set_aa_triangle_function(struct gl_context *ctx)
    ASSERT(ctx->Polygon.SmoothFlag);
 
    if (ctx->Texture._EnabledCoordUnits != 0
-       || ctx->FragmentProgram._Current
+       || _swrast_use_fragment_program(ctx)
        || swrast->_FogEnabled
        || _mesa_need_secondary_color(ctx)) {
       SWRAST_CONTEXT(ctx)->Triangle = general_aa_tri;
index 14cb9b180c33352e63062e2bdbbec5b0dbd269fa..cc304d70c066fc20f9cc0d75bf8b979ed82a09b5 100644 (file)
@@ -105,7 +105,7 @@ _swrast_update_rasterflags( struct gl_context *ctx )
    }
 
 
-   if (ctx->FragmentProgram._Current) {
+   if (_swrast_use_fragment_program(ctx)) {
       rasterMask |= FRAGPROG_BIT;
    }
 
@@ -170,7 +170,7 @@ _swrast_update_fog_hint( struct gl_context *ctx )
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    swrast->_PreferPixelFog = (!swrast->AllowVertexFog ||
-                              ctx->FragmentProgram._Current ||
+                             _swrast_use_fragment_program(ctx) ||
                              (ctx->Hint.Fog == GL_NICEST &&
                               swrast->AllowPixelFog));
 }
@@ -220,13 +220,14 @@ _swrast_update_deferred_texture(struct gl_context *ctx)
       swrast->_DeferredTexture = GL_FALSE;
    }
    else {
+      GLboolean use_fprog = _swrast_use_fragment_program(ctx);
       const struct gl_fragment_program *fprog
          = ctx->FragmentProgram._Current;
-      if (fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH))) {
+      if (use_fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH))) {
          /* Z comes from fragment program/shader */
          swrast->_DeferredTexture = GL_FALSE;
       }
-      else if (fprog && fprog->UsesKill) {
+      else if (use_fprog && fprog->UsesKill) {
          swrast->_DeferredTexture = GL_FALSE;
       }
       else if (ctx->Query.CurrentOcclusionObject) {
@@ -254,7 +255,8 @@ _swrast_update_fog_state( struct gl_context *ctx )
           (fp->Base.Target == GL_FRAGMENT_PROGRAM_NV));
 
    /* determine if fog is needed, and if so, which fog mode */
-   swrast->_FogEnabled = (fp == NULL && ctx->Fog.Enabled);
+   swrast->_FogEnabled = (!_swrast_use_fragment_program(ctx) &&
+                         ctx->Fog.Enabled);
 }
 
 
@@ -265,10 +267,11 @@ _swrast_update_fog_state( struct gl_context *ctx )
 static void
 _swrast_update_fragment_program(struct gl_context *ctx, GLbitfield newState)
 {
-   const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
-   if (fp) {
-      _mesa_load_state_parameters(ctx, fp->Base.Parameters);
-   }
+   if (!_swrast_use_fragment_program(ctx))
+      return;
+
+   _mesa_load_state_parameters(ctx,
+                               ctx->FragmentProgram._Current->Base.Parameters);
 }
 
 
@@ -286,7 +289,7 @@ _swrast_update_specular_vertex_add(struct gl_context *ctx)
 
    swrast->SpecularVertexAdd = (separateSpecular
                                 && ctx->Texture._EnabledUnits == 0x0
-                                && !ctx->FragmentProgram._Current
+                                && !_swrast_use_fragment_program(ctx)
                                 && !ctx->ATIFragmentShader._Enabled);
 }
 
@@ -497,7 +500,7 @@ _swrast_update_active_attribs(struct gl_context *ctx)
    /*
     * Compute _ActiveAttribsMask = which fragment attributes are needed.
     */
-   if (ctx->FragmentProgram._Current) {
+   if (_swrast_use_fragment_program(ctx)) {
       /* fragment program/shader */
       attribsMask = ctx->FragmentProgram._Current->Base.InputsRead;
       attribsMask &= ~FRAG_BIT_WPOS; /* WPOS is always handled specially */
index 1caa0ebc22697a94a217e873c14d3f6b85cf95e5..cd20d8e3647f4dfd621ea004b44a23fa81d79211 100644 (file)
 #include "s_fragprog.h"
 #include "s_span.h"
 
+/**
+ * \brief Should swrast use a fragment program?
+ *
+ * \return true if the current fragment program exists and is not the fixed
+ *         function fragment program
+ */
+GLboolean
+_swrast_use_fragment_program(struct gl_context *ctx)
+{
+   struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
+   return fp && fp != ctx->FragmentProgram._TexEnvProgram;
+}
 
 /**
  * Apply texture object's swizzle (X/Y/Z/W/0/1) to incoming 'texel'
index 62a68361769f3edb8b7859cea9f9f401da31b3db..ac1f5ff4cf41e214f9892be4cb7f5515ea7de930 100644 (file)
@@ -31,6 +31,8 @@
 
 struct gl_context;
 
+GLboolean
+_swrast_use_fragment_program(struct gl_context *ctx);
 
 extern void
 _swrast_exec_fragment_program(struct gl_context *ctx, SWspan *span);
index 95a2a5d96fc5a482d9ee57827a11ab28b1cb32e5..ee997b08a7b1c5c285a49da050dcf89063928b0e 100644 (file)
@@ -236,7 +236,7 @@ _swrast_choose_line( struct gl_context *ctx )
          ASSERT(swrast->Line);
       }
       else if (ctx->Texture._EnabledCoordUnits
-               || ctx->FragmentProgram._Current
+               || _swrast_use_fragment_program(ctx)
                || swrast->_FogEnabled
                || specular) {
          USE(general_line);
index ccdbe5f79c42ff54b7baec61598ba5647b4a4d15..28f2f3d3fff43f302d97476ba7e7f38f4c66ee2c 100644 (file)
@@ -139,7 +139,8 @@ _swrast_span_default_attribs(struct gl_context *ctx, SWspan *span)
       for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
          const GLuint attr = FRAG_ATTRIB_TEX0 + i;
          const GLfloat *tc = ctx->Current.RasterTexCoords[i];
-         if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) {
+         if (_swrast_use_fragment_program(ctx) ||
+             ctx->ATIFragmentShader._Enabled) {
             COPY_4V(span->attrStart[attr], tc);
          }
          else if (tc[3] > 0.0F) {
@@ -498,7 +499,7 @@ interpolate_texcoords(struct gl_context *ctx, SWspan *span)
                swrast_texture_image_const(img);
 
             needLambda = (obj->Sampler.MinFilter != obj->Sampler.MagFilter)
-               || ctx->FragmentProgram._Current;
+               || _swrast_use_fragment_program(ctx);
             /* LOD is calculated directly in the ansiotropic filter, we can
              * skip the normal lambda function as the result is ignored.
              */
@@ -518,7 +519,7 @@ interpolate_texcoords(struct gl_context *ctx, SWspan *span)
 
          if (needLambda) {
             GLuint i;
-            if (ctx->FragmentProgram._Current
+            if (_swrast_use_fragment_program(ctx)
                 || ctx->ATIFragmentShader._Enabled) {
                /* do perspective correction but don't divide s, t, r by q */
                const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
@@ -559,7 +560,7 @@ interpolate_texcoords(struct gl_context *ctx, SWspan *span)
          }
          else {
             GLuint i;
-            if (ctx->FragmentProgram._Current ||
+            if (_swrast_use_fragment_program(ctx) ||
                 ctx->ATIFragmentShader._Enabled) {
                /* do perspective correction but don't divide s, t, r by q */
                const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
@@ -833,7 +834,7 @@ add_specular(struct gl_context *ctx, SWspan *span)
    GLfloat (*col1)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
    GLuint i;
 
-   ASSERT(!ctx->FragmentProgram._Current);
+   ASSERT(!_swrast_use_fragment_program(ctx));
    ASSERT(span->arrayMask & SPAN_RGBA);
    ASSERT(swrast->_ActiveAttribMask & FRAG_BIT_COL1);
    (void) swrast; /* silence warning */
@@ -971,25 +972,7 @@ convert_color_type(SWspan *span, GLenum newType, GLuint output)
 static inline void
 shade_texture_span(struct gl_context *ctx, SWspan *span)
 {
-   /* This is a hack to work around drivers such as i965 that:
-    *
-    *     - Set _MaintainTexEnvProgram to generate GLSL IR for
-    *       fixed-function fragment processing.
-    *     - Don't call _mesa_ir_link_shader to generate Mesa IR from
-    *       the GLSL IR.
-    *     - May use swrast to handle glDrawPixels.
-    *
-    * Since _mesa_ir_link_shader is never called, there is no Mesa IR
-    * to execute.  Instead do regular fixed-function processing.
-    *
-    * It is also worth noting that the software fixed-function path is
-    * much faster than the software shader path.
-    */
-   const bool use_fragment_program =
-      ctx->FragmentProgram._Current
-      && ctx->FragmentProgram._Current != ctx->FragmentProgram._TexEnvProgram;
-
-   if (use_fragment_program ||
+   if (_swrast_use_fragment_program(ctx) ||
        ctx->ATIFragmentShader._Enabled) {
       /* programmable shading */
       if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) {
@@ -1018,7 +1001,7 @@ shade_texture_span(struct gl_context *ctx, SWspan *span)
          interpolate_wpos(ctx, span);
 
       /* Run fragment program/shader now */
-      if (use_fragment_program) {
+      if (_swrast_use_fragment_program(ctx)) {
          _swrast_exec_fragment_program(ctx, span);
       }
       else {
@@ -1151,7 +1134,7 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
    const GLbitfield64 origArrayAttribs = span->arrayAttribs;
    const GLenum origChanType = span->array->ChanType;
    void * const origRgba = span->array->rgba;
-   const GLboolean shader = (ctx->FragmentProgram._Current
+   const GLboolean shader = (_swrast_use_fragment_program(ctx)
                              || ctx->ATIFragmentShader._Enabled);
    const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits;
    struct gl_framebuffer *fb = ctx->DrawBuffer;
@@ -1326,7 +1309,8 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
       const GLuint numBuffers = fb->_NumColorDrawBuffers;
       const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
       const GLboolean multiFragOutputs = 
-         (fp && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0));
+         _swrast_use_fragment_program(ctx)
+         && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0);
       GLuint buf;
 
       for (buf = 0; buf < numBuffers; buf++) {
index 124aa5f8edd2f2005a3938c9c185a1bf1c25dde4..ddb4792f7e9d35321784e65f7e6963e7a3f07763 100644 (file)
@@ -1038,7 +1038,7 @@ _swrast_choose_triangle( struct gl_context *ctx )
        * needs to be interpolated.
        */
       if (ctx->Texture._EnabledCoordUnits ||
-          ctx->FragmentProgram._Current ||
+         _swrast_use_fragment_program(ctx) ||
           ctx->ATIFragmentShader._Enabled ||
           _mesa_need_secondary_color(ctx) ||
           swrast->_FogEnabled) {
@@ -1060,7 +1060,7 @@ _swrast_choose_triangle( struct gl_context *ctx )
 
          /* First see if we can use an optimized 2-D texture function */
          if (ctx->Texture._EnabledCoordUnits == 0x1
-             && !ctx->FragmentProgram._Current
+             && !_swrast_use_fragment_program(ctx)
              && !ctx->ATIFragmentShader._Enabled
              && ctx->Texture._EnabledUnits == 0x1
              && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT