basic glDrawPixels convolution implemented
authorBrian Paul <brian.paul@tungstengraphics.com>
Mon, 21 Aug 2000 14:24:10 +0000 (14:24 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Mon, 21 Aug 2000 14:24:10 +0000 (14:24 +0000)
src/mesa/main/drawpix.c

index 02d618fc2df45be742e552137b8f4989c96d1fc6..3cf40956ab4bc88abcabbfc3ef49321e20bd87d3 100644 (file)
@@ -1,8 +1,8 @@
-/* $Id: drawpix.c,v 1.28 2000/08/16 20:51:53 brianp Exp $ */
+/* $Id: drawpix.c,v 1.29 2000/08/21 14:24:10 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.4
+ * Version:  3.5
  * 
  * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
  * 
@@ -30,6 +30,7 @@
 #else
 #include "glheader.h"
 #include "context.h"
+#include "convolve.h"
 #include "drawpix.h"
 #include "feedback.h"
 #include "image.h"
@@ -99,10 +100,21 @@ _mesa_clip_pixelrect(const GLcontext *ctx,
  * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
  */
 static GLboolean
-simple_DrawPixels( GLcontext *ctx, GLint x, GLint y,
-                   GLsizei width, GLsizei height, GLenum format, GLenum type,
-                   const GLvoid *pixels )
+fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
+                 GLsizei width, GLsizei height,
+                 GLenum format, GLenum type, const GLvoid *pixels)
 {
+   const GLuint cantTransferBits =
+      IMAGE_SCALE_BIAS_BIT |
+      IMAGE_SHIFT_OFFSET_BIT |
+      IMAGE_MAP_COLOR_BIT |
+      IMAGE_COLOR_TABLE_BIT |
+      IMAGE_CONVOLUTION_BIT |
+      IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT |
+      IMAGE_COLOR_MATRIX_BIT |
+      IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT |
+      IMAGE_HISTOGRAM_BIT |
+      IMAGE_MIN_MAX_BIT;
    const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
    GLubyte rgb[MAX_WIDTH][3];
    GLubyte rgba[MAX_WIDTH][4];
@@ -112,23 +124,13 @@ simple_DrawPixels( GLcontext *ctx, GLint x, GLint y,
 
 
    if (!ctx->Current.RasterPosValid) {
-      /* no-op */
-      return GL_TRUE;
+      return GL_TRUE;      /* no-op */
    }
 
    if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
-       && !ctx->Pixel.ScaleOrBiasRGBA
-       && !ctx->Pixel.ScaleOrBiasRGBApcm
-       && ctx->ColorMatrix.type == MATRIX_IDENTITY
-       && !ctx->Pixel.ColorTableEnabled
-       && !ctx->Pixel.PostColorMatrixColorTableEnabled
-       && !ctx->Pixel.PostConvolutionColorTableEnabled
-       && !ctx->Pixel.MinMaxEnabled
-       && !ctx->Pixel.HistogramEnabled
-       && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0
-       && ctx->Pixel.MapColorFlag==0
+       && (ctx->ImageTransferState & cantTransferBits) == 0
        && ctx->Texture.ReallyEnabled == 0
-       && unpack->Alignment==1
+       && unpack->Alignment == 1
        && !unpack->SwapBytes
        && !unpack->LsbFirst) {
 
@@ -525,7 +527,8 @@ draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
       const GLvoid *source = _mesa_image_address(&ctx->Unpack,
                     pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
       _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes,
-                              type, source, &ctx->Unpack, GL_TRUE);
+                              type, source, &ctx->Unpack,
+                              ctx->ImageTransferState);
       if (zoom) {
          gl_write_zoomed_index_span(ctx, drawWidth, x, y, zspan, indexes, desty);
       }
@@ -547,7 +550,6 @@ draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
                      GLenum type, const GLvoid *pixels )
 {
    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
-   const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
    const GLint desty = y;
    GLint row, drawWidth;
 
@@ -572,8 +574,9 @@ draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
       const GLvoid *source = _mesa_image_address(&ctx->Unpack,
                     pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
       _mesa_unpack_index_span(ctx, drawWidth, destType, values,
-                              type, source, &ctx->Unpack, GL_FALSE);
-      if (shift_or_offset) {
+                              type, source, &ctx->Unpack,
+                              ctx->ImageTransferState);
+      if (ctx->ImageTransferState & IMAGE_SHIFT_OFFSET_BIT) {
          _mesa_shift_and_offset_stencil( ctx, drawWidth, values );
       }
       if (ctx->Pixel.MapStencilFlag) {
@@ -671,7 +674,7 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
          const GLvoid *src = _mesa_image_address(&ctx->Unpack,
                 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
          _mesa_unpack_depth_span( ctx, drawWidth, zspan, type, src,
-                                  &ctx->Unpack, GL_TRUE );
+                                  &ctx->Unpack, ctx->ImageTransferState );
          if (ctx->Visual->RGBAflag) {
             if (zoom) {
                gl_write_zoomed_rgba_span(ctx, width, x, y, zspan,
@@ -709,9 +712,11 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
    const GLint desty = y;
    GLdepth zspan[MAX_WIDTH];
    GLboolean quickDraw;
+   GLfloat *convImage = NULL;
+   GLuint transferOps = ctx->ImageTransferState;
 
    /* Try an optimized glDrawPixels first */
-   if (simple_DrawPixels(ctx, x, y, width, height, format, type, pixels))
+   if (fast_draw_pixels(ctx, x, y, width, height, format, type, pixels))
       return;
 
    /* Fragment depth values */
@@ -725,8 +730,7 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
    }
 
 
-   if (ctx->RasterMask == 0 && !zoom
-       && x >= 0 && y >= 0
+   if (ctx->RasterMask == 0 && !zoom && x >= 0 && y >= 0
        && x + width <= ctx->DrawBuffer->Width
        && y + height <= ctx->DrawBuffer->Height) {
       quickDraw = GL_TRUE;
@@ -735,6 +739,69 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
       quickDraw = GL_FALSE;
    }
 
+   if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
+      /* Convolution has to be handled specially.  We'll create an
+       * intermediate image, applying all pixel transfer operations
+       * up to convolution.  Then we'll convolve the image.  Then
+       * we'll proceed with the rest of the transfer operations and
+       * rasterize the image.
+       */
+      const GLuint preConvTransferOps =
+         IMAGE_SCALE_BIAS_BIT |
+         IMAGE_SHIFT_OFFSET_BIT |
+         IMAGE_MAP_COLOR_BIT |
+         IMAGE_COLOR_TABLE_BIT;
+      const GLuint postConvTransferOps =
+         IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT |
+         IMAGE_COLOR_MATRIX_BIT |
+         IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT |
+         IMAGE_HISTOGRAM_BIT |
+         IMAGE_MIN_MAX_BIT;
+      GLint row;
+      GLfloat *dest, *tmpImage;
+
+      tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
+      if (!tmpImage) {
+         gl_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+         return;
+      }
+      convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
+      if (!convImage) {
+         FREE(tmpImage);
+         gl_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+         return;
+      }
+
+      /* Unpack the image and apply transfer ops up to convolution */
+      dest = tmpImage;
+      for (row = 0; row < height; row++) {
+         const GLvoid *source = _mesa_image_address(unpack,
+                  pixels, width, height, format, type, 0, row, 0);
+         _mesa_unpack_float_color_span(ctx, width, GL_RGBA, (void *) dest,
+                                       format, type, source, unpack,
+                                       transferOps & preConvTransferOps,
+                                       GL_FALSE);
+         dest += width * 4;
+      }
+
+      /* do convolution */
+      if (ctx->Pixel.Convolution2DEnabled) {
+         _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
+      }
+      else if (ctx->Pixel.Separable2DEnabled) {
+         _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
+      }
+
+      FREE(tmpImage);
+
+      /* continue transfer ops and draw the convolved image */
+      unpack = &_mesa_native_packing;
+      pixels = convImage;
+      format = GL_RGBA;
+      type = GL_FLOAT;
+      transferOps &= postConvTransferOps;
+   }
+
    /*
     * General solution
     */
@@ -747,7 +814,8 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
          const GLvoid *source = _mesa_image_address(unpack,
                   pixels, width, height, format, type, 0, row, 0);
          _mesa_unpack_ubyte_color_span(ctx, width, GL_RGBA, (void*) rgba,
-                   format, type, source, unpack, GL_TRUE);
+                                       format, type, source, unpack,
+                                       transferOps);
          if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) ||
              (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink))
             continue;
@@ -781,6 +849,10 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
          }
       }
    }
+
+   if (convImage) {
+      FREE(convImage);
+   }
 }
 
 
@@ -805,6 +877,9 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
          gl_update_state(ctx);
       }
 
+      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
+         _mesa_update_image_transfer_state(ctx);
+
       x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
       y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);