home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / swrast / s_copypix.cpp < prev    next >
C/C++ Source or Header  |  2002-12-06  |  27KB  |  829 lines

  1. /* $Id: s_copypix.c,v 1.43 2002/12/05 04:46:54 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. #include "glheader.h"
  29. #include "context.h"
  30. #include "convolve.h"
  31. #include "macros.h"
  32. #include "imports.h"
  33. #include "pixel.h"
  34.  
  35. #include "s_context.h"
  36. #include "s_depth.h"
  37. #include "s_histogram.h"
  38. #include "s_pixeltex.h"
  39. #include "s_span.h"
  40. #include "s_stencil.h"
  41. #include "s_texture.h"
  42. #include "s_zoom.h"
  43.  
  44.  
  45.  
  46. /*
  47.  * Determine if there's overlap in an image copy.
  48.  * This test also compensates for the fact that copies are done from
  49.  * bottom to top and overlaps can sometimes be handled correctly
  50.  * without making a temporary image copy.
  51.  */
  52. static GLboolean
  53. regions_overlap(GLint srcx, GLint srcy,
  54.                 GLint dstx, GLint dsty,
  55.                 GLint width, GLint height,
  56.                 GLfloat zoomX, GLfloat zoomY)
  57. {
  58.    if (zoomX == 1.0 && zoomY == 1.0) {
  59.       /* no zoom */
  60.       if (srcx >= dstx + width || (srcx + width <= dstx)) {
  61.          return GL_FALSE;
  62.       }
  63.       else if (srcy < dsty) { /* this is OK */
  64.          return GL_FALSE;
  65.       }
  66.       else if (srcy > dsty + height) {
  67.          return GL_FALSE;
  68.       }
  69.       else {
  70.          return GL_TRUE;
  71.       }
  72.    }
  73.    else {
  74.       /* add one pixel of slop when zooming, just to be safe */
  75.       if ((srcx > dstx + (width * zoomX) + 1) || (srcx + width + 1 < dstx)) {
  76.          return GL_FALSE;
  77.       }
  78.       else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) {
  79.          return GL_FALSE;
  80.       }
  81.       else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) {
  82.          return GL_FALSE;
  83.       }
  84.       else {
  85.          return GL_TRUE;
  86.       }
  87.    }
  88. }
  89.  
  90.  
  91.  
  92. /*
  93.  * RGBA copypixels with convolution.
  94.  */
  95. static void
  96. copy_conv_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
  97.                       GLint width, GLint height, GLint destx, GLint desty)
  98. {
  99.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  100.    GLboolean quick_draw;
  101.    GLint row;
  102.    GLboolean changeBuffer;
  103.    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
  104.    const GLuint transferOps = ctx->_ImageTransferState;
  105.    GLfloat *dest, *tmpImage, *convImage;
  106.    struct sw_span span;
  107.  
  108.    INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
  109.  
  110.    if (ctx->Depth.Test)
  111.       _mesa_span_default_z(ctx, &span);
  112.    if (ctx->Fog.Enabled)
  113.       _mesa_span_default_fog(ctx, &span);
  114.  
  115.  
  116.    if (SWRAST_CONTEXT(ctx)->_RasterMask == 0
  117.        && !zoom
  118.        && destx >= 0
  119.        && destx + width <= (GLint) ctx->DrawBuffer->Width) {
  120.       quick_draw = GL_TRUE;
  121.    }
  122.    else {
  123.       quick_draw = GL_FALSE;
  124.    }
  125.  
  126.    /* If read and draw buffer are different we must do buffer switching */
  127.    changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer
  128.                || ctx->DrawBuffer != ctx->ReadBuffer;
  129.  
  130.  
  131.    /* allocate space for GLfloat image */
  132.    tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
  133.    if (!tmpImage) {
  134.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
  135.       return;
  136.    }
  137.    convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
  138.    if (!convImage) {
  139.       FREE(tmpImage);
  140.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
  141.       return;
  142.    }
  143.  
  144.    dest = tmpImage;
  145.  
  146.    if (changeBuffer) {
  147.       /* choose the read buffer */
  148.       _swrast_use_read_buffer(ctx);
  149.    }
  150.  
  151.    /* read source image */
  152.    dest = tmpImage;
  153.    for (row = 0; row < height; row++) {
  154.       GLchan rgba[MAX_WIDTH][4];
  155.       GLint i;
  156.       _mesa_read_rgba_span(ctx, ctx->ReadBuffer, width, srcx, srcy + row, rgba);
  157.       /* convert GLchan to GLfloat */
  158.       for (i = 0; i < width; i++) {
  159.          *dest++ = (GLfloat) rgba[i][RCOMP] * (1.0F / CHAN_MAXF);
  160.          *dest++ = (GLfloat) rgba[i][GCOMP] * (1.0F / CHAN_MAXF);
  161.          *dest++ = (GLfloat) rgba[i][BCOMP] * (1.0F / CHAN_MAXF);
  162.          *dest++ = (GLfloat) rgba[i][ACOMP] * (1.0F / CHAN_MAXF);
  163.       }
  164.    }
  165.  
  166.    if (changeBuffer) {
  167.       /* restore default src/dst buffer */
  168.       _swrast_use_draw_buffer(ctx);
  169.    }
  170.  
  171.    /* do image transfer ops up until convolution */
  172.    for (row = 0; row < height; row++) {
  173.       GLfloat (*rgba)[4] = (GLfloat (*)[4]) (tmpImage + row * width * 4);
  174.  
  175.       /* scale & bias */
  176.       if (transferOps & IMAGE_SCALE_BIAS_BIT) {
  177.          _mesa_scale_and_bias_rgba(ctx, width, rgba,
  178.                                    ctx->Pixel.RedScale, ctx->Pixel.GreenScale,
  179.                                    ctx->Pixel.BlueScale, ctx->Pixel.AlphaScale,
  180.                                    ctx->Pixel.RedBias, ctx->Pixel.GreenBias,
  181.                                    ctx->Pixel.BlueBias, ctx->Pixel.AlphaBias);
  182.       }
  183.       /* color map lookup */
  184.       if (transferOps & IMAGE_MAP_COLOR_BIT) {
  185.          _mesa_map_rgba(ctx, width, rgba);
  186.       }
  187.       /* GL_COLOR_TABLE lookup */
  188.       if (transferOps & IMAGE_COLOR_TABLE_BIT) {
  189.          _mesa_lookup_rgba(&ctx->ColorTable, width, rgba);
  190.       }
  191.    }
  192.  
  193.    /* do convolution */
  194.    if (ctx->Pixel.Convolution2DEnabled) {
  195.       _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
  196.    }
  197.    else {
  198.       ASSERT(ctx->Pixel.Separable2DEnabled);
  199.       _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
  200.    }
  201.    FREE(tmpImage);
  202.  
  203.    /* do remaining image transfer ops */
  204.    for (row = 0; row < height; row++) {
  205.       GLfloat (*rgba)[4] = (GLfloat (*)[4]) (convImage + row * width * 4);
  206.  
  207.       /* GL_POST_CONVOLUTION_COLOR_TABLE lookup */
  208.       if (transferOps & IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT) {
  209.          _mesa_lookup_rgba(&ctx->PostConvolutionColorTable, width, rgba);
  210.       }
  211.       /* color matrix */
  212.       if (transferOps & IMAGE_COLOR_MATRIX_BIT) {
  213.          _mesa_transform_rgba(ctx, width, rgba);
  214.       }
  215.       /* GL_POST_COLOR_MATRIX_COLOR_TABLE lookup */
  216.       if (transferOps & IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT) {
  217.          _mesa_lookup_rgba(&ctx->PostColorMatrixColorTable, width, rgba);
  218.       }
  219.       /* update histogram count */
  220.       if (transferOps & IMAGE_HISTOGRAM_BIT) {
  221.          _mesa_update_histogram(ctx, width, (CONST GLfloat (*)[4]) rgba);
  222.       }
  223.       /* update min/max */
  224.       if (transferOps & IMAGE_MIN_MAX_BIT) {
  225.          _mesa_update_minmax(ctx, width, (CONST GLfloat (*)[4]) rgba);
  226.       }
  227.    }
  228.  
  229.    for (row = 0; row < height; row++) {
  230.       const GLfloat *src = convImage + row * width * 4;
  231.       GLint i, dy;
  232.  
  233.       /* clamp to [0,1] and convert float back to chan */
  234.       for (i = 0; i < width; i++) {
  235.          GLint r = (GLint) (src[i * 4 + RCOMP] * CHAN_MAXF);
  236.          GLint g = (GLint) (src[i * 4 + GCOMP] * CHAN_MAXF);
  237.          GLint b = (GLint) (src[i * 4 + BCOMP] * CHAN_MAXF);
  238.          GLint a = (GLint) (src[i * 4 + ACOMP] * CHAN_MAXF);
  239.          span.array->rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
  240.          span.array->rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
  241.          span.array->rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
  242.          span.array->rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
  243.       }
  244.  
  245.       if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) {
  246.          span.end = width;
  247.          _swrast_pixel_texture(ctx, &span);
  248.       }
  249.  
  250.       /* write row to framebuffer */
  251.  
  252.       dy = desty + row;
  253.       if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) {
  254.          (*swrast->Driver.WriteRGBASpan)( ctx, width, destx, dy,
  255.                (const GLchan (*)[4])span.array->rgba, NULL );
  256.       }
  257.       else if (zoom) {
  258.          span.x = destx;
  259.          span.y = dy;
  260.          span.end = width;
  261.          _mesa_write_zoomed_rgba_span(ctx, &span, 
  262.                                      (CONST GLchan (*)[4])span.array->rgba,
  263.                                      desty, 0);
  264.       }
  265.       else {
  266.          span.x = destx;
  267.          span.y = dy;
  268.          span.end = width;
  269.          _mesa_write_rgba_span(ctx, &span);
  270.       }
  271.    }
  272.  
  273.    FREE(convImage);
  274. }
  275.  
  276.  
  277. /*
  278.  * RGBA copypixels
  279.  */
  280. static void
  281. copy_rgba_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
  282.                  GLint width, GLint height, GLint destx, GLint desty)
  283. {
  284.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  285.    GLchan *tmpImage,*p;
  286.    GLboolean quick_draw;
  287.    GLint sy, dy, stepy, j;
  288.    GLboolean changeBuffer;
  289.    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
  290.    GLint overlapping;
  291.    const GLuint transferOps = ctx->_ImageTransferState;
  292.    struct sw_span span;
  293.  
  294.    INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
  295.  
  296.    if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
  297.       copy_conv_rgba_pixels(ctx, srcx, srcy, width, height, destx, desty);
  298.       return;
  299.    }
  300.  
  301.    /* Determine if copy should be done bottom-to-top or top-to-bottom */
  302.    if (srcy < desty) {
  303.       /* top-down  max-to-min */
  304.       sy = srcy + height - 1;
  305.       dy = desty + height - 1;
  306.       stepy = -1;
  307.    }
  308.    else {
  309.       /* bottom-up  min-to-max */
  310.       sy = srcy;
  311.       dy = desty;
  312.       stepy = 1;
  313.    }
  314.  
  315.    overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
  316.                                  ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
  317.  
  318.    if (ctx->Depth.Test)
  319.       _mesa_span_default_z(ctx, &span);
  320.    if (ctx->Fog.Enabled)
  321.       _mesa_span_default_fog(ctx, &span);
  322.  
  323.    if (SWRAST_CONTEXT(ctx)->_RasterMask == 0
  324.        && !zoom
  325.        && destx >= 0
  326.        && destx + width <= (GLint) ctx->DrawBuffer->Width) {
  327.       quick_draw = GL_TRUE;
  328.    }
  329.    else {
  330.       quick_draw = GL_FALSE;
  331.    }
  332.  
  333.    /* If read and draw buffer are different we must do buffer switching */
  334.    changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer
  335.                   || ctx->DrawBuffer != ctx->ReadBuffer;
  336.  
  337.    if (overlapping) {
  338.       GLint ssy = sy;
  339.       tmpImage = (GLchan *) MALLOC(width * height * sizeof(GLchan) * 4);
  340.       if (!tmpImage) {
  341.          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
  342.          return;
  343.       }
  344.       /* setup source */
  345.       if (changeBuffer)
  346.          _swrast_use_read_buffer(ctx);
  347.       /* read the source image */
  348.       p = tmpImage;
  349.       for (j = 0; j < height; j++, ssy += stepy) {
  350.          _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, ssy,
  351.                             (GLchan (*)[4]) p );
  352.          p += width * 4;
  353.       }
  354.       p = tmpImage;
  355.       /* restore dest */
  356.       if (changeBuffer) {
  357.          _swrast_use_draw_buffer(ctx);
  358.          changeBuffer = GL_FALSE;
  359.       }
  360.    }
  361.    else {
  362.       tmpImage = NULL;  /* silence compiler warnings */
  363.       p = NULL;
  364.    }
  365.  
  366.    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
  367.       /* Get source pixels */
  368.       if (overlapping) {
  369.          /* get from buffered image */
  370.          ASSERT(width < MAX_WIDTH);
  371.          MEMCPY(span.array->rgba, p, width * sizeof(GLchan) * 4);
  372.          p += width * 4;
  373.       }
  374.       else {
  375.          /* get from framebuffer */
  376.          if (changeBuffer)
  377.             _swrast_use_read_buffer(ctx);
  378.          ASSERT(width < MAX_WIDTH);
  379.          _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, sy,
  380.                                span.array->rgba );
  381.          if (changeBuffer)
  382.             _swrast_use_draw_buffer(ctx);
  383.       }
  384.  
  385.       if (transferOps) {
  386.          const GLfloat scale = (1.0F / CHAN_MAXF);
  387.          GLint k;
  388.          DEFMARRAY(GLfloat, rgbaFloat, MAX_WIDTH, 4);  /* mac 32k limitation */
  389.          CHECKARRAY(rgbaFloat, return);
  390.  
  391.          /* convert chan to float */
  392.          for (k = 0; k < width; k++) {
  393.             rgbaFloat[k][RCOMP] = (GLfloat) span.array->rgba[k][RCOMP] * scale;
  394.             rgbaFloat[k][GCOMP] = (GLfloat) span.array->rgba[k][GCOMP] * scale;
  395.             rgbaFloat[k][BCOMP] = (GLfloat) span.array->rgba[k][BCOMP] * scale;
  396.             rgbaFloat[k][ACOMP] = (GLfloat) span.array->rgba[k][ACOMP] * scale;
  397.          }
  398.          /* scale & bias */
  399.          if (transferOps & IMAGE_SCALE_BIAS_BIT) {
  400.             _mesa_scale_and_bias_rgba(ctx, width, rgbaFloat,
  401.                                    ctx->Pixel.RedScale, ctx->Pixel.GreenScale,
  402.                                    ctx->Pixel.BlueScale, ctx->Pixel.AlphaScale,
  403.                                    ctx->Pixel.RedBias, ctx->Pixel.GreenBias,
  404.                                    ctx->Pixel.BlueBias, ctx->Pixel.AlphaBias);
  405.          }
  406.          /* color map lookup */
  407.          if (transferOps & IMAGE_MAP_COLOR_BIT) {
  408.             _mesa_map_rgba(ctx, width, rgbaFloat);
  409.          }
  410.          /* GL_COLOR_TABLE lookup */
  411.          if (transferOps & IMAGE_COLOR_TABLE_BIT) {
  412.             _mesa_lookup_rgba(&ctx->ColorTable, width, rgbaFloat);
  413.          }
  414.          /* convolution */
  415.          if (transferOps & IMAGE_CONVOLUTION_BIT) {
  416.             _mesa_problem(ctx, "Convolution should not be enabled in copy_rgba_pixels()");
  417.             return;
  418.          }
  419.          /* GL_POST_CONVOLUTION_RED/GREEN/BLUE/ALPHA_SCALE/BIAS */
  420.          if (transferOps & IMAGE_POST_CONVOLUTION_SCALE_BIAS) {
  421.             _mesa_scale_and_bias_rgba(ctx, width, rgbaFloat,
  422.                                       ctx->Pixel.PostConvolutionScale[RCOMP],
  423.                                       ctx->Pixel.PostConvolutionScale[GCOMP],
  424.                                       ctx->Pixel.PostConvolutionScale[BCOMP],
  425.                                       ctx->Pixel.PostConvolutionScale[ACOMP],
  426.                                       ctx->Pixel.PostConvolutionBias[RCOMP],
  427.                                       ctx->Pixel.PostConvolutionBias[GCOMP],
  428.                                       ctx->Pixel.PostConvolutionBias[BCOMP],
  429.                                       ctx->Pixel.PostConvolutionBias[ACOMP]);
  430.          }
  431.          /* GL_POST_CONVOLUTION_COLOR_TABLE lookup */
  432.          if (transferOps & IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT) {
  433.             _mesa_lookup_rgba(&ctx->PostConvolutionColorTable, width, rgbaFloat);
  434.          }
  435.          /* color matrix */
  436.          if (transferOps & IMAGE_COLOR_MATRIX_BIT) {
  437.             _mesa_transform_rgba(ctx, width, rgbaFloat);
  438.          }
  439.          /* GL_POST_COLOR_MATRIX_COLOR_TABLE lookup */
  440.          if (transferOps & IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT) {
  441.             _mesa_lookup_rgba(&ctx->PostColorMatrixColorTable, width, rgbaFloat);
  442.          }
  443.          /* update histogram count */
  444.          if (transferOps & IMAGE_HISTOGRAM_BIT) {
  445.             _mesa_update_histogram(ctx, width, (CONST GLfloat (*)[4]) rgbaFloat);
  446.          }
  447.          /* update min/max */
  448.          if (transferOps & IMAGE_MIN_MAX_BIT) {
  449.             _mesa_update_minmax(ctx, width, (CONST GLfloat (*)[4]) rgbaFloat);
  450.          }
  451.          /* clamp to [0,1] and convert float back to chan */
  452.          for (k = 0; k < width; k++) {
  453.             GLint r = (GLint) (rgbaFloat[k][RCOMP] * CHAN_MAXF);
  454.             GLint g = (GLint) (rgbaFloat[k][GCOMP] * CHAN_MAXF);
  455.             GLint b = (GLint) (rgbaFloat[k][BCOMP] * CHAN_MAXF);
  456.             GLint a = (GLint) (rgbaFloat[k][ACOMP] * CHAN_MAXF);
  457.             span.array->rgba[k][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
  458.             span.array->rgba[k][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
  459.             span.array->rgba[k][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
  460.             span.array->rgba[k][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
  461.          }
  462.          UNDEFARRAY(rgbaFloat);  /* mac 32k limitation */
  463.       }
  464.  
  465.       if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) {
  466.          span.end = width;
  467.          _swrast_pixel_texture(ctx, &span);
  468.       }
  469.  
  470.       /* Write color span */
  471.       if (quick_draw && dy >= 0 && dy < (GLint) ctx->DrawBuffer->Height) {
  472.          (*swrast->Driver.WriteRGBASpan)( ctx, width, destx, dy,
  473.                                  (const GLchan (*)[4])span.array->rgba, NULL );
  474.       }
  475.       else if (zoom) {
  476.          span.x = destx;
  477.          span.y = dy;
  478.          span.end = width;
  479.          _mesa_write_zoomed_rgba_span(ctx, &span,
  480.                                      (CONST GLchan (*)[4]) span.array->rgba,
  481.                                      desty, 0);
  482.       }
  483.       else {
  484.          span.x = destx;
  485.          span.y = dy;
  486.          span.end = width;
  487.          _mesa_write_rgba_span(ctx, &span);
  488.       }
  489.    }
  490.  
  491.    if (overlapping)
  492.       FREE(tmpImage);
  493. }
  494.  
  495.  
  496. static void
  497. copy_ci_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
  498.                 GLint width, GLint height,
  499.                 GLint destx, GLint desty )
  500. {
  501.    GLuint *tmpImage,*p;
  502.    GLint sy, dy, stepy;
  503.    GLint j;
  504.    GLboolean changeBuffer;
  505.    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
  506.    const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
  507.    GLint overlapping;
  508.    struct sw_span span;
  509.  
  510.    INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_INDEX);
  511.  
  512.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  513.    if (srcy<desty) {
  514.       /* top-down  max-to-min */
  515.       sy = srcy + height - 1;
  516.       dy = desty + height - 1;
  517.       stepy = -1;
  518.    }
  519.    else {
  520.       /* bottom-up  min-to-max */
  521.       sy = srcy;
  522.       dy = desty;
  523.       stepy = 1;
  524.    }
  525.  
  526.    overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
  527.                                  ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
  528.  
  529.    if (ctx->Depth.Test)
  530.       _mesa_span_default_z(ctx, &span);
  531.    if (ctx->Fog.Enabled)
  532.       _mesa_span_default_fog(ctx, &span);
  533.  
  534.    /* If read and draw buffer are different we must do buffer switching */
  535.    changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer
  536.                || ctx->DrawBuffer != ctx->ReadBuffer;
  537.  
  538.    if (overlapping) {
  539.       GLint ssy = sy;
  540.       tmpImage = (GLuint *) MALLOC(width * height * sizeof(GLuint));
  541.       if (!tmpImage) {
  542.          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
  543.          return;
  544.       }
  545.       /* setup source */
  546.       if (changeBuffer)
  547.          _swrast_use_read_buffer(ctx);
  548.       /* read the image */
  549.       p = tmpImage;
  550.       for (j = 0; j < height; j++, ssy += stepy) {
  551.          _mesa_read_index_span( ctx, ctx->ReadBuffer, width, srcx, ssy, p );
  552.          p += width;
  553.       }
  554.       p = tmpImage;
  555.       /* restore to draw buffer */
  556.       if (changeBuffer) {
  557.          _swrast_use_draw_buffer(ctx);
  558.          changeBuffer = GL_FALSE;
  559.       }
  560.    }
  561.    else {
  562.       tmpImage = NULL;  /* silence compiler warning */
  563.       p = NULL;
  564.    }
  565.  
  566.    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
  567.       /* Get color indexes */
  568.       if (overlapping) {
  569.          MEMCPY(span.array->index, p, width * sizeof(GLuint));
  570.          p += width;
  571.       }
  572.       else {
  573.          if (changeBuffer)
  574.             _swrast_use_read_buffer(ctx);
  575.          _mesa_read_index_span( ctx, ctx->ReadBuffer, width, srcx, sy,
  576.                                 span.array->index );
  577.          if (changeBuffer)
  578.             _swrast_use_draw_buffer(ctx);
  579.       }
  580.  
  581.       /* Apply shift, offset, look-up table */
  582.       if (shift_or_offset) {
  583.          _mesa_shift_and_offset_ci( ctx, width, span.array->index );
  584.       }
  585.       if (ctx->Pixel.MapColorFlag) {
  586.          _mesa_map_ci( ctx, width, span.array->index );
  587.       }
  588.  
  589.       /* write color indexes */
  590.       span.x = destx;
  591.       span.y = dy;
  592.       span.end = width;
  593.       if (zoom)
  594.          _mesa_write_zoomed_index_span(ctx, &span, desty, 0);
  595.       else
  596.          _mesa_write_index_span(ctx, &span);
  597.    }
  598.  
  599.    if (overlapping)
  600.       FREE(tmpImage);
  601. }
  602.  
  603.  
  604.  
  605. /*
  606.  * TODO: Optimize!!!!
  607.  */
  608. static void
  609. copy_depth_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
  610.                    GLint width, GLint height,
  611.                    GLint destx, GLint desty )
  612. {
  613.    GLfloat *p, *tmpImage;
  614.    GLint sy, dy, stepy;
  615.    GLint i, j;
  616.    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
  617.    GLint overlapping;
  618.    struct sw_span span;
  619.  
  620.    INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_Z);
  621.  
  622.    if (!ctx->Visual.depthBits) {
  623.       _mesa_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  624.       return;
  625.    }
  626.  
  627.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  628.    if (srcy<desty) {
  629.       /* top-down  max-to-min */
  630.       sy = srcy + height - 1;
  631.       dy = desty + height - 1;
  632.       stepy = -1;
  633.    }
  634.    else {
  635.       /* bottom-up  min-to-max */
  636.       sy = srcy;
  637.       dy = desty;
  638.       stepy = 1;
  639.    }
  640.  
  641.    overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
  642.                                  ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
  643.  
  644.    _mesa_span_default_color(ctx, &span);
  645.    if (ctx->Fog.Enabled)
  646.       _mesa_span_default_fog(ctx, &span);
  647.  
  648.    if (overlapping) {
  649.       GLint ssy = sy;
  650.       tmpImage = (GLfloat *) MALLOC(width * height * sizeof(GLfloat));
  651.       if (!tmpImage) {
  652.          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
  653.          return;
  654.       }
  655.       p = tmpImage;
  656.       for (j = 0; j < height; j++, ssy += stepy) {
  657.          _mesa_read_depth_span_float(ctx, width, srcx, ssy, p);
  658.          p += width;
  659.       }
  660.       p = tmpImage;
  661.    }
  662.    else {
  663.       tmpImage = NULL;  /* silence compiler warning */
  664.       p = NULL;
  665.    }
  666.  
  667.    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
  668.       GLfloat depth[MAX_WIDTH];
  669.  
  670.       /* get depth values */
  671.       if (overlapping) {
  672.          MEMCPY(depth, p, width * sizeof(GLfloat));
  673.          p += width;
  674.       }
  675.       else {
  676.          _mesa_read_depth_span_float(ctx, width, srcx, sy, depth);
  677.       }
  678.  
  679.       /* apply scale and bias */
  680.       for (i = 0; i < width; i++) {
  681.          GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
  682.          span.array->z[i] = (GLdepth) (CLAMP(d, 0.0F, 1.0F) * ctx->DepthMax);
  683.       }
  684.  
  685.       /* write depth values */
  686.       span.x = destx;
  687.       span.y = dy;
  688.       span.end = width;
  689.       if (ctx->Visual.rgbMode) {
  690.          if (zoom)
  691.             _mesa_write_zoomed_rgba_span( ctx, &span, 
  692.                             (const GLchan (*)[4])span.array->rgba, desty, 0 );
  693.          else
  694.             _mesa_write_rgba_span(ctx, &span);
  695.       }
  696.       else {
  697.          if (zoom)
  698.             _mesa_write_zoomed_index_span( ctx, &span, desty, 0 );
  699.          else
  700.             _mesa_write_index_span(ctx, &span);
  701.       }
  702.    }
  703.  
  704.    if (overlapping)
  705.       FREE(tmpImage);
  706. }
  707.  
  708.  
  709.  
  710. static void
  711. copy_stencil_pixels( GLcontext *ctx, GLint srcx, GLint srcy,
  712.                      GLint width, GLint height,
  713.                      GLint destx, GLint desty )
  714. {
  715.    GLint sy, dy, stepy;
  716.    GLint j;
  717.    GLstencil *p, *tmpImage;
  718.    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
  719.    const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
  720.    GLint overlapping;
  721.  
  722.    if (!ctx->Visual.stencilBits) {
  723.       _mesa_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  724.       return;
  725.    }
  726.  
  727.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  728.    if (srcy < desty) {
  729.       /* top-down  max-to-min */
  730.       sy = srcy + height - 1;
  731.       dy = desty + height - 1;
  732.       stepy = -1;
  733.    }
  734.    else {
  735.       /* bottom-up  min-to-max */
  736.       sy = srcy;
  737.       dy = desty;
  738.       stepy = 1;
  739.    }
  740.  
  741.    overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
  742.                                  ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
  743.  
  744.    if (overlapping) {
  745.       GLint ssy = sy;
  746.       tmpImage = (GLstencil *) MALLOC(width * height * sizeof(GLstencil));
  747.       if (!tmpImage) {
  748.          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
  749.          return;
  750.       }
  751.       p = tmpImage;
  752.       for (j = 0; j < height; j++, ssy += stepy) {
  753.          _mesa_read_stencil_span( ctx, width, srcx, ssy, p );
  754.          p += width;
  755.       }
  756.       p = tmpImage;
  757.    }
  758.    else {
  759.       tmpImage = NULL;  /* silence compiler warning */
  760.       p = NULL;
  761.    }
  762.  
  763.    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
  764.       GLstencil stencil[MAX_WIDTH];
  765.  
  766.       /* Get stencil values */
  767.       if (overlapping) {
  768.          MEMCPY(stencil, p, width * sizeof(GLstencil));
  769.          p += width;
  770.       }
  771.       else {
  772.          _mesa_read_stencil_span( ctx, width, srcx, sy, stencil );
  773.       }
  774.  
  775.       /* Apply shift, offset, look-up table */
  776.       if (shift_or_offset) {
  777.          _mesa_shift_and_offset_stencil( ctx, width, stencil );
  778.       }
  779.       if (ctx->Pixel.MapStencilFlag) {
  780.          _mesa_map_stencil( ctx, width, stencil );
  781.       }
  782.  
  783.       /* Write stencil values */
  784.       if (zoom) {
  785.          _mesa_write_zoomed_stencil_span( ctx, width, destx, dy,
  786.                                           stencil, desty, 0 );
  787.       }
  788.       else {
  789.          _mesa_write_stencil_span( ctx, width, destx, dy, stencil );
  790.       }
  791.    }
  792.  
  793.    if (overlapping)
  794.       FREE(tmpImage);
  795. }
  796.  
  797.  
  798.  
  799. void
  800. _swrast_CopyPixels( GLcontext *ctx,
  801.             GLint srcx, GLint srcy, GLsizei width, GLsizei height,
  802.             GLint destx, GLint desty,
  803.             GLenum type )
  804. {
  805.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  806.    RENDER_START(swrast,ctx);
  807.       
  808.    if (swrast->NewState)
  809.       _swrast_validate_derived( ctx );
  810.  
  811.    if (type == GL_COLOR && ctx->Visual.rgbMode) {
  812.       copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
  813.    }
  814.    else if (type == GL_COLOR && !ctx->Visual.rgbMode) {
  815.       copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
  816.    }
  817.    else if (type == GL_DEPTH) {
  818.       copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
  819.    }
  820.    else if (type == GL_STENCIL) {
  821.       copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
  822.    }
  823.    else {
  824.       _mesa_error( ctx, GL_INVALID_ENUM, "glCopyPixels" );
  825.    }
  826.  
  827.    RENDER_FINISH(swrast,ctx);
  828. }
  829.