diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mesa/swrast/s_accum.c | 4 | ||||
| -rw-r--r-- | src/mesa/swrast/s_context.h | 10 | ||||
| -rw-r--r-- | src/mesa/swrast/s_copypix.c | 286 | ||||
| -rw-r--r-- | src/mesa/swrast/s_drawpix.c | 149 | ||||
| -rw-r--r-- | src/mesa/swrast/s_imaging.c | 8 | ||||
| -rw-r--r-- | src/mesa/swrast/s_readpix.c | 128 | ||||
| -rw-r--r-- | src/mesa/swrast/s_span.c | 25 | ||||
| -rw-r--r-- | src/mesa/swrast/s_span.h | 4 | ||||
| -rw-r--r-- | src/mesa/swrast/s_texstore.c | 66 | 
9 files changed, 369 insertions, 311 deletions
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 ); -      } -      else { -         copy_ci_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");        } -      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);     }  | 
