From bd3b40ad75d50483aaa99ad2d08a3dd8f20cdb42 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Sun, 31 Oct 2004 17:36:23 +0000 Subject: PBO support for glConvolutionFilter1D/2D, glGetConvolutionFilter, etc. --- src/mesa/main/convolve.c | 258 +++++++++++++++++++++++++++++++++++--------- src/mesa/swrast/s_imaging.c | 18 +++- 2 files changed, 223 insertions(+), 53 deletions(-) (limited to 'src/mesa') diff --git a/src/mesa/main/convolve.c b/src/mesa/main/convolve.c index adc279069b..afa550a481 100644 --- a/src/mesa/main/convolve.c +++ b/src/mesa/main/convolve.c @@ -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; diff --git a/src/mesa/swrast/s_imaging.c b/src/mesa/swrast/s_imaging.c index 52c809f7a9..a15cc0ba57 100644 --- a/src/mesa/swrast/s_imaging.c +++ b/src/mesa/swrast/s_imaging.c @@ -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; } -- cgit v1.2.3