From 76e778dce59aa6f290db50242df945943fc47b05 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 12 Oct 2006 23:17:02 +0000 Subject: 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. --- src/mesa/swrast/s_accum.c | 4 +- src/mesa/swrast/s_context.h | 10 ++ src/mesa/swrast/s_copypix.c | 286 ++++++++++++++++++++++--------------------- src/mesa/swrast/s_drawpix.c | 149 +++++++++++----------- src/mesa/swrast/s_imaging.c | 8 +- src/mesa/swrast/s_readpix.c | 128 +++++++++++-------- src/mesa/swrast/s_span.c | 25 ++-- src/mesa/swrast/s_span.h | 4 +- src/mesa/swrast/s_texstore.c | 66 ++++++---- 9 files changed, 369 insertions(+), 311 deletions(-) (limited to 'src') diff --git a/src/mesa/swrast/s_accum.c b/src/mesa/swrast/s_accum.c index 64b6d6b84e..0b8ad00762 100644 --- a/src/mesa/swrast/s_accum.c +++ b/src/mesa/swrast/s_accum.c @@ -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) { diff --git a/src/mesa/swrast/s_context.h b/src/mesa/swrast/s_context.h index 6ccee5438e..37d7081d4d 100644 --- a/src/mesa/swrast/s_context.h +++ b/src/mesa/swrast/s_context.h @@ -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. diff --git a/src/mesa/swrast/s_copypix.c b/src/mesa/swrast/s_copypix.c index be794e38e2..7c1f3c8877 100644 --- a/src/mesa/swrast/s_copypix.c +++ b/src/mesa/swrast/s_copypix.c @@ -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); } - /* write the new image */ - for (row = 0; row < height; row++) { - const GLfloat *src = convImage + row * width * 4; - GLint dy; + if (!sink) { + /* write the new image */ + for (row = 0; row < height; row++) { + const GLfloat *src = convImage + row * width * 4; + 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,49 +260,43 @@ 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); + 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, rgba); } else { - span.x = destx; - span.y = dy; - span.end = width; - if (zoom) { - _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, - span.array->rgba); - } - else { - _swrast_write_rgba_span(ctx, &span); - } + _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,26 +925,28 @@ _swrast_CopyPixels( GLcontext *ctx, if (swrast->NewState) _swrast_validate_derived( ctx ); - switch (type) { - case GL_COLOR: - if (ctx->Visual.rgbMode) { - copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty ); + if (!fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) { + switch (type) { + case GL_COLOR: + if (ctx->Visual.rgbMode) { + copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty ); + } + else { + copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty ); + } + break; + case GL_DEPTH: + copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty ); + break; + case GL_STENCIL: + copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty ); + break; + case GL_DEPTH_STENCIL_EXT: + copy_depth_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty); + break; + default: + _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels"); } - else { - copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty ); - } - break; - case GL_DEPTH: - copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty ); - break; - case GL_STENCIL: - copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty ); - break; - case GL_DEPTH_STENCIL_EXT: - copy_depth_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty); - break; - default: - _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels"); } RENDER_FINISH(swrast,ctx); diff --git a/src/mesa/swrast/s_drawpix.c b/src/mesa/swrast/s_drawpix.c index 5be2934b40..46dd797023 100644 --- a/src/mesa/swrast/s_drawpix.c +++ b/src/mesa/swrast/s_drawpix.c @@ -40,16 +40,17 @@ #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, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const struct gl_pixelstore_attrib *userUnpack, - const GLvoid *pixels) +fast_draw_rgba_pixels(GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *userUnpack, + const GLvoid *pixels) { const GLint imgX = x, imgY = y; struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0]; @@ -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; - destY++; + 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. - */ - span.array->ChanType = CHAN_TYPE; - 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; - + /* 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 (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); - } - else { - _swrast_write_rgba_span(ctx, &span); + if (!sink) { + /* Set these for each row since the _swrast_write_* functions + * may change them while clipping/rendering. + */ + span.array->ChanType = GL_FLOAT; + span.x = x + skipPixels; + span.y = y + row; + span.end = spanWidth; + span.arrayMask = arrayMask; + span.interpMask = interpMask; + 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) { diff --git a/src/mesa/swrast/s_imaging.c b/src/mesa/swrast/s_imaging.c index ac69d270b8..73aaba1ec9 100644 --- a/src/mesa/swrast/s_imaging.c +++ b/src/mesa/swrast/s_imaging.c @@ -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); diff --git a/src/mesa/swrast/s_readpix.c b/src/mesa/swrast/s_readpix.c index a73bb81aac..334dc02918 100644 --- a/src/mesa/swrast/s_readpix.c +++ b/src/mesa/swrast/s_readpix.c @@ -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) - return GL_FALSE; - - /* can't do fancy pixel packing */ - if (packing->Alignment != 1 || packing->SwapBytes || packing->LsbFirst) + /* check for things we can't handle here */ + if (ctx->_ImageTransferState || + 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; } } } diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c index 4d0ccf5f1d..59a5361632 100644 --- a/src/mesa/swrast/s_span.c +++ b/src/mesa/swrast/s_span.c @@ -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; } diff --git a/src/mesa/swrast/s_span.h b/src/mesa/swrast/s_span.h index efc98f290c..c441106aba 100644 --- a/src/mesa/swrast/s_span.h +++ b/src/mesa/swrast/s_span.h @@ -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, diff --git a/src/mesa/swrast/s_texstore.c b/src/mesa/swrast/s_texstore.c index b018c5a4a6..ddaf7471f5 100644 --- a/src/mesa/swrast/s_texstore.c +++ b/src/mesa/swrast/s_texstore.c @@ -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); } -- cgit v1.2.3