Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.1
  4.  *
  5.  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25.  
  26. #include "main/glheader.h"
  27. #include "main/context.h"
  28. #include "main/colormac.h"
  29. #include "main/condrender.h"
  30. #include "main/macros.h"
  31. #include "main/pixeltransfer.h"
  32. #include "main/imports.h"
  33.  
  34. #include "s_context.h"
  35. #include "s_depth.h"
  36. #include "s_span.h"
  37. #include "s_stencil.h"
  38. #include "s_zoom.h"
  39.  
  40.  
  41.  
  42. /**
  43.  * Determine if there's overlap in an image copy.
  44.  * This test also compensates for the fact that copies are done from
  45.  * bottom to top and overlaps can sometimes be handled correctly
  46.  * without making a temporary image copy.
  47.  * \return GL_TRUE if the regions overlap, GL_FALSE otherwise.
  48.  */
  49. static GLboolean
  50. regions_overlap(GLint srcx, GLint srcy,
  51.                 GLint dstx, GLint dsty,
  52.                 GLint width, GLint height,
  53.                 GLfloat zoomX, GLfloat zoomY)
  54. {
  55.    if (zoomX == 1.0 && zoomY == 1.0) {
  56.       /* no zoom */
  57.       if (srcx >= dstx + width || (srcx + width <= dstx)) {
  58.          return GL_FALSE;
  59.       }
  60.       else if (srcy < dsty) { /* this is OK */
  61.          return GL_FALSE;
  62.       }
  63.       else if (srcy > dsty + height) {
  64.          return GL_FALSE;
  65.       }
  66.       else {
  67.          return GL_TRUE;
  68.       }
  69.    }
  70.    else {
  71.       /* add one pixel of slop when zooming, just to be safe */
  72.       if (srcx > (dstx + ((zoomX > 0.0F) ? (width * zoomX + 1.0F) : 0.0F))) {
  73.          /* src is completely right of dest */
  74.          return GL_FALSE;
  75.       }
  76.       else if (srcx + width + 1.0F < dstx + ((zoomX > 0.0F) ? 0.0F : (width * zoomX))) {
  77.          /* src is completely left of dest */
  78.          return GL_FALSE;
  79.       }
  80.       else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) {
  81.          /* src is completely below dest */
  82.          return GL_FALSE;
  83.       }
  84.       else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) {
  85.          /* src is completely above dest */
  86.          return GL_FALSE;
  87.       }
  88.       else {
  89.          return GL_TRUE;
  90.       }
  91.    }
  92. }
  93.  
  94.  
  95. /**
  96.  * RGBA copypixels
  97.  */
  98. static void
  99. copy_rgba_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
  100.                  GLint width, GLint height, GLint destx, GLint desty)
  101. {
  102.    GLfloat *tmpImage, *p;
  103.    GLint sy, dy, stepy, row;
  104.    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
  105.    GLint overlapping;
  106.    GLuint transferOps = ctx->_ImageTransferState;
  107.    SWspan span;
  108.  
  109.    if (!ctx->ReadBuffer->_ColorReadBuffer) {
  110.       /* no readbuffer - OK */
  111.       return;
  112.    }
  113.  
  114.    if (ctx->DrawBuffer == ctx->ReadBuffer) {
  115.       overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
  116.                                     ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
  117.    }
  118.    else {
  119.       overlapping = GL_FALSE;
  120.    }
  121.  
  122.    /* Determine if copy should be done bottom-to-top or top-to-bottom */
  123.    if (!overlapping && srcy < desty) {
  124.       /* top-down  max-to-min */
  125.       sy = srcy + height - 1;
  126.       dy = desty + height - 1;
  127.       stepy = -1;
  128.    }
  129.    else {
  130.       /* bottom-up  min-to-max */
  131.       sy = srcy;
  132.       dy = desty;
  133.       stepy = 1;
  134.    }
  135.  
  136.    INIT_SPAN(span, GL_BITMAP);
  137.    _swrast_span_default_attribs(ctx, &span);
  138.    span.arrayMask = SPAN_RGBA;
  139.    span.arrayAttribs = FRAG_BIT_COL0; /* we'll fill in COL0 attrib values */
  140.  
  141.    if (overlapping) {
  142.       tmpImage = (GLfloat *) malloc(width * height * sizeof(GLfloat) * 4);
  143.       if (!tmpImage) {
  144.          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
  145.          return;
  146.       }
  147.       /* read the source image as RGBA/float */
  148.       p = tmpImage;
  149.       for (row = 0; row < height; row++) {
  150.          _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
  151.                                  width, srcx, sy + row, GL_FLOAT, p );
  152.          p += width * 4;
  153.       }
  154.       p = tmpImage;
  155.    }
  156.    else {
  157.       tmpImage = NULL;  /* silence compiler warnings */
  158.       p = NULL;
  159.    }
  160.  
  161.    ASSERT(width < MAX_WIDTH);
  162.  
  163.    for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
  164.       GLvoid *rgba = span.array->attribs[FRAG_ATTRIB_COL0];
  165.  
  166.       /* Get row/span of source pixels */
  167.       if (overlapping) {
  168.          /* get from buffered image */
  169.          memcpy(rgba, p, width * sizeof(GLfloat) * 4);
  170.          p += width * 4;
  171.       }
  172.       else {
  173.          /* get from framebuffer */
  174.          _swrast_read_rgba_span( ctx, ctx->ReadBuffer->_ColorReadBuffer,
  175.                                  width, srcx, sy, GL_FLOAT, rgba );
  176.       }
  177.  
  178.       if (transferOps) {
  179.          _mesa_apply_rgba_transfer_ops(ctx, transferOps, width,
  180.                                        (GLfloat (*)[4]) rgba);
  181.       }
  182.  
  183.       /* Write color span */
  184.       span.x = destx;
  185.       span.y = dy;
  186.       span.end = width;
  187.       span.array->ChanType = GL_FLOAT;
  188.       if (zoom) {
  189.          _swrast_write_zoomed_rgba_span(ctx, destx, desty, &span, rgba);
  190.       }
  191.       else {
  192.          _swrast_write_rgba_span(ctx, &span);
  193.       }
  194.    }
  195.  
  196.    span.array->ChanType = CHAN_TYPE; /* restore */
  197.  
  198.    if (overlapping)
  199.       free(tmpImage);
  200. }
  201.  
  202.  
  203. /**
  204.  * Convert floating point Z values to integer Z values with pixel transfer's
  205.  * Z scale and bias.
  206.  */
  207. static void
  208. scale_and_bias_z(struct gl_context *ctx, GLuint width,
  209.                  const GLfloat depth[], GLuint z[])
  210. {
  211.    const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
  212.    GLuint i;
  213.  
  214.    if (depthMax <= 0xffffff &&
  215.        ctx->Pixel.DepthScale == 1.0 &&
  216.        ctx->Pixel.DepthBias == 0.0) {
  217.       /* no scale or bias and no clamping and no worry of overflow */
  218.       const GLfloat depthMaxF = ctx->DrawBuffer->_DepthMaxF;
  219.       for (i = 0; i < width; i++) {
  220.          z[i] = (GLuint) (depth[i] * depthMaxF);
  221.       }
  222.    }
  223.    else {
  224.       /* need to be careful with overflow */
  225.       const GLdouble depthMaxF = ctx->DrawBuffer->_DepthMaxF;
  226.       for (i = 0; i < width; i++) {
  227.          GLdouble d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
  228.          d = CLAMP(d, 0.0, 1.0) * depthMaxF;
  229.          if (d >= depthMaxF)
  230.             z[i] = depthMax;
  231.          else
  232.             z[i] = (GLuint) d;
  233.       }
  234.    }
  235. }
  236.  
  237.  
  238.  
  239. /*
  240.  * TODO: Optimize!!!!
  241.  */
  242. static void
  243. copy_depth_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
  244.                    GLint width, GLint height,
  245.                    GLint destx, GLint desty )
  246. {
  247.    struct gl_framebuffer *fb = ctx->ReadBuffer;
  248.    struct gl_renderbuffer *readRb = fb->_DepthBuffer;
  249.    GLfloat *p, *tmpImage;
  250.    GLint sy, dy, stepy;
  251.    GLint j;
  252.    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
  253.    GLint overlapping;
  254.    SWspan span;
  255.  
  256.    if (!readRb) {
  257.       /* no readbuffer - OK */
  258.       return;
  259.    }
  260.  
  261.    INIT_SPAN(span, GL_BITMAP);
  262.    _swrast_span_default_attribs(ctx, &span);
  263.    span.arrayMask = SPAN_Z;
  264.  
  265.    if (ctx->DrawBuffer == ctx->ReadBuffer) {
  266.       overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
  267.                                     ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
  268.    }
  269.    else {
  270.       overlapping = GL_FALSE;
  271.    }
  272.  
  273.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  274.    if (!overlapping && srcy < desty) {
  275.       /* top-down  max-to-min */
  276.       sy = srcy + height - 1;
  277.       dy = desty + height - 1;
  278.       stepy = -1;
  279.    }
  280.    else {
  281.       /* bottom-up  min-to-max */
  282.       sy = srcy;
  283.       dy = desty;
  284.       stepy = 1;
  285.    }
  286.  
  287.    if (overlapping) {
  288.       GLint ssy = sy;
  289.       tmpImage = (GLfloat *) malloc(width * height * sizeof(GLfloat));
  290.       if (!tmpImage) {
  291.          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
  292.          return;
  293.       }
  294.       p = tmpImage;
  295.       for (j = 0; j < height; j++, ssy += stepy) {
  296.          _swrast_read_depth_span_float(ctx, readRb, width, srcx, ssy, p);
  297.          p += width;
  298.       }
  299.       p = tmpImage;
  300.    }
  301.    else {
  302.       tmpImage = NULL;  /* silence compiler warning */
  303.       p = NULL;
  304.    }
  305.  
  306.    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
  307.       GLfloat depth[MAX_WIDTH];
  308.       /* get depth values */
  309.       if (overlapping) {
  310.          memcpy(depth, p, width * sizeof(GLfloat));
  311.          p += width;
  312.       }
  313.       else {
  314.          _swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth);
  315.       }
  316.  
  317.       /* apply scale and bias */
  318.       scale_and_bias_z(ctx, width, depth, span.array->z);
  319.  
  320.       /* write depth values */
  321.       span.x = destx;
  322.       span.y = dy;
  323.       span.end = width;
  324.       if (zoom)
  325.          _swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
  326.       else
  327.          _swrast_write_rgba_span(ctx, &span);
  328.    }
  329.  
  330.    if (overlapping)
  331.       free(tmpImage);
  332. }
  333.  
  334.  
  335.  
  336. static void
  337. copy_stencil_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
  338.                      GLint width, GLint height,
  339.                      GLint destx, GLint desty )
  340. {
  341.    struct gl_framebuffer *fb = ctx->ReadBuffer;
  342.    struct gl_renderbuffer *rb = fb->_StencilBuffer;
  343.    GLint sy, dy, stepy;
  344.    GLint j;
  345.    GLstencil *p, *tmpImage;
  346.    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
  347.    GLint overlapping;
  348.  
  349.    if (!rb) {
  350.       /* no readbuffer - OK */
  351.       return;
  352.    }
  353.  
  354.    if (ctx->DrawBuffer == ctx->ReadBuffer) {
  355.       overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
  356.                                     ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
  357.    }
  358.    else {
  359.       overlapping = GL_FALSE;
  360.    }
  361.  
  362.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  363.    if (!overlapping && srcy < desty) {
  364.       /* top-down  max-to-min */
  365.       sy = srcy + height - 1;
  366.       dy = desty + height - 1;
  367.       stepy = -1;
  368.    }
  369.    else {
  370.       /* bottom-up  min-to-max */
  371.       sy = srcy;
  372.       dy = desty;
  373.       stepy = 1;
  374.    }
  375.  
  376.    if (overlapping) {
  377.       GLint ssy = sy;
  378.       tmpImage = (GLstencil *) malloc(width * height * sizeof(GLstencil));
  379.       if (!tmpImage) {
  380.          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
  381.          return;
  382.       }
  383.       p = tmpImage;
  384.       for (j = 0; j < height; j++, ssy += stepy) {
  385.          _swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p );
  386.          p += width;
  387.       }
  388.       p = tmpImage;
  389.    }
  390.    else {
  391.       tmpImage = NULL;  /* silence compiler warning */
  392.       p = NULL;
  393.    }
  394.  
  395.    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
  396.       GLstencil stencil[MAX_WIDTH];
  397.  
  398.       /* Get stencil values */
  399.       if (overlapping) {
  400.          memcpy(stencil, p, width * sizeof(GLstencil));
  401.          p += width;
  402.       }
  403.       else {
  404.          _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
  405.       }
  406.  
  407.       _mesa_apply_stencil_transfer_ops(ctx, width, stencil);
  408.  
  409.       /* Write stencil values */
  410.       if (zoom) {
  411.          _swrast_write_zoomed_stencil_span(ctx, destx, desty, width,
  412.                                            destx, dy, stencil);
  413.       }
  414.       else {
  415.          _swrast_write_stencil_span( ctx, width, destx, dy, stencil );
  416.       }
  417.    }
  418.  
  419.    if (overlapping)
  420.       free(tmpImage);
  421. }
  422.  
  423.  
  424. /**
  425.  * This isn't terribly efficient.  If a driver really has combined
  426.  * depth/stencil buffers the driver should implement an optimized
  427.  * CopyPixels function.
  428.  */
  429. static void
  430. copy_depth_stencil_pixels(struct gl_context *ctx,
  431.                           const GLint srcX, const GLint srcY,
  432.                           const GLint width, const GLint height,
  433.                           const GLint destX, const GLint destY)
  434. {
  435.    struct gl_renderbuffer *stencilReadRb, *depthReadRb, *depthDrawRb;
  436.    GLint sy, dy, stepy;
  437.    GLint j;
  438.    GLstencil *tempStencilImage = NULL, *stencilPtr = NULL;
  439.    GLfloat *tempDepthImage = NULL, *depthPtr = NULL;
  440.    const GLfloat depthScale = ctx->DrawBuffer->_DepthMaxF;
  441.    const GLuint stencilMask = ctx->Stencil.WriteMask[0];
  442.    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
  443.    const GLboolean scaleOrBias
  444.       = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
  445.    GLint overlapping;
  446.  
  447.    depthDrawRb = ctx->DrawBuffer->_DepthBuffer;
  448.    depthReadRb = ctx->ReadBuffer->_DepthBuffer;
  449.    stencilReadRb = ctx->ReadBuffer->_StencilBuffer;
  450.  
  451.    ASSERT(depthDrawRb);
  452.    ASSERT(depthReadRb);
  453.    ASSERT(stencilReadRb);
  454.  
  455.    if (ctx->DrawBuffer == ctx->ReadBuffer) {
  456.       overlapping = regions_overlap(srcX, srcY, destX, destY, width, height,
  457.                                     ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
  458.    }
  459.    else {
  460.       overlapping = GL_FALSE;
  461.    }
  462.  
  463.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  464.    if (!overlapping && srcY < destY) {
  465.       /* top-down  max-to-min */
  466.       sy = srcY + height - 1;
  467.       dy = destY + height - 1;
  468.       stepy = -1;
  469.    }
  470.    else {
  471.       /* bottom-up  min-to-max */
  472.       sy = srcY;
  473.       dy = destY;
  474.       stepy = 1;
  475.    }
  476.  
  477.    if (overlapping) {
  478.       GLint ssy = sy;
  479.  
  480.       if (stencilMask != 0x0) {
  481.          tempStencilImage
  482.             = (GLstencil *) malloc(width * height * sizeof(GLstencil));
  483.          if (!tempStencilImage) {
  484.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
  485.             return;
  486.          }
  487.  
  488.          /* get copy of stencil pixels */
  489.          stencilPtr = tempStencilImage;
  490.          for (j = 0; j < height; j++, ssy += stepy) {
  491.             _swrast_read_stencil_span(ctx, stencilReadRb,
  492.                                       width, srcX, ssy, stencilPtr);
  493.             stencilPtr += width;
  494.          }
  495.          stencilPtr = tempStencilImage;
  496.       }
  497.  
  498.       if (ctx->Depth.Mask) {
  499.          tempDepthImage
  500.             = (GLfloat *) malloc(width * height * sizeof(GLfloat));
  501.          if (!tempDepthImage) {
  502.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
  503.             free(tempStencilImage);
  504.             return;
  505.          }
  506.  
  507.          /* get copy of depth pixels */
  508.          depthPtr = tempDepthImage;
  509.          for (j = 0; j < height; j++, ssy += stepy) {
  510.             _swrast_read_depth_span_float(ctx, depthReadRb,
  511.                                           width, srcX, ssy, depthPtr);
  512.             depthPtr += width;
  513.          }
  514.          depthPtr = tempDepthImage;
  515.       }
  516.    }
  517.  
  518.    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
  519.       if (stencilMask != 0x0) {
  520.          GLstencil stencil[MAX_WIDTH];
  521.  
  522.          /* Get stencil values */
  523.          if (overlapping) {
  524.             memcpy(stencil, stencilPtr, width * sizeof(GLstencil));
  525.             stencilPtr += width;
  526.          }
  527.          else {
  528.             _swrast_read_stencil_span(ctx, stencilReadRb,
  529.                                       width, srcX, sy, stencil);
  530.          }
  531.  
  532.          _mesa_apply_stencil_transfer_ops(ctx, width, stencil);
  533.  
  534.          /* Write values */
  535.          if (zoom) {
  536.             _swrast_write_zoomed_stencil_span(ctx, destX, destY, width,
  537.                                               destX, dy, stencil);
  538.          }
  539.          else {
  540.             _swrast_write_stencil_span( ctx, width, destX, dy, stencil );
  541.          }
  542.       }
  543.  
  544.       if (ctx->Depth.Mask) {
  545.          GLfloat depth[MAX_WIDTH];
  546.          GLuint zVals32[MAX_WIDTH];
  547.          GLushort zVals16[MAX_WIDTH];
  548.          GLvoid *zVals;
  549.          GLuint zBytes;
  550.  
  551.          /* get depth values */
  552.          if (overlapping) {
  553.             memcpy(depth, depthPtr, width * sizeof(GLfloat));
  554.             depthPtr += width;
  555.          }
  556.          else {
  557.             _swrast_read_depth_span_float(ctx, depthReadRb,
  558.                                           width, srcX, sy, depth);
  559.          }
  560.  
  561.          /* scale & bias */
  562.          if (scaleOrBias) {
  563.             _mesa_scale_and_bias_depth(ctx, width, depth);
  564.          }
  565.          /* convert to integer Z values */
  566.          if (depthDrawRb->DataType == GL_UNSIGNED_SHORT) {
  567.             GLint k;
  568.             for (k = 0; k < width; k++)
  569.                zVals16[k] = (GLushort) (depth[k] * depthScale);
  570.             zVals = zVals16;
  571.             zBytes = 2;
  572.          }
  573.          else {
  574.             GLint k;
  575.             for (k = 0; k < width; k++)
  576.                zVals32[k] = (GLuint) (depth[k] * depthScale);
  577.             zVals = zVals32;
  578.             zBytes = 4;
  579.          }
  580.  
  581.          /* Write values */
  582.          if (zoom) {
  583.             _swrast_write_zoomed_z_span(ctx, destX, destY, width,
  584.                                         destX, dy, zVals);
  585.          }
  586.          else {
  587.             _swrast_put_row(ctx, depthDrawRb, width, destX, dy, zVals, zBytes);
  588.          }
  589.       }
  590.    }
  591.  
  592.    if (tempStencilImage)
  593.       free(tempStencilImage);
  594.  
  595.    if (tempDepthImage)
  596.       free(tempDepthImage);
  597. }
  598.  
  599.  
  600.  
  601. /**
  602.  * Try to do a fast copy pixels.
  603.  */
  604. static GLboolean
  605. fast_copy_pixels(struct gl_context *ctx,
  606.                  GLint srcX, GLint srcY, GLsizei width, GLsizei height,
  607.                  GLint dstX, GLint dstY, GLenum type)
  608. {
  609.    struct gl_framebuffer *srcFb = ctx->ReadBuffer;
  610.    struct gl_framebuffer *dstFb = ctx->DrawBuffer;
  611.    struct gl_renderbuffer *srcRb, *dstRb;
  612.    GLint row, yStep;
  613.  
  614.    if (SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 ||
  615.        ctx->Pixel.ZoomX != 1.0F ||
  616.        ctx->Pixel.ZoomY != 1.0F ||
  617.        ctx->_ImageTransferState) {
  618.       /* can't handle these */
  619.       return GL_FALSE;
  620.    }
  621.  
  622.    if (type == GL_COLOR) {
  623.       if (dstFb->_NumColorDrawBuffers != 1)
  624.          return GL_FALSE;
  625.       srcRb = srcFb->_ColorReadBuffer;
  626.       dstRb = dstFb->_ColorDrawBuffers[0];
  627.    }
  628.    else if (type == GL_STENCIL) {
  629.       srcRb = srcFb->_StencilBuffer;
  630.       dstRb = dstFb->_StencilBuffer;
  631.    }
  632.    else if (type == GL_DEPTH) {
  633.       srcRb = srcFb->_DepthBuffer;
  634.       dstRb = dstFb->_DepthBuffer;
  635.    }
  636.    else {
  637.       ASSERT(type == GL_DEPTH_STENCIL_EXT);
  638.       /* XXX correct? */
  639.       srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
  640.       dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
  641.    }
  642.  
  643.    /* src and dst renderbuffers must be same format and type */
  644.    if (!srcRb || !dstRb ||
  645.        srcRb->DataType != dstRb->DataType ||
  646.        srcRb->_BaseFormat != dstRb->_BaseFormat) {
  647.       return GL_FALSE;
  648.    }
  649.  
  650.    /* clipping not supported */
  651.    if (srcX < 0 || srcX + width > (GLint) srcFb->Width ||
  652.        srcY < 0 || srcY + height > (GLint) srcFb->Height ||
  653.        dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
  654.        dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
  655.       return GL_FALSE;
  656.    }
  657.  
  658.    /* overlapping src/dst doesn't matter, just determine Y direction */
  659.    if (srcY < dstY) {
  660.       /* top-down  max-to-min */
  661.       srcY = srcY + height - 1;
  662.       dstY = dstY + height - 1;
  663.       yStep = -1;
  664.    }
  665.    else {
  666.       /* bottom-up  min-to-max */
  667.       yStep = 1;
  668.    }
  669.  
  670.    for (row = 0; row < height; row++) {
  671.       GLuint temp[MAX_WIDTH][4];
  672.       srcRb->GetRow(ctx, srcRb, width, srcX, srcY, temp);
  673.       dstRb->PutRow(ctx, dstRb, width, dstX, dstY, temp, NULL);
  674.       srcY += yStep;
  675.       dstY += yStep;
  676.    }
  677.  
  678.    return GL_TRUE;
  679. }
  680.  
  681.  
  682. /**
  683.  * Do software-based glCopyPixels.
  684.  * By time we get here, all parameters will have been error-checked.
  685.  */
  686. void
  687. _swrast_CopyPixels( struct gl_context *ctx,
  688.                     GLint srcx, GLint srcy, GLsizei width, GLsizei height,
  689.                     GLint destx, GLint desty, GLenum type )
  690. {
  691.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  692.    swrast_render_start(ctx);
  693.      
  694.    if (!_mesa_check_conditional_render(ctx))
  695.       return; /* don't copy */
  696.  
  697.    if (swrast->NewState)
  698.       _swrast_validate_derived( ctx );
  699.  
  700.    if (!fast_copy_pixels(ctx, srcx, srcy, width, height, destx, desty, type)) {
  701.       switch (type) {
  702.       case GL_COLOR:
  703.          copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
  704.          break;
  705.       case GL_DEPTH:
  706.          copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
  707.          break;
  708.       case GL_STENCIL:
  709.          copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
  710.          break;
  711.       case GL_DEPTH_STENCIL_EXT:
  712.          copy_depth_stencil_pixels(ctx, srcx, srcy, width, height, destx, desty);
  713.          break;
  714.       default:
  715.          _mesa_problem(ctx, "unexpected type in _swrast_CopyPixels");
  716.       }
  717.    }
  718.  
  719.    swrast_render_finish(ctx);
  720. }
  721.