Subversion Repositories Kolibri OS

Rev

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

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