Lots of changes to support runtime renderbuffer depths.

_swrast_read_rgba_span() now takes a datatype parameter.
New optimization for glReadPixels(format=GL_RGB).
New glCopyPixels optimization for the simple, common cases.
This commit is contained in:
Brian Paul
2006-10-12 23:17:02 +00:00
parent 4bb9f4115c
commit 76e778dce5
9 changed files with 369 additions and 311 deletions

View File

@@ -307,7 +307,7 @@ accum_accum(GLcontext *ctx, GLfloat value,
/* read colors from color buffer */
_swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
xpos, ypos + i, rgba);
xpos, ypos + i, CHAN_TYPE, rgba);
/* do accumulation */
if (swrast->_IntegerAccumMode) {
@@ -391,7 +391,7 @@ accum_load(GLcontext *ctx, GLfloat value,
/* read colors from color buffer */
_swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer, width,
xpos, ypos + i, rgba);
xpos, ypos + i, CHAN_TYPE, rgba);
/* do load */
if (swrast->_IntegerAccumMode) {

View File

@@ -432,6 +432,16 @@ _swrast_validate_derived( GLcontext *ctx );
/**
* Size of an RGBA pixel, in bytes, for given datatype.
*/
#define RGBA_PIXEL_SIZE(TYPE) \
((TYPE == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) : \
((TYPE == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort) \
: 4 * sizeof(GLfloat)))
/*
* XXX these macros are just bandages for now in order to make
* CHAN_BITS==32 compile cleanly.

View File

@@ -41,11 +41,12 @@
/*
/**
* Determine if there's overlap in an image copy.
* This test also compensates for the fact that copies are done from
* bottom to top and overlaps can sometimes be handled correctly
* without making a temporary image copy.
* \return GL_TRUE if the regions overlap, GL_FALSE otherwise.
*/
static GLboolean
regions_overlap(GLint srcx, GLint srcy,
@@ -87,41 +88,6 @@ regions_overlap(GLint srcx, GLint srcy,
/**
* Convert GLfloat[n][4] colors to GLchan[n][4].
* XXX maybe move into image.c
*/
static void
float_span_to_chan(GLuint n, CONST GLfloat in[][4], GLchan out[][4])
{
GLuint i;
for (i = 0; i < n; i++) {
UNCLAMPED_FLOAT_TO_CHAN(out[i][RCOMP], in[i][RCOMP]);
UNCLAMPED_FLOAT_TO_CHAN(out[i][GCOMP], in[i][GCOMP]);
UNCLAMPED_FLOAT_TO_CHAN(out[i][BCOMP], in[i][BCOMP]);
UNCLAMPED_FLOAT_TO_CHAN(out[i][ACOMP], in[i][ACOMP]);
}
}
/**
* Convert GLchan[n][4] colors to GLfloat[n][4].
* XXX maybe move into image.c
*/
static void
chan_span_to_float(GLuint n, CONST GLchan in[][4], GLfloat out[][4])
{
GLuint i;
for (i = 0; i < n; i++) {
out[i][RCOMP] = CHAN_TO_FLOAT(in[i][RCOMP]);
out[i][GCOMP] = CHAN_TO_FLOAT(in[i][GCOMP]);
out[i][BCOMP] = CHAN_TO_FLOAT(in[i][BCOMP]);
out[i][ACOMP] = CHAN_TO_FLOAT(in[i][ACOMP]);
}
}
/*
* RGBA copypixels with convolution.
*/
static void
@@ -129,11 +95,11 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
GLint width, GLint height, GLint destx, GLint desty)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_renderbuffer *drawRb = NULL;
GLboolean quick_draw;
GLint row;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
const GLuint transferOps = ctx->_ImageTransferState;
const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink)
|| (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink);
GLfloat *dest, *tmpImage, *convImage;
SWspan span;
@@ -145,17 +111,6 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
_swrast_span_default_fog(ctx, &span);
if (SWRAST_CONTEXT(ctx)->_RasterMask == 0
&& !zoom
&& destx >= 0
&& destx + width <= (GLint) ctx->DrawBuffer->Width) {
quick_draw = GL_TRUE;
drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
}
else {
quick_draw = GL_FALSE;
}
/* allocate space for GLfloat image */
tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
if (!tmpImage) {
@@ -169,15 +124,11 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
return;
}
/* read source image */
/* read source image as float/RGBA */
dest = tmpImage;
for (row = 0; row < height; row++) {
GLchan rgba[MAX_WIDTH][4];
/* Read GLchan and convert to GLfloat */
_swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, srcx, srcy + row, rgba);
chan_span_to_float(width, (CONST GLchan (*)[4]) rgba,
(GLfloat (*)[4]) dest);
width, srcx, srcy + row, GL_FLOAT, dest);
dest += 4 * width;
}
@@ -207,38 +158,36 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
width, rgba);
}
if (!sink) {
/* write the new image */
for (row = 0; row < height; row++) {
const GLfloat *src = convImage + row * width * 4;
GLint dy;
GLvoid *rgba = span.array->color.sz1.rgba; /* row storage */
/* convert floats back to chan */
float_span_to_chan(width, (const GLfloat (*)[4]) src, span.array->rgba);
/* copy convolved colors into span array */
_mesa_memcpy(rgba, src, width * 4 * sizeof(GLfloat));
/* write row to framebuffer */
dy = desty + row;
if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) {
drawRb->PutRow(ctx, drawRb, width, destx, dy, span.array->rgba, NULL);
}
else {
/* write span */
span.x = destx;
span.y = dy;
span.y = desty + row;
span.end = width;
span.array->ChanType = GL_FLOAT;
if (zoom) {
_swrast_write_zoomed_rgba_span(ctx, destx, desty, &span,
span.array->rgba);
_swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
}
else {
_swrast_write_rgba_span(ctx, &span);
}
}
/* restore this */
span.array->ChanType = CHAN_TYPE;
}
_mesa_free(convImage);
}
/*
/**
* RGBA copypixels
*/
static void
@@ -246,10 +195,8 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
GLint width, GLint height, GLint destx, GLint desty)
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_renderbuffer *drawRb;
GLchan *tmpImage,*p;
GLboolean quick_draw;
GLint sy, dy, stepy, j;
GLfloat *tmpImage, *p;
GLint sy, dy, stepy, row;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
GLint overlapping;
const GLuint transferOps = ctx->_ImageTransferState;
@@ -260,8 +207,6 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
return;
}
INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty);
return;
@@ -289,35 +234,23 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
overlapping = GL_FALSE;
}
INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
if (ctx->Depth.Test)
_swrast_span_default_z(ctx, &span);
if (swrast->_FogEnabled)
_swrast_span_default_fog(ctx, &span);
if (SWRAST_CONTEXT(ctx)->_RasterMask == 0
&& !zoom
&& destx >= 0
&& destx + width <= (GLint) ctx->DrawBuffer->Width) {
quick_draw = GL_TRUE;
drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
}
else {
quick_draw = GL_FALSE;
drawRb = NULL;
}
if (overlapping) {
GLint ssy = sy;
tmpImage = (GLchan *) _mesa_malloc(width * height * sizeof(GLchan) * 4);
tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat) * 4);
if (!tmpImage) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
return;
}
/* read the source image */
/* read the source image as RGBA/float */
p = tmpImage;
for (j = 0; j < height; j++, ssy += stepy) {
for (row = 0; row < height; row++) {
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, srcx, ssy, (GLchan (*)[4]) p );
width, srcx, sy + row, GL_FLOAT, p );
p += width * 4;
}
p = tmpImage;
@@ -327,48 +260,42 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
p = NULL;
}
for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
/* Get source pixels */
ASSERT(width < MAX_WIDTH);
for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
GLvoid *rgba = span.array->color.sz4.rgba;
/* Get row/span of source pixels */
if (overlapping) {
/* get from buffered image */
ASSERT(width < MAX_WIDTH);
_mesa_memcpy(span.array->rgba, p, width * sizeof(GLchan) * 4);
_mesa_memcpy(rgba, p, width * sizeof(GLfloat) * 4);
p += width * 4;
}
else {
/* get from framebuffer */
ASSERT(width < MAX_WIDTH);
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, srcx, sy, span.array->rgba );
width, srcx, sy, GL_FLOAT, rgba );
}
if (transferOps) {
GLfloat rgbaFloat[MAX_WIDTH][4];
/* convert to float, transfer, convert back to chan */
chan_span_to_float(width, (CONST GLchan (*)[4]) span.array->rgba,
rgbaFloat);
_mesa_apply_rgba_transfer_ops(ctx, transferOps, width, rgbaFloat);
float_span_to_chan(width, (CONST GLfloat (*)[4]) rgbaFloat,
span.array->rgba);
_mesa_apply_rgba_transfer_ops(ctx, transferOps, width,
(GLfloat (*)[4]) rgba);
}
/* Write color span */
if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) {
drawRb->PutRow(ctx, drawRb, width, destx, dy, span.array->rgba, NULL);
}
else {
span.x = destx;
span.y = dy;
span.end = width;
span.array->ChanType = GL_FLOAT;
if (zoom) {
_swrast_write_zoomed_rgba_span(ctx, destx, desty, &span,
span.array->rgba);
_swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
}
else {
_swrast_write_rgba_span(ctx, &span);
}
}
}
span.array->ChanType = CHAN_TYPE; /* restore */
if (overlapping)
_mesa_free(tmpImage);
@@ -902,6 +829,87 @@ copy_depth_stencil_pixels(GLcontext *ctx,
}
/**
* Try to do a fast copy pixels.
*/
static GLboolean
fast_copy_pixels(GLcontext *ctx,
GLint srcX, GLint srcY, GLsizei width, GLsizei height,
GLint dstX, GLint dstY, GLenum type)
{
struct gl_framebuffer *srcFb = ctx->ReadBuffer;
struct gl_framebuffer *dstFb = ctx->DrawBuffer;
struct gl_renderbuffer *srcRb, *dstRb;
GLint row, yStep;
if (SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 ||
ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != 1.0F ||
ctx->_ImageTransferState) {
/* can't handle these */
return GL_FALSE;
}
if (type == GL_COLOR) {
if (dstFb->_NumColorDrawBuffers[0] != 1)
return GL_FALSE;
srcRb = srcFb->_ColorReadBuffer;
dstRb = dstFb->_ColorDrawBuffers[0][0];
}
else if (type == GL_STENCIL) {
srcRb = srcFb->_StencilBuffer;
dstRb = dstFb->_StencilBuffer;
}
else if (type == GL_DEPTH) {
srcRb = srcFb->_DepthBuffer;
dstRb = dstFb->_DepthBuffer;
}
else if (type == GL_DEPTH_STENCIL_EXT) {
/* XXX correct? */
srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
}
/* src and dst renderbuffers must be same format and type */
if (!srcRb || !dstRb ||
srcRb->DataType != dstRb->DataType ||
srcRb->_BaseFormat != dstRb->_BaseFormat) {
return GL_FALSE;
}
/* clipping not supported */
if (srcX < 0 || srcX + width > srcFb->Width ||
srcY < 0 || srcY + height > srcFb->Width ||
dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
return GL_FALSE;
}
/* overlapping src/dst doesn't matter, just determine Y direction */
if (srcY < dstY) {
/* top-down max-to-min */
srcY = srcY + height - 1;
dstY = dstY + height - 1;
yStep = -1;
}
else {
/* bottom-up min-to-max */
yStep = 1;
}
for (row = 0; row < height; row++) {
GLuint temp[MAX_WIDTH][4];
srcRb->GetRow(ctx, srcRb, width, srcX, srcY, temp);
dstRb->PutRow(ctx, dstRb, width, dstX, dstY, temp, NULL);
srcY += yStep;
dstY += yStep;
}
return GL_TRUE;
}
/**
* Do software-based glCopyPixels.
* By time we get here, all parameters will have been error-checked.
@@ -917,6 +925,7 @@ _swrast_CopyPixels( GLcontext *ctx,
if (swrast->NewState)
_swrast_validate_derived( ctx );
if (!fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) {
switch (type) {
case GL_COLOR:
if (ctx->Visual.rgbMode) {
@@ -938,6 +947,7 @@ _swrast_CopyPixels( GLcontext *ctx,
default:
_mesa_problem(ctx, "unexpected type in _swrast_CopyPixels");
}
}
RENDER_FINISH(swrast,ctx);
}

View File

@@ -40,12 +40,13 @@
#include "s_zoom.h"
/**
* Try to do a fast and simple RGB(a) glDrawPixels.
* Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
*/
static GLboolean
fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
fast_draw_rgba_pixels(GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *userUnpack,
@@ -63,7 +64,6 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
if ((swrast->_RasterMask & ~CLIP_BIT) ||
ctx->Texture._EnabledCoordUnits ||
userUnpack->Alignment != 1 ||
userUnpack->SwapBytes ||
ctx->_ImageTransferState) {
/* can't handle any of those conditions */
@@ -100,26 +100,25 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
else {
/* non-simple zooming */
simpleZoom = GL_FALSE;
yStep = 1;
if (unpack.RowLength == 0)
unpack.RowLength = width;
}
/*
* Ready to draw!
* The window region at (destX, destY) of size (drawWidth, drawHeight)
* will be written to.
* We'll take pixel data from buffer pointed to by "pixels" but we'll
* skip "unpack.SkipRows" rows and skip "unpack.SkipPixels" pixels/row.
*/
if (format == GL_RGBA && type == CHAN_TYPE && rbType == CHAN_TYPE) {
const GLchan *src = (const GLchan *) pixels
+ (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels) * 4;
if (format == GL_RGBA && type == rbType) {
const GLubyte *src = _mesa_image_address2d(&unpack, pixels, width,
height, format, type, 0, 0);
const GLint srcStride = _mesa_image_row_stride(&unpack, width,
format, type);
if (simpleZoom) {
GLint row;
for (row = 0; row < drawHeight; row++) {
rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL);
src += unpack.RowLength * 4;
src += srcStride;
destY += yStep;
}
}
@@ -130,21 +129,25 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
span.x = destX;
span.y = destY + row;
span.end = drawWidth;
span.array->ChanType = rbType;
_swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, src);
src += unpack.RowLength * 4;
src += srcStride;
}
span.array->ChanType = CHAN_TYPE;
}
return GL_TRUE;
}
if (format == GL_RGB && type == CHAN_TYPE && rbType == CHAN_TYPE) {
const GLchan *src = (const GLchan *) pixels
+ (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels) * 3;
if (format == GL_RGB && type == rbType) {
const GLubyte *src = _mesa_image_address2d(&unpack, pixels, width,
height, format, type, 0, 0);
const GLint srcStride = _mesa_image_row_stride(&unpack, width,
format, type);
if (simpleZoom) {
GLint row;
for (row = 0; row < drawHeight; row++) {
rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL);
src += unpack.RowLength * 3;
src += srcStride;
destY += yStep;
}
}
@@ -155,14 +158,20 @@ fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
span.x = destX;
span.y = destY;
span.end = drawWidth;
span.array->ChanType = rbType;
_swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, src);
src += unpack.RowLength * 3;
src += srcStride;
destY++;
}
span.array->ChanType = CHAN_TYPE;
}
return GL_TRUE;
}
/* Remaining cases haven't been tested with alignment != 1 */
if (userUnpack->Alignment != 1)
return GL_FALSE;
if (format == GL_LUMINANCE && type == CHAN_TYPE && rbType == CHAN_TYPE) {
const GLchan *src = (const GLchan *) pixels
+ (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels);
@@ -530,7 +539,7 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
/*
/**
* Draw RGBA image.
*/
static void
@@ -542,19 +551,17 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLint imgX = x, imgY = y;
struct gl_renderbuffer *rb = NULL; /* only used for quickDraw path */
const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
GLboolean quickDraw;
GLfloat *convImage = NULL;
GLuint transferOps = ctx->_ImageTransferState;
SWspan span;
/* Try an optimized glDrawPixels first */
if (fast_draw_pixels(ctx, x, y, width, height, format, type, unpack, pixels))
if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type,
unpack, pixels))
return;
INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
if (ctx->Depth.Test)
_swrast_span_default_z(ctx, &span);
if (swrast->_FogEnabled)
@@ -562,21 +569,6 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
if (ctx->Texture._EnabledCoordUnits)
_swrast_span_default_texcoords(ctx, &span);
if (swrast->_RasterMask == 0 && !zoom && x >= 0 && y >= 0
&& x + width <= (GLint) ctx->DrawBuffer->Width
&& y + height <= (GLint) ctx->DrawBuffer->Height
&& ctx->DrawBuffer->_NumColorDrawBuffers[0] == 1) {
rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
if (rb->DataType == format)
quickDraw = GL_TRUE;
else
quickDraw = GL_FALSE;
}
else {
quickDraw = GL_FALSE;
rb = NULL;
}
if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
/* Convolution has to be handled specially. We'll create an
* intermediate image, applying all pixel transfer operations
@@ -628,6 +620,13 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
transferOps &= IMAGE_POST_CONVOLUTION_BITS;
}
if (ctx->DrawBuffer->_NumColorDrawBuffers[0] > 0 &&
ctx->DrawBuffer->_ColorDrawBuffers[0][0]->DataType != GL_FLOAT &&
ctx->Color.ClampFragmentColor != GL_FALSE) {
/* need to clamp colors before applying fragment ops */
transferOps |= IMAGE_CLAMP_BIT;
}
/*
* General solution
*/
@@ -636,53 +635,51 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
|| (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink);
const GLbitfield interpMask = span.interpMask;
const GLbitfield arrayMask = span.arrayMask;
const GLint srcStride
= _mesa_image_row_stride(unpack, width, format, type);
GLint skipPixels = 0;
/* use span array for temp color storage */
GLfloat *rgba = (GLfloat *) span.array->color.sz4.rgba;
/* if the span is wider than MAX_WIDTH we have to do it in chunks */
while (skipPixels < width) {
const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
const GLubyte *source = _mesa_image_address2d(unpack, pixels,
width, height, format, type, 0, skipPixels);
GLint row;
ASSERT(span.end <= MAX_WIDTH);
for (row = 0; row < height; row++) {
const GLvoid *source = _mesa_image_address2d(unpack,
pixels, width, height, format, type, row, skipPixels);
/* Set these for each row since the _swrast_write_* function may
* change them while clipping.
/* get image row as float/RGBA */
_mesa_unpack_color_span_float(ctx, spanWidth, GL_RGBA, rgba,
format, type, source, unpack,
transferOps);
/* draw the span */
if (!sink) {
/* Set these for each row since the _swrast_write_* functions
* may change them while clipping/rendering.
*/
span.array->ChanType = CHAN_TYPE;
span.array->ChanType = GL_FLOAT;
span.x = x + skipPixels;
span.y = y + row;
span.end = spanWidth;
span.arrayMask = arrayMask;
span.interpMask = interpMask;
_mesa_unpack_color_span_chan(ctx, spanWidth, GL_RGBA,
(GLchan *) span.array->rgba,
format, type, source, unpack,
transferOps);
if (sink)
continue;
/* draw the span */
if (quickDraw) {
rb->PutRow(ctx, rb, span.end, span.x, span.y,
span.array->rgba, NULL);
}
else if (zoom) {
_swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
span.array->rgba);
if (zoom) {
_swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
}
else {
_swrast_write_rgba_span(ctx, &span);
}
}
source += srcStride;
} /* for row */
skipPixels += spanWidth;
}
} /* while skipPixels < width */
/* XXX this is ugly/temporary, to undo above change */
span.array->ChanType = CHAN_TYPE;
}
if (convImage) {

View File

@@ -54,7 +54,7 @@ _swrast_CopyColorTable( GLcontext *ctx,
/* read the data from framebuffer */
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, x, y, data );
width, x, y, CHAN_TYPE, data );
RENDER_FINISH(swrast,ctx);
@@ -89,7 +89,7 @@ _swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start,
/* read the data from framebuffer */
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, x, y, data );
width, x, y, CHAN_TYPE, data );
RENDER_FINISH(swrast,ctx);
@@ -122,7 +122,7 @@ _swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target,
/* read the data from framebuffer */
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, x, y, (GLchan (*)[4]) rgba );
width, x, y, CHAN_TYPE, rgba );
RENDER_FINISH( swrast, ctx );
@@ -160,7 +160,7 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target,
/* read pixels from framebuffer */
for (i = 0; i < height; i++) {
_swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, x, y + i, (GLchan (*)[4]) rgba[i] );
width, x, y + i, CHAN_TYPE, rgba[i] );
}
RENDER_FINISH(swrast,ctx);

View File

@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
* Version: 6.5
* Version: 6.5.2
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
@@ -197,7 +197,7 @@ read_stencil_pixels( GLcontext *ctx,
* scaling, biasing, mapping, etc. are disabled.
*/
static GLboolean
read_fast_rgba_pixels( GLcontext *ctx,
fast_read_rgba_pixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
@@ -206,53 +206,59 @@ read_fast_rgba_pixels( GLcontext *ctx,
{
struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
/* clipping should have already been done */
ASSERT(x + width <= rb->Width);
ASSERT(y + height <= rb->Height);
/* can't do scale, bias, mapping, etc */
if (ctx->_ImageTransferState)
/* check for things we can't handle here */
if (ctx->_ImageTransferState ||
packing->SwapBytes ||
packing->LsbFirst) {
return GL_FALSE;
}
/* can't do fancy pixel packing */
if (packing->Alignment != 1 || packing->SwapBytes || packing->LsbFirst)
return GL_FALSE;
/* if the pixel format exactly matches the renderbuffer format */
if (format == GL_RGBA && rb->DataType == type) {
GLint rowLength = (packing->RowLength > 0) ? packing->RowLength : width;
GLint pixelSize, row;
GLubyte *dest;
if (type == GL_UNSIGNED_BYTE)
pixelSize = 4 * sizeof(GLubyte);
else if (type == GL_UNSIGNED_SHORT)
pixelSize = 4 * sizeof(GLushort);
else {
ASSERT(type == GL_FLOAT);
pixelSize = 4 * sizeof(GLfloat);
}
dest = (GLubyte *) pixels
+ (packing->SkipRows * rowLength + packing->SkipPixels) * pixelSize;
if (packing->Invert) {
/* start at top and go down */
dest += (height - 1) * rowLength * pixelSize;
rowLength = -rowLength;
}
const GLint dstStride = _mesa_image_row_stride(packing, width,
format, type);
GLubyte *dest = _mesa_image_address2d(packing, pixels, width, height,
format, type, 0, 0);
GLint row;
ASSERT(rb->GetRow);
for (row = 0; row < height; row++) {
rb->GetRow(ctx, rb, width, x, y + row, dest);
dest += rowLength * pixelSize;
dest += dstStride;
}
return GL_TRUE;
}
else {
/* can't do this format/type combination */
return GL_FALSE;
if (format == GL_RGB &&
rb->DataType == GL_UNSIGNED_BYTE &&
type == GL_UNSIGNED_BYTE) {
const GLint dstStride = _mesa_image_row_stride(packing, width,
format, type);
GLubyte *dest = _mesa_image_address2d(packing, pixels, width, height,
format, type, 0, 0);
GLint row;
ASSERT(rb->GetRow);
for (row = 0; row < height; row++) {
GLubyte tempRow[MAX_WIDTH][4];
GLint col;
rb->GetRow(ctx, rb, width, x, y + row, tempRow);
/* convert RGBA to RGB */
for (col = 0; col < width; col++) {
dest[col * 3 + 0] = tempRow[col][0];
dest[col * 3 + 1] = tempRow[col][1];
dest[col * 3 + 2] = tempRow[col][2];
}
dest += dstStride;
}
return GL_TRUE;
}
/* not handled */
return GL_FALSE;
}
@@ -267,14 +273,15 @@ read_rgba_pixels( GLcontext *ctx,
GLenum format, GLenum type, GLvoid *pixels,
const struct gl_pixelstore_attrib *packing )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct gl_framebuffer *fb = ctx->ReadBuffer;
struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
ASSERT(rb);
/* Try optimized path first */
if (read_fast_rgba_pixels( ctx, x, y, width, height,
format, type, pixels, packing )) {
if (fast_read_rgba_pixels(ctx, x, y, width, height,
format, type, pixels, packing)) {
return; /* done! */
}
@@ -301,9 +308,8 @@ read_rgba_pixels( GLcontext *ctx,
/* read full RGBA, FLOAT image */
dest = tmpImage;
for (row = 0; row < height; row++, y++) {
GLchan rgba[MAX_WIDTH][4];
if (fb->Visual.rgbMode) {
_swrast_read_rgba_span(ctx, rb, width, x, y, rgba);
_swrast_read_rgba_span(ctx, rb, width, x, y, GL_FLOAT, dest);
}
else {
GLuint index[MAX_WIDTH];
@@ -312,11 +318,11 @@ read_rgba_pixels( GLcontext *ctx,
if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset !=0 ) {
_mesa_map_ci(ctx, width, index);
}
_mesa_map_ci_to_rgba_chan(ctx, width, index, rgba);
_mesa_map_ci_to_rgba(ctx, width, index, (GLfloat (*)[4]) dest);
}
_mesa_pack_rgba_span_chan(ctx, width, (const GLchan (*)[4]) rgba,
GL_RGBA, GL_FLOAT, dest, &ctx->DefaultPacking,
transferOps & IMAGE_PRE_CONVOLUTION_BITS);
_mesa_apply_rgba_transfer_ops(ctx,
transferOps & IMAGE_PRE_CONVOLUTION_BITS,
width, (GLfloat (*)[4]) dest);
dest += width * 4;
}
@@ -346,24 +352,35 @@ read_rgba_pixels( GLcontext *ctx,
}
else {
/* no convolution */
const GLint dstStride
= _mesa_image_row_stride(packing, width, format, type);
GLfloat (*rgba)[4] = swrast->SpanArrays->color.sz4.rgba;
GLint row;
GLubyte *dst = _mesa_image_address2d(packing, pixels, width, height,
format, type, 0, 0);
for (row = 0; row < height; row++, y++) {
GLchan rgba[MAX_WIDTH][4];
GLvoid *dst;
/* Get float rgba pixels */
if (fb->Visual.rgbMode) {
_swrast_read_rgba_span(ctx, rb, width, x, y, rgba);
_swrast_read_rgba_span(ctx, rb, width, x, y, GL_FLOAT, rgba);
}
else {
/* read CI and convert to RGBA */
GLuint index[MAX_WIDTH];
ASSERT(rb->DataType == GL_UNSIGNED_INT);
rb->GetRow(ctx, rb, width, x, y, index);
if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) {
_mesa_map_ci(ctx, width, index);
}
_mesa_map_ci_to_rgba_chan(ctx, width, index, rgba);
_mesa_map_ci_to_rgba(ctx, width, index, rgba);
}
dst = _mesa_image_address2d(packing, pixels, width, height,
format, type, row, 0);
/* pack the row of RGBA pixels into user's buffer */
#if 0
/* XXX may need to rejuvinate this code if we get conformance
* falures on 16bpp displays (i.e. 5/6/5).
*/
if (fb->Visual.redBits < CHAN_BITS ||
fb->Visual.greenBits < CHAN_BITS ||
fb->Visual.blueBits < CHAN_BITS) {
@@ -379,12 +396,15 @@ read_rgba_pixels( GLcontext *ctx,
format, type, dst, packing,
ctx->_ImageTransferState);
}
else {
/* GLubytes are fine */
_mesa_pack_rgba_span_chan(ctx, width, (CONST GLchan (*)[4]) rgba,
format, type, dst, packing,
ctx->_ImageTransferState);
else
#endif
{
_mesa_pack_rgba_span_float(ctx, width, (CONST GLfloat (*)[4]) rgba,
format, type, dst,
packing, ctx->_ImageTransferState);
}
dst += dstStride;
}
}
}

View File

@@ -1560,14 +1560,16 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
}
/**
* Read RGBA pixels from frame buffer. Clipping will be done to prevent
* reading ouside the buffer's boundaries.
* \param type datatype for returned colors
* \param rgba the returned colors
*/
void
_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint n, GLint x, GLint y, GLchan rgba[][4] )
GLuint n, GLint x, GLint y, GLenum dstType,
GLvoid *rgba)
{
const GLint bufWidth = (GLint) rb->Width;
const GLint bufHeight = (GLint) rb->Height;
@@ -1609,8 +1611,18 @@ _swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
ASSERT(rb);
ASSERT(rb->GetRow);
ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
ASSERT(rb->DataType == CHAN_TYPE);
rb->GetRow(ctx, rb, length, x + skip, y, rgba + skip);
if (rb->DataType == dstType) {
rb->GetRow(ctx, rb, length, x + skip, y,
(GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
}
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);
}
}
}
@@ -1801,7 +1813,7 @@ void *
_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
SWspan *span)
{
GLuint pixelSize;
const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
void *rbPixels;
/*
@@ -1809,15 +1821,12 @@ _swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
* Point rbPixels to a temporary space (use specular color arrays).
*/
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
pixelSize = 4 * sizeof(GLubyte);
rbPixels = span->array->color.sz1.spec;
}
else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
pixelSize = 4 * sizeof(GLushort);
rbPixels = span->array->color.sz2.spec;
}
else {
pixelSize = 4 * sizeof(GLfloat);
rbPixels = span->array->color.sz4.spec;
}

View File

@@ -60,8 +60,8 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span);
extern void
_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint n, GLint x, GLint y, GLchan rgba[][4] );
_swrast_read_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint n, GLint x, GLint y, GLenum type, GLvoid *rgba);
extern void
_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,

View File

@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
* Version: 6.5.1
* Version: 6.5.2
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
@@ -52,33 +52,37 @@
#include "s_depth.h"
#include "s_span.h"
/*
/**
* Read an RGBA image from the frame buffer.
* This is used by glCopyTex[Sub]Image[12]D().
* Input: ctx - the context
* x, y - lower left corner
* width, height - size of region to read
* Return: pointer to block of GL_RGBA, GLchan data.
* \param x window source x
* \param y window source y
* \param width image width
* \param height image height
* \param type datatype for returned GL_RGBA image
* \return pointer to image
*/
static GLchan *
read_color_image( GLcontext *ctx, GLint x, GLint y,
static GLvoid *
read_color_image( GLcontext *ctx, GLint x, GLint y, GLenum type,
GLsizei width, GLsizei height )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLint stride = 4 * width;
GLint i;
GLchan *image, *dst;
struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
const GLint pixelSize = _mesa_bytes_per_pixel(GL_RGBA, type);
const GLint stride = width * pixelSize;
GLint row;
GLubyte *image, *dst;
image = (GLchan *) _mesa_malloc(width * height * 4 * sizeof(GLchan));
image = (GLubyte *) _mesa_malloc(width * height * pixelSize);
if (!image)
return NULL;
RENDER_START(swrast, ctx);
dst = image;
for (i = 0; i < height; i++) {
_swrast_read_rgba_span(ctx, ctx->ReadBuffer->_ColorReadBuffer,
width, x, y + i, (GLchan (*)[4]) dst);
for (row = 0; row < height; row++) {
_swrast_read_rgba_span(ctx, rb, width, x, y + row, type, dst);
dst += stride;
}
@@ -285,15 +289,16 @@ _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
}
else {
/* read RGBA image from framebuffer */
GLchan *image = read_color_image(ctx, x, y, width, 1);
const GLenum format = GL_RGBA;
const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
GLvoid *image = read_color_image(ctx, x, y, type, width, 1);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
return;
}
/* call glTexImage1D to redefine the texture */
ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
width, border,
GL_RGBA, CHAN_TYPE, image,
width, border, format, type, image,
&ctx->DefaultPacking, texObj, texImage);
_mesa_free(image);
}
@@ -360,15 +365,16 @@ _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
}
else {
/* read RGBA image from framebuffer */
GLchan *image = read_color_image(ctx, x, y, width, height);
const GLenum format = GL_RGBA;
const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
GLvoid *image = read_color_image(ctx, x, y, type, width, height);
if (!image) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
return;
}
/* call glTexImage2D to redefine the texture */
ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
width, height, border,
GL_RGBA, CHAN_TYPE, image,
width, height, border, format, type, image,
&ctx->DefaultPacking, texObj, texImage);
_mesa_free(image);
}
@@ -428,14 +434,16 @@ _swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level,
}
else {
/* read RGBA image from framebuffer */
GLchan *image = read_color_image(ctx, x, y, width, 1);
const GLenum format = GL_RGBA;
const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
GLvoid *image = read_color_image(ctx, x, y, type, width, 1);
if (!image) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
return;
}
/* now call glTexSubImage1D to do the real work */
ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
GL_RGBA, CHAN_TYPE, image,
format, type, image,
&ctx->DefaultPacking, texObj, texImage);
_mesa_free(image);
}
@@ -501,7 +509,9 @@ _swrast_copy_texsubimage2d( GLcontext *ctx,
}
else {
/* read RGBA image from framebuffer */
GLchan *image = read_color_image(ctx, x, y, width, height);
const GLenum format = GL_RGBA;
const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
GLvoid *image = read_color_image(ctx, x, y, type, width, height);
if (!image) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
return;
@@ -509,7 +519,7 @@ _swrast_copy_texsubimage2d( GLcontext *ctx,
/* now call glTexSubImage2D to do the real work */
ctx->Driver.TexSubImage2D(ctx, target, level,
xoffset, yoffset, width, height,
GL_RGBA, CHAN_TYPE, image,
format, type, image,
&ctx->DefaultPacking, texObj, texImage);
_mesa_free(image);
}
@@ -572,7 +582,9 @@ _swrast_copy_texsubimage3d( GLcontext *ctx,
}
else {
/* read RGBA image from framebuffer */
GLchan *image = read_color_image(ctx, x, y, width, height);
const GLenum format = GL_RGBA;
const GLenum type = ctx->ReadBuffer->_ColorReadBuffer->DataType;
GLvoid *image = read_color_image(ctx, x, y, type, width, height);
if (!image) {
_mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
return;
@@ -580,7 +592,7 @@ _swrast_copy_texsubimage3d( GLcontext *ctx,
/* now call glTexSubImage3D to do the real work */
ctx->Driver.TexSubImage3D(ctx, target, level,
xoffset, yoffset, zoffset, width, height, 1,
GL_RGBA, CHAN_TYPE, image,
format, type, image,
&ctx->DefaultPacking, texObj, texImage);
_mesa_free(image);
}