mesa/tests: Sanity check the ES2 dispatch table
[mesa.git] / src / mesa / swrast / s_span.c
index 3d3ec57d3977310d66b5fd1179f085109a55cf6e..ff653a6225767927c62e14ec3502020c47bbb910 100644 (file)
 
 #include "main/glheader.h"
 #include "main/colormac.h"
+#include "main/format_pack.h"
+#include "main/format_unpack.h"
 #include "main/macros.h"
 #include "main/imports.h"
 #include "main/image.h"
+#include "main/samplerobj.h"
 
 #include "s_atifragshader.h"
 #include "s_alpha.h"
@@ -137,7 +140,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) {
@@ -415,8 +419,8 @@ _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
    GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
    GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
    GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
-   GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
-   GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
+   GLfloat x = sqrtf(dudx * dudx + dvdx * dvdx);
+   GLfloat y = sqrtf(dudy * dudy + dvdy * dvdy);
    GLfloat rho = MAX2(x, y);
    GLfloat lambda = LOG2(rho);
    return lambda;
@@ -494,14 +498,15 @@ interpolate_texcoords(struct gl_context *ctx, SWspan *span)
             const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
             const struct swrast_texture_image *swImg =
                swrast_texture_image_const(img);
+            const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, u);
 
-            needLambda = (obj->Sampler.MinFilter != obj->Sampler.MagFilter)
-               || ctx->FragmentProgram._Current;
+            needLambda = (samp->MinFilter != samp->MagFilter)
+               || _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.
              */
-            if (obj->Sampler.MaxAnisotropy > 1.0 &&
-                obj->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
+            if (samp->MaxAnisotropy > 1.0 &&
+                samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
                needLambda = GL_FALSE;
             }
             texW = swImg->WidthScale;
@@ -516,7 +521,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];
@@ -557,7 +562,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];
@@ -831,7 +836,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 */
@@ -969,25 +974,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) {
@@ -1016,7 +1003,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 {
@@ -1043,6 +1030,94 @@ shade_texture_span(struct gl_context *ctx, SWspan *span)
 }
 
 
+/** Put colors at x/y locations into a renderbuffer */
+static void
+put_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
+           GLenum datatype,
+           GLuint count, const GLint x[], const GLint y[],
+           const void *values, const GLubyte *mask)
+{
+   gl_pack_ubyte_rgba_func pack_ubyte = NULL;
+   gl_pack_float_rgba_func pack_float = NULL;
+   GLuint i;
+
+   if (datatype == GL_UNSIGNED_BYTE)
+      pack_ubyte = _mesa_get_pack_ubyte_rgba_function(rb->Format);
+   else
+      pack_float = _mesa_get_pack_float_rgba_function(rb->Format);
+
+   for (i = 0; i < count; i++) {
+      if (mask[i]) {
+         GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]);
+
+         if (datatype == GL_UNSIGNED_BYTE) {
+            pack_ubyte((const GLubyte *) values + 4 * i, dst);
+         }
+         else {
+            assert(datatype == GL_FLOAT);
+            pack_float((const GLfloat *) values + 4 * i, dst);
+         }
+      }
+   }
+}
+
+
+/** Put row of colors into renderbuffer */
+void
+_swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
+                GLenum datatype,
+                GLuint count, GLint x, GLint y,
+                const void *values, const GLubyte *mask)
+{
+   GLubyte *dst = _swrast_pixel_address(rb, x, y);
+
+   if (!mask) {
+      if (datatype == GL_UNSIGNED_BYTE) {
+         _mesa_pack_ubyte_rgba_row(rb->Format, count,
+                                   (const GLubyte (*)[4]) values, dst);
+      }
+      else {
+         assert(datatype == GL_FLOAT);
+         _mesa_pack_float_rgba_row(rb->Format, count,
+                                   (const GLfloat (*)[4]) values, dst);
+      }
+   }
+   else {
+      const GLuint bpp = _mesa_get_format_bytes(rb->Format);
+      GLuint i, runLen, runStart;
+      /* We can't pass a 'mask' array to the _mesa_pack_rgba_row() functions
+       * so look for runs where mask=1...
+       */
+      runLen = runStart = 0;
+      for (i = 0; i < count; i++) {
+         if (mask[i]) {
+            if (runLen == 0)
+               runStart = i;
+            runLen++;
+         }
+
+         if (!mask[i] || i == count - 1) {
+            /* might be the end of a run of pixels */
+            if (runLen > 0) {
+               if (datatype == GL_UNSIGNED_BYTE) {
+                  _mesa_pack_ubyte_rgba_row(rb->Format, runLen,
+                                     (const GLubyte (*)[4]) values + runStart,
+                                     dst + runStart * bpp);
+               }
+               else {
+                  assert(datatype == GL_FLOAT);
+                  _mesa_pack_float_rgba_row(rb->Format, runLen,
+                                   (const GLfloat (*)[4]) values + runStart,
+                                   dst + runStart * bpp);
+               }
+               runLen = 0;
+            }
+         }
+      }
+   }
+}
+
+
 
 /**
  * Apply all the per-fragment operations to a span.
@@ -1061,7 +1136,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;
@@ -1091,7 +1166,7 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
       return;
    }
 
-   ASSERT(span->end <= MAX_WIDTH);
+   ASSERT(span->end <= SWRAST_MAX_WIDTH);
 
    /* Depth bounds test */
    if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
@@ -1236,7 +1311,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++) {
@@ -1245,20 +1321,22 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
          /* color[fragOutput] will be written to buffer[buf] */
 
          if (rb) {
-            GLchan rgbaSave[MAX_WIDTH][4];
-            const GLuint fragOutput = multiFragOutputs ? buf : 0;
+            /* re-use one of the attribute array buffers for rgbaSave */
+            GLchan (*rgbaSave)[4] = (GLchan (*)[4]) span->array->attribs[0];
+            struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
+            GLenum colorType = srb->ColorType;
+
+            assert(colorType == GL_UNSIGNED_BYTE ||
+                   colorType == GL_FLOAT);
 
-            /* set span->array->rgba to colors for render buffer's datatype */
-            if (rb->DataType != span->array->ChanType || fragOutput > 0) {
-               convert_color_type(span, rb->DataType, fragOutput);
+            /* set span->array->rgba to colors for renderbuffer's datatype */
+            if (span->array->ChanType != colorType) {
+               convert_color_type(span, colorType, 0);
             }
             else {
-               if (rb->DataType == GL_UNSIGNED_BYTE) {
+               if (span->array->ChanType == GL_UNSIGNED_BYTE) {
                   span->array->rgba = span->array->rgba8;
                }
-               else if (rb->DataType == GL_UNSIGNED_SHORT) {
-                  span->array->rgba = (void *) span->array->rgba16;
-               }
                else {
                   span->array->rgba = (void *)
                      span->array->attribs[FRAG_ATTRIB_COL0];
@@ -1290,17 +1368,18 @@ _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
 
             if (span->arrayMask & SPAN_XY) {
                /* array of pixel coords */
-               ASSERT(rb->PutValues);
-               rb->PutValues(ctx, rb, span->end,
-                             span->array->x, span->array->y,
-                             span->array->rgba, span->array->mask);
+               put_values(ctx, rb,
+                          span->array->ChanType, span->end,
+                          span->array->x, span->array->y,
+                          span->array->rgba, span->array->mask);
             }
             else {
                /* horizontal run of pixels */
-               ASSERT(rb->PutRow);
-               rb->PutRow(ctx, rb, span->end, span->x, span->y,
-                          span->array->rgba,
-                          span->writeAll ? NULL: span->array->mask);
+               _swrast_put_row(ctx, rb,
+                               span->array->ChanType,
+                               span->end, span->x, span->y,
+                               span->array->rgba,
+                               span->writeAll ? NULL: span->array->mask);
             }
 
             if (!multiFragOutputs && numBuffers > 1) {
@@ -1333,6 +1412,7 @@ _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
                         GLuint n, GLint x, GLint y,
                         GLvoid *rgba)
 {
+   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
    GLenum dstType = GL_FLOAT;
    const GLint bufWidth = (GLint) rb->Width;
    const GLint bufHeight = (GLint) rb->Height;
@@ -1344,6 +1424,8 @@ _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
    }
    else {
       GLint skip, length;
+      GLubyte *src;
+
       if (x < 0) {
          /* left edge clipping */
          skip = -x;
@@ -1372,7 +1454,6 @@ _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
       }
 
       ASSERT(rb);
-      ASSERT(rb->GetRow);
       ASSERT(rb->_BaseFormat == GL_RGBA ||
             rb->_BaseFormat == GL_RGB ||
             rb->_BaseFormat == GL_RG ||
@@ -1382,70 +1463,69 @@ _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
             rb->_BaseFormat == GL_LUMINANCE_ALPHA ||
             rb->_BaseFormat == GL_ALPHA);
 
-      if (rb->DataType == dstType) {
-         rb->GetRow(ctx, rb, length, x + skip, y,
-                    (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
+      assert(srb->Map);
+
+      src = _swrast_pixel_address(rb, x + skip, y);
+
+      if (dstType == GL_UNSIGNED_BYTE) {
+         _mesa_unpack_ubyte_rgba_row(rb->Format, length, src,
+                                     (GLubyte (*)[4]) rgba + skip);
+      }
+      else if (dstType == GL_FLOAT) {
+         _mesa_unpack_rgba_row(rb->Format, length, src,
+                               (GLfloat (*)[4]) rgba + skip);
       }
       else {
-         GLuint temp[MAX_WIDTH * 4];
-         rb->GetRow(ctx, rb, length, x + skip, y, temp);
-         _mesa_convert_colors(rb->DataType, temp,
-                   dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
-                   length, NULL);
+         _mesa_problem(ctx, "unexpected type in _swrast_read_rgba_span()");
       }
    }
 }
 
 
 /**
- * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
- * reading values outside the buffer bounds.
- * We can use this for reading any format/type of renderbuffer.
- * \param valueSize is the size in bytes of each value (pixel) put into the
- *                  values array.
+ * Get colors at x/y positions with clipping.
+ * \param type  type of values to return
  */
-void
-_swrast_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
-                   GLuint count, const GLint x[], const GLint y[],
-                   void *values, GLuint valueSize)
+static void
+get_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
+           GLuint count, const GLint x[], const GLint y[],
+           void *values, GLenum type)
 {
-   GLuint i, inCount = 0, inStart = 0;
+   GLuint i;
 
    for (i = 0; i < count; i++) {
       if (x[i] >= 0 && y[i] >= 0 &&
          x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
          /* inside */
-         if (inCount == 0)
-            inStart = i;
-         inCount++;
-      }
-      else {
-         if (inCount > 0) {
-            /* read [inStart, inStart + inCount) */
-            rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
-                          (GLubyte *) values + inStart * valueSize);
-            inCount = 0;
+         const GLubyte *src = _swrast_pixel_address(rb, x[i], y[i]);
+
+         if (type == GL_UNSIGNED_BYTE) {
+            _mesa_unpack_ubyte_rgba_row(rb->Format, 1, src,
+                                        (GLubyte (*)[4]) values + i);
+         }
+         else if (type == GL_FLOAT) {
+            _mesa_unpack_rgba_row(rb->Format, 1, src,
+                                  (GLfloat (*)[4]) values + i);
+         }
+         else {
+            _mesa_problem(ctx, "unexpected type in get_values()");
          }
       }
    }
-   if (inCount > 0) {
-      /* read last values */
-      rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
-                    (GLubyte *) values + inStart * valueSize);
-   }
 }
 
 
 /**
- * Wrapper for gl_renderbuffer::GetRow() which does clipping.
- * \param valueSize  size of each value (pixel) in bytes
+ * Get row of colors with clipping.
+ * \param type  type of values to return
  */
-void
-_swrast_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
-                GLuint count, GLint x, GLint y,
-                GLvoid *values, GLuint valueSize)
+static void
+get_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
+        GLuint count, GLint x, GLint y,
+        GLvoid *values, GLenum type)
 {
    GLint skip = 0;
+   GLubyte *src;
 
    if (y < 0 || y >= (GLint) rb->Height)
       return; /* above or below */
@@ -1466,7 +1546,19 @@ _swrast_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
       count -= skip;
    }
 
-   rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
+   src = _swrast_pixel_address(rb, x, y);
+
+   if (type == GL_UNSIGNED_BYTE) {
+      _mesa_unpack_ubyte_rgba_row(rb->Format, count, src,
+                                  (GLubyte (*)[4]) values + skip);
+   }
+   else if (type == GL_FLOAT) {
+      _mesa_unpack_rgba_row(rb->Format, count, src,
+                            (GLfloat (*)[4]) values + skip);
+   }
+   else {
+      _mesa_problem(ctx, "unexpected type in get_row()");
+   }
 }
 
 
@@ -1479,7 +1571,6 @@ void *
 _swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb,
                       SWspan *span)
 {
-   const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
    void *rbPixels;
 
    /* Point rbPixels to a temporary space */
@@ -1487,12 +1578,12 @@ _swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb,
 
    /* Get destination values from renderbuffer */
    if (span->arrayMask & SPAN_XY) {
-      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
-                         rbPixels, pixelSize);
+      get_values(ctx, rb, span->end, span->array->x, span->array->y,
+                 rbPixels, span->array->ChanType);
    }
    else {
-      _swrast_get_row(ctx, rb, span->end, span->x, span->y,
-                      rbPixels, pixelSize);
+      get_row(ctx, rb, span->end, span->x, span->y,
+              rbPixels, span->array->ChanType);
    }
 
    return rbPixels;