R1/2/3/4/5xx: fixed calculation of cliprects in CopyBuffer.
[mesa.git] / src / mesa / swrast / s_copypix.c
index 7c1f3c887791c06d70889032a60014f7fee68c88..3962721a61cf12f032c00394821eac6d836dd94d 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.2
+ * Version:  7.1
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -71,13 +71,20 @@ regions_overlap(GLint srcx, GLint srcy,
    }
    else {
       /* add one pixel of slop when zooming, just to be safe */
-      if ((srcx > dstx + (width * zoomX) + 1) || (srcx + width + 1 < dstx)) {
+      if (srcx > (dstx + ((zoomX > 0.0F) ? (width * zoomX + 1.0F) : 0.0F))) {
+         /* src is completely right of dest */
+         return GL_FALSE;
+      }
+      else if (srcx + width + 1.0F < dstx + ((zoomX > 0.0F) ? 0.0F : (width * zoomX))) {
+         /* src is completely left of dest */
          return GL_FALSE;
       }
       else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) {
+         /* src is completely below dest */
          return GL_FALSE;
       }
       else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) {
+         /* src is completely above dest */
          return GL_FALSE;
       }
       else {
@@ -94,22 +101,18 @@ static void
 copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
                       GLint width, GLint height, GLint destx, GLint desty)
 {
-   SWcontext *swrast = SWRAST_CONTEXT(ctx);
    GLint row;
    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
-   const GLuint transferOps = ctx->_ImageTransferState;
+   const GLbitfield transferOps = ctx->_ImageTransferState;
    const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink)
       || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink);
    GLfloat *dest, *tmpImage, *convImage;
    SWspan span;
 
-   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);
-
+   INIT_SPAN(span, GL_BITMAP);
+   _swrast_span_default_attribs(ctx, &span);
+   span.arrayMask = SPAN_RGBA;
+   span.arrayAttribs = FRAG_BIT_COL0;
 
    /* allocate space for GLfloat image */
    tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
@@ -162,7 +165,7 @@ copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
       /* 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 */
+         GLfloat *rgba = (GLfloat *) span.array->attribs[FRAG_ATTRIB_COL0];
 
          /* copy convolved colors into span array */
          _mesa_memcpy(rgba, src, width * 4 * sizeof(GLfloat));
@@ -194,12 +197,11 @@ static void
 copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
                  GLint width, GLint height, GLint destx, GLint desty)
 {
-   SWcontext *swrast = SWRAST_CONTEXT(ctx);
    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;
+   GLuint transferOps = ctx->_ImageTransferState;
    SWspan span;
 
    if (!ctx->ReadBuffer->_ColorReadBuffer) {
@@ -211,9 +213,22 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
       copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty);
       return;
    }
+   else if (ctx->Pixel.Convolution1DEnabled) {
+      /* make sure we don't apply 1D convolution */
+      transferOps &= ~(IMAGE_CONVOLUTION_BIT |
+                       IMAGE_POST_CONVOLUTION_SCALE_BIAS);
+   }
+
+   if (ctx->DrawBuffer == ctx->ReadBuffer) {
+      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
+                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+   }
+   else {
+      overlapping = GL_FALSE;
+   }
 
    /* Determine if copy should be done bottom-to-top or top-to-bottom */
-   if (srcy < desty) {
+   if (!overlapping && srcy < desty) {
       /* top-down  max-to-min */
       sy = srcy + height - 1;
       dy = desty + height - 1;
@@ -226,19 +241,10 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
       stepy = 1;
    }
 
-   if (ctx->DrawBuffer == ctx->ReadBuffer) {
-      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
-                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
-   }
-   else {
-      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);
+   INIT_SPAN(span, GL_BITMAP);
+   _swrast_span_default_attribs(ctx, &span);
+   span.arrayMask = SPAN_RGBA;
+   span.arrayAttribs = FRAG_BIT_COL0; /* we'll fill in COL0 attrib values */
 
    if (overlapping) {
       tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat) * 4);
@@ -263,7 +269,7 @@ copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
    ASSERT(width < MAX_WIDTH);
 
    for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
-      GLvoid *rgba = span.array->color.sz4.rgba;
+      GLvoid *rgba = span.array->attribs[FRAG_ATTRIB_COL0];
 
       /* Get row/span of source pixels */
       if (overlapping) {
@@ -307,12 +313,10 @@ copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
                 GLint width, GLint height,
                 GLint destx, GLint desty )
 {
-   SWcontext *swrast = SWRAST_CONTEXT(ctx);
    GLuint *tmpImage,*p;
    GLint sy, dy, stepy;
    GLint j;
    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
-   const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
    GLint overlapping;
    SWspan span;
 
@@ -321,10 +325,20 @@ copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
       return;
    }
 
-   INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_INDEX);
+   INIT_SPAN(span, GL_BITMAP);
+   _swrast_span_default_attribs(ctx, &span);
+   span.arrayMask = SPAN_INDEX;
+
+   if (ctx->DrawBuffer == ctx->ReadBuffer) {
+      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
+                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+   }
+   else {
+      overlapping = GL_FALSE;
+   }
 
    /* Determine if copy should be bottom-to-top or top-to-bottom */
-   if (srcy<desty) {
+   if (!overlapping && srcy < desty) {
       /* top-down  max-to-min */
       sy = srcy + height - 1;
       dy = desty + height - 1;
@@ -337,19 +351,6 @@ copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
       stepy = 1;
    }
 
-   if (ctx->DrawBuffer == ctx->ReadBuffer) {
-      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
-                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
-   }
-   else {
-      overlapping = GL_FALSE;
-   }
-
-   if (ctx->Depth.Test)
-      _swrast_span_default_z(ctx, &span);
-   if (swrast->_FogEnabled)
-      _swrast_span_default_fog(ctx, &span);
-
    if (overlapping) {
       GLint ssy = sy;
       tmpImage = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint));
@@ -382,13 +383,9 @@ copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
                                   width, srcx, sy, span.array->index );
       }
 
-      /* Apply shift, offset, look-up table */
-      if (shift_or_offset) {
-         _mesa_shift_and_offset_ci( ctx, width, span.array->index );
-      }
-      if (ctx->Pixel.MapColorFlag) {
-         _mesa_map_ci( ctx, width, span.array->index );
-      }
+      if (ctx->_ImageTransferState)
+         _mesa_apply_ci_transfer_ops(ctx, ctx->_ImageTransferState,
+                                     width, span.array->index);
 
       /* write color indexes */
       span.x = destx;
@@ -449,7 +446,6 @@ copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
                    GLint width, GLint height,
                    GLint destx, GLint desty )
 {
-   SWcontext *swrast = SWRAST_CONTEXT(ctx);
    struct gl_framebuffer *fb = ctx->ReadBuffer;
    struct gl_renderbuffer *readRb = fb->_DepthBuffer;
    GLfloat *p, *tmpImage;
@@ -464,10 +460,20 @@ copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
       return;
    }
 
-   INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_Z);
+   INIT_SPAN(span, GL_BITMAP);
+   _swrast_span_default_attribs(ctx, &span);
+   span.arrayMask = SPAN_Z;
+
+   if (ctx->DrawBuffer == ctx->ReadBuffer) {
+      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
+                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+   }
+   else {
+      overlapping = GL_FALSE;
+   }
 
    /* Determine if copy should be bottom-to-top or top-to-bottom */
-   if (srcy<desty) {
+   if (!overlapping && srcy < desty) {
       /* top-down  max-to-min */
       sy = srcy + height - 1;
       dy = desty + height - 1;
@@ -480,18 +486,6 @@ copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
       stepy = 1;
    }
 
-   if (ctx->DrawBuffer == ctx->ReadBuffer) {
-      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
-                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
-   }
-   else {
-      overlapping = GL_FALSE;
-   }
-
-   _swrast_span_default_color(ctx, &span);
-   if (swrast->_FogEnabled)
-      _swrast_span_default_fog(ctx, &span);
-
    if (overlapping) {
       GLint ssy = sy;
       tmpImage = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat));
@@ -531,14 +525,13 @@ copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
       span.end = width;
       if (fb->Visual.rgbMode) {
          if (zoom)
-            _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, 
-                                           span.array->rgba);
+            _swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
          else
             _swrast_write_rgba_span(ctx, &span);
       }
       else {
          if (zoom)
-            _swrast_write_zoomed_index_span(ctx, destx, desty, &span);
+            _swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
          else
             _swrast_write_index_span(ctx, &span);
       }
@@ -561,7 +554,6 @@ copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
    GLint j;
    GLstencil *p, *tmpImage;
    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
-   const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
    GLint overlapping;
 
    if (!rb) {
@@ -569,8 +561,16 @@ copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
       return;
    }
 
+   if (ctx->DrawBuffer == ctx->ReadBuffer) {
+      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
+                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+   }
+   else {
+      overlapping = GL_FALSE;
+   }
+
    /* Determine if copy should be bottom-to-top or top-to-bottom */
-   if (srcy < desty) {
+   if (!overlapping && srcy < desty) {
       /* top-down  max-to-min */
       sy = srcy + height - 1;
       dy = desty + height - 1;
@@ -583,14 +583,6 @@ copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
       stepy = 1;
    }
 
-   if (ctx->DrawBuffer == ctx->ReadBuffer) {
-      overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
-                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
-   }
-   else {
-      overlapping = GL_FALSE;
-   }
-
    if (overlapping) {
       GLint ssy = sy;
       tmpImage = (GLstencil *) _mesa_malloc(width * height * sizeof(GLstencil));
@@ -622,13 +614,7 @@ copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
          _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
       }
 
-      /* Apply shift, offset, look-up table */
-      if (shift_or_offset) {
-         _mesa_shift_and_offset_stencil( ctx, width, stencil );
-      }
-      if (ctx->Pixel.MapStencilFlag) {
-         _mesa_map_stencil( ctx, width, stencil );
-      }
+      _mesa_apply_stencil_transfer_ops(ctx, width, stencil);
 
       /* Write stencil values */
       if (zoom) {
@@ -664,8 +650,6 @@ copy_depth_stencil_pixels(GLcontext *ctx,
    const GLfloat depthScale = ctx->DrawBuffer->_DepthMaxF;
    const GLuint stencilMask = ctx->Stencil.WriteMask[0];
    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
-   const GLboolean shiftOrOffset
-      = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
    const GLboolean scaleOrBias
       = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
    GLint overlapping;
@@ -678,8 +662,16 @@ copy_depth_stencil_pixels(GLcontext *ctx,
    ASSERT(depthReadRb);
    ASSERT(stencilReadRb);
 
+   if (ctx->DrawBuffer == ctx->ReadBuffer) {
+      overlapping = regions_overlap(srcX, srcY, destX, destY, width, height,
+                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
+   }
+   else {
+      overlapping = GL_FALSE;
+   }
+
    /* Determine if copy should be bottom-to-top or top-to-bottom */
-   if (srcY < destY) {
+   if (!overlapping && srcY < destY) {
       /* top-down  max-to-min */
       sy = srcY + height - 1;
       dy = destY + height - 1;
@@ -692,14 +684,6 @@ copy_depth_stencil_pixels(GLcontext *ctx,
       stepy = 1;
    }
 
-   if (ctx->DrawBuffer == ctx->ReadBuffer) {
-      overlapping = regions_overlap(srcX, srcY, destX, destY, width, height,
-                                    ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
-   }
-   else {
-      overlapping = GL_FALSE;
-   }
-
    if (overlapping) {
       GLint ssy = sy;
 
@@ -755,13 +739,7 @@ copy_depth_stencil_pixels(GLcontext *ctx,
                                       width, srcX, sy, stencil);
          }
 
-         /* Apply shift, offset, look-up table */
-         if (shiftOrOffset) {
-            _mesa_shift_and_offset_stencil(ctx, width, stencil);
-         }
-         if (ctx->Pixel.MapStencilFlag) {
-            _mesa_map_stencil(ctx, width, stencil);
-         }
+         _mesa_apply_stencil_transfer_ops(ctx, width, stencil);
 
          /* Write values */
          if (zoom) {
@@ -852,10 +830,10 @@ fast_copy_pixels(GLcontext *ctx,
    }
 
    if (type == GL_COLOR) {
-      if (dstFb->_NumColorDrawBuffers[0] != 1)
+      if (dstFb->_NumColorDrawBuffers != 1)
          return GL_FALSE;
       srcRb = srcFb->_ColorReadBuffer;
-      dstRb = dstFb->_ColorDrawBuffers[0][0];
+      dstRb = dstFb->_ColorDrawBuffers[0];
    }
    else if (type == GL_STENCIL) {
       srcRb = srcFb->_StencilBuffer;
@@ -865,7 +843,8 @@ fast_copy_pixels(GLcontext *ctx,
       srcRb = srcFb->_DepthBuffer;
       dstRb = dstFb->_DepthBuffer;
    }
-   else if (type == GL_DEPTH_STENCIL_EXT) {
+   else {
+      ASSERT(type == GL_DEPTH_STENCIL_EXT);
       /* XXX correct? */
       srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
       dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
@@ -879,8 +858,8 @@ fast_copy_pixels(GLcontext *ctx,
    }
 
    /* clipping not supported */
-   if (srcX < 0 || srcX + width > srcFb->Width ||
-       srcY < 0 || srcY + height > srcFb->Width ||
+   if (srcX < 0 || srcX + width > (GLint) srcFb->Width ||
+       srcY < 0 || srcY + height > (GLint) srcFb->Height ||
        dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
        dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
       return GL_FALSE;