PBO support for glConvolutionFilter1D/2D, glGetConvolutionFilter, etc.
authorBrian Paul <brian.paul@tungstengraphics.com>
Sun, 31 Oct 2004 17:36:23 +0000 (17:36 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Sun, 31 Oct 2004 17:36:23 +0000 (17:36 +0000)
src/mesa/main/convolve.c
src/mesa/swrast/s_imaging.c

index adc279069b64b63b36de0f0b1a3a5f984cf97a96..afa550a4812eec22cd95ac30e1669712795e6557 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.1
+ * Version:  6.3
  *
  * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
@@ -32,6 +32,7 @@
 
 
 #include "glheader.h"
+#include "bufferobj.h"
 #include "colormac.h"
 #include "convolve.h"
 #include "context.h"
@@ -142,12 +143,40 @@ _mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, G
    ctx->Convolution1D.Width = width;
    ctx->Convolution1D.Height = 1;
 
-   /* unpack filter image */
+   if (ctx->Unpack.BufferObj->Name) {
+      /* unpack filter from PBO */
+      GLubyte *buf;
+      if (!_mesa_validate_pbo_access(&ctx->Unpack, width, 1, 1,
+                                     format, type, image)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glConvolutionFilter1D(invalid PBO access)");
+         return;
+      }
+      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                                              GL_READ_ONLY_ARB,
+                                              ctx->Unpack.BufferObj);
+      if (!buf) {
+         /* buffer is already mapped - that's an error */
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glConvolutionFilter1D(PBO is mapped)");
+         return;
+      }
+      image = ADD_POINTERS(buf, image);
+   }
+   else if (!image) {
+      return;
+   }
+
    _mesa_unpack_color_span_float(ctx, width, GL_RGBA,
                                  ctx->Convolution1D.Filter,
                                  format, type, image, &ctx->Unpack,
                                  0); /* transferOps */
 
+   if (ctx->Unpack.BufferObj->Name) {
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                              ctx->Unpack.BufferObj);
+   }
+
    /* apply scale and bias */
    {
       const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[0];
@@ -222,6 +251,30 @@ _mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, G
    ctx->Convolution2D.Width = width;
    ctx->Convolution2D.Height = height;
 
+   if (ctx->Unpack.BufferObj->Name) {
+      /* unpack filter from PBO */
+      GLubyte *buf;
+      if (!_mesa_validate_pbo_access(&ctx->Unpack, width, height, 1,
+                                     format, type, image)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glConvolutionFilter2D(invalid PBO access)");
+         return;
+      }
+      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                                              GL_READ_ONLY_ARB,
+                                              ctx->Unpack.BufferObj);
+      if (!buf) {
+         /* buffer is already mapped - that's an error */
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glConvolutionFilter2D(PBO is mapped)");
+         return;
+      }
+      image = ADD_POINTERS(buf, image);
+   }
+   else if (!image) {
+      return;
+   }
+
    /* Unpack filter image.  We always store filters in RGBA format. */
    for (i = 0; i < height; i++) {
       const GLvoid *src = _mesa_image_address(&ctx->Unpack, image, width,
@@ -232,6 +285,11 @@ _mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, G
                                     0); /* transferOps */
    }
 
+   if (ctx->Unpack.BufferObj->Name) {
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                              ctx->Unpack.BufferObj);
+   }
+
    /* apply scale and bias */
    {
       const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[1];
@@ -516,7 +574,6 @@ _mesa_CopyConvolutionFilter2D(GLenum target, GLenum internalFormat, GLint x, GLi
 
    ctx->Driver.CopyConvolutionFilter2D( ctx, target, internalFormat, x, y, 
                                        width, height );
-
 }
 
 
@@ -558,6 +615,27 @@ _mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, GLvoid *im
          return;
    }
 
+   if (ctx->Pack.BufferObj->Name) {
+      /* Pack the filter into a PBO */
+      GLubyte *buf;
+      if (!_mesa_validate_pbo_access(&ctx->Pack, filter->Width, filter->Height,
+                                     1, format, type, image)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetConvolutionFilter(invalid PBO access)");
+         return;
+      }
+      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+                                              GL_WRITE_ONLY_ARB,
+                                              ctx->Pack.BufferObj);
+      if (!buf) {
+         /* buffer is already mapped - that's an error */
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetConvolutionFilter(PBO is mapped)");
+         return;
+      }
+      image = ADD_POINTERS(image, buf);
+   }
+
    for (row = 0; row < filter->Height; row++) {
       GLvoid *dst = _mesa_image_address( &ctx->Pack, image, filter->Width,
                                          filter->Height, format, type,
@@ -567,6 +645,11 @@ _mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, GLvoid *im
                                  (const GLfloat (*)[4]) src,
                                  format, type, dst, &ctx->Pack, 0);
    }
+
+   if (ctx->Pack.BufferObj->Name) {
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+                              ctx->Pack.BufferObj);
+   }
 }
 
 
@@ -734,8 +817,36 @@ _mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid *row,
 
    filter = &ctx->Separable2D;
 
+   if (ctx->Pack.BufferObj->Name) {
+      /* Pack filter into PBO */
+      GLubyte *buf;
+      if (!_mesa_validate_pbo_access(&ctx->Pack, filter->Width, 1, 1,
+                                     format, type, row)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetSeparableFilter(invalid PBO access, width)");
+         return;
+      }
+      if (!_mesa_validate_pbo_access(&ctx->Pack, filter->Height, 1, 1,
+                                     format, type, column)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetSeparableFilter(invalid PBO access, height)");
+         return;
+      }
+      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+                                              GL_WRITE_ONLY_ARB,
+                                              ctx->Pack.BufferObj);
+      if (!buf) {
+         /* buffer is already mapped - that's an error */
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glGetSeparableFilter(PBO is mapped)");
+         return;
+      }
+      row = ADD_POINTERS(buf, row);
+      column = ADD_POINTERS(buf, column);
+   }
+
    /* Row filter */
-   {
+   if (row) {
       GLvoid *dst = _mesa_image_address( &ctx->Pack, row, filter->Width,
                                          filter->Height, format, type,
                                          0, 0, 0);
@@ -745,7 +856,7 @@ _mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid *row,
    }
 
    /* Column filter */
-   {
+   if (column) {
       GLvoid *dst = _mesa_image_address( &ctx->Pack, column, filter->Width,
                                          1, format, type,
                                          0, 0, 0);
@@ -756,6 +867,12 @@ _mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid *row,
    }
 
    (void) span;  /* unused at this time */
+
+   if (ctx->Pack.BufferObj->Name) {
+      /* Pack filter into PBO */
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                              ctx->Unpack.BufferObj);
+   }
 }
 
 
@@ -806,58 +923,95 @@ _mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLs
    ctx->Separable2D.Width = width;
    ctx->Separable2D.Height = height;
 
-   /* unpack row filter */
-   _mesa_unpack_color_span_float(ctx, width, GL_RGBA,
-                                 ctx->Separable2D.Filter,
-                                 format, type, row, &ctx->Unpack,
-                                 0);  /* transferOps */
+   if (ctx->Unpack.BufferObj->Name) {
+      /* unpack filter from PBO */
+      GLubyte *buf;
+      if (!_mesa_validate_pbo_access(&ctx->Unpack, width, 1, 1,
+                                     format, type, row)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glSeparableFilter2D(invalid PBO access, width)");
+         return;
+      }
+      if (!_mesa_validate_pbo_access(&ctx->Unpack, height, 1, 1,
+                                     format, type, column)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glSeparableFilter2D(invalid PBO access, height)");
+         return;
+      }
+      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                                              GL_READ_ONLY_ARB,
+                                              ctx->Unpack.BufferObj);
+      if (!buf) {
+         /* buffer is already mapped - that's an error */
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glSeparableFilter2D(PBO is mapped)");
+         return;
+      }
+      row = ADD_POINTERS(buf, row);
+      column = ADD_POINTERS(buf, column);
+   }
 
-   /* apply scale and bias */
-   {
-      const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[2];
-      const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[2];
-      GLint i;
-      for (i = 0; i < width; i++) {
-         GLfloat r = ctx->Separable2D.Filter[i * 4 + 0];
-         GLfloat g = ctx->Separable2D.Filter[i * 4 + 1];
-         GLfloat b = ctx->Separable2D.Filter[i * 4 + 2];
-         GLfloat a = ctx->Separable2D.Filter[i * 4 + 3];
-         r = r * scale[0] + bias[0];
-         g = g * scale[1] + bias[1];
-         b = b * scale[2] + bias[2];
-         a = a * scale[3] + bias[3];
-         ctx->Separable2D.Filter[i * 4 + 0] = r;
-         ctx->Separable2D.Filter[i * 4 + 1] = g;
-         ctx->Separable2D.Filter[i * 4 + 2] = b;
-         ctx->Separable2D.Filter[i * 4 + 3] = a;
+   /* unpack row filter */
+   if (row) {
+      _mesa_unpack_color_span_float(ctx, width, GL_RGBA,
+                                    ctx->Separable2D.Filter,
+                                    format, type, row, &ctx->Unpack,
+                                    0);  /* transferOps */
+
+      /* apply scale and bias */
+      {
+         const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[2];
+         const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[2];
+         GLint i;
+         for (i = 0; i < width; i++) {
+            GLfloat r = ctx->Separable2D.Filter[i * 4 + 0];
+            GLfloat g = ctx->Separable2D.Filter[i * 4 + 1];
+            GLfloat b = ctx->Separable2D.Filter[i * 4 + 2];
+            GLfloat a = ctx->Separable2D.Filter[i * 4 + 3];
+            r = r * scale[0] + bias[0];
+            g = g * scale[1] + bias[1];
+            b = b * scale[2] + bias[2];
+            a = a * scale[3] + bias[3];
+            ctx->Separable2D.Filter[i * 4 + 0] = r;
+            ctx->Separable2D.Filter[i * 4 + 1] = g;
+            ctx->Separable2D.Filter[i * 4 + 2] = b;
+            ctx->Separable2D.Filter[i * 4 + 3] = a;
+         }
       }
    }
 
    /* unpack column filter */
-   _mesa_unpack_color_span_float(ctx, width, GL_RGBA,
-                                 &ctx->Separable2D.Filter[colStart],
-                                 format, type, column, &ctx->Unpack,
-                                 0); /* transferOps */
-
-   /* apply scale and bias */
-   {
-      const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[2];
-      const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[2];
-      GLint i;
-      for (i = 0; i < width; i++) {
-         GLfloat r = ctx->Separable2D.Filter[i * 4 + 0 + colStart];
-         GLfloat g = ctx->Separable2D.Filter[i * 4 + 1 + colStart];
-         GLfloat b = ctx->Separable2D.Filter[i * 4 + 2 + colStart];
-         GLfloat a = ctx->Separable2D.Filter[i * 4 + 3 + colStart];
-         r = r * scale[0] + bias[0];
-         g = g * scale[1] + bias[1];
-         b = b * scale[2] + bias[2];
-         a = a * scale[3] + bias[3];
-         ctx->Separable2D.Filter[i * 4 + 0 + colStart] = r;
-         ctx->Separable2D.Filter[i * 4 + 1 + colStart] = g;
-         ctx->Separable2D.Filter[i * 4 + 2 + colStart] = b;
-         ctx->Separable2D.Filter[i * 4 + 3 + colStart] = a;
-      }
+   if (column) {
+     _mesa_unpack_color_span_float(ctx, height, GL_RGBA,
+                                   &ctx->Separable2D.Filter[colStart],
+                                   format, type, column, &ctx->Unpack,
+                                   0); /* transferOps */
+
+     /* apply scale and bias */
+     {
+        const GLfloat *scale = ctx->Pixel.ConvolutionFilterScale[2];
+        const GLfloat *bias = ctx->Pixel.ConvolutionFilterBias[2];
+        GLint i;
+        for (i = 0; i < height; i++) {
+           GLfloat r = ctx->Separable2D.Filter[i * 4 + 0 + colStart];
+           GLfloat g = ctx->Separable2D.Filter[i * 4 + 1 + colStart];
+           GLfloat b = ctx->Separable2D.Filter[i * 4 + 2 + colStart];
+           GLfloat a = ctx->Separable2D.Filter[i * 4 + 3 + colStart];
+           r = r * scale[0] + bias[0];
+           g = g * scale[1] + bias[1];
+           b = b * scale[2] + bias[2];
+           a = a * scale[3] + bias[3];
+           ctx->Separable2D.Filter[i * 4 + 0 + colStart] = r;
+           ctx->Separable2D.Filter[i * 4 + 1 + colStart] = g;
+           ctx->Separable2D.Filter[i * 4 + 2 + colStart] = b;
+           ctx->Separable2D.Filter[i * 4 + 3 + colStart] = a;
+        }
+     }
+   }
+
+   if (ctx->Unpack.BufferObj->Name) {
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                              ctx->Unpack.BufferObj);
    }
 
    ctx->NewState |= _NEW_PIXEL;
index 52c809f7a9bc946924a320da4952dcc27b5721ce..a15cc0ba57c88b84dbf254ec8e202384bea79f28 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.1
+ * Version:  6.3
  *
  * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
@@ -85,6 +85,7 @@ _swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    GLchan rgba[MAX_CONVOLUTION_WIDTH][4];
+   struct gl_buffer_object *bufferSave;
 
    /* Select buffer to read from */
    _swrast_use_read_buffer(ctx);
@@ -100,9 +101,16 @@ _swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
    /* Restore reading from draw buffer (the default) */
    _swrast_use_draw_buffer(ctx);
 
+   /* save PBO binding */
+   bufferSave = ctx->Unpack.BufferObj;
+   ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
+
    /* store as convolution filter */
    _mesa_ConvolutionFilter1D(target, internalFormat, width,
                              GL_RGBA, CHAN_TYPE, rgba);
+
+   /* restore PBO binding */
+   ctx->Unpack.BufferObj = bufferSave;
 }
 
 
@@ -115,6 +123,7 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
    struct gl_pixelstore_attrib packSave;
    GLchan rgba[MAX_CONVOLUTION_HEIGHT][MAX_CONVOLUTION_WIDTH][4];
    GLint i;
+   struct gl_buffer_object *bufferSave;
 
    /* Select buffer to read from */
    _swrast_use_read_buffer(ctx);
@@ -151,9 +160,16 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
    ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
    ctx->NewState |= _NEW_PACKUNPACK;
 
+   /* save PBO binding */
+   bufferSave = ctx->Unpack.BufferObj;
+   ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
+
    _mesa_ConvolutionFilter2D(target, internalFormat, width, height,
                              GL_RGBA, CHAN_TYPE, rgba);
 
+   /* restore PBO binding */
+   ctx->Unpack.BufferObj = bufferSave;
+
    ctx->Unpack = packSave;  /* restore pixel packing params */
    ctx->NewState |= _NEW_PACKUNPACK; 
 }