PBO support for glConvolutionFilter1D/2D, glGetConvolutionFilter, etc.

This commit is contained in:
Brian Paul 2004-10-31 17:36:23 +00:00
parent d56928f10d
commit bd3b40ad75
2 changed files with 222 additions and 52 deletions

View 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 */
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 < 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;
}
/* 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;

View 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;
}