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/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 = VARYING_BIT_COL0; /* we'll fill in COL0 attrib values */
  140.  
  141.    if (overlapping) {
  142.       tmpImage = 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, 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 < SWRAST_MAX_WIDTH);
  162.  
  163.    for (row = 0; row < height; row++, sy += stepy, dy += stepy) {
  164.       GLvoid *rgba = span.array->attribs[VARYING_SLOT_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, 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->Attachment[BUFFER_DEPTH].Renderbuffer;
  249.    GLfloat *p, *tmpImage, *depth;
  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 = 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.    depth = malloc(width * sizeof(GLfloat));
  307.    if (!depth) {
  308.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels()");
  309.       goto end;
  310.    }
  311.  
  312.    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
  313.       /* get depth values */
  314.       if (overlapping) {
  315.          memcpy(depth, p, width * sizeof(GLfloat));
  316.          p += width;
  317.       }
  318.       else {
  319.          _swrast_read_depth_span_float(ctx, readRb, width, srcx, sy, depth);
  320.       }
  321.  
  322.       /* apply scale and bias */
  323.       scale_and_bias_z(ctx, width, depth, span.array->z);
  324.  
  325.       /* write depth values */
  326.       span.x = destx;
  327.       span.y = dy;
  328.       span.end = width;
  329.       if (zoom)
  330.          _swrast_write_zoomed_depth_span(ctx, destx, desty, &span);
  331.       else
  332.          _swrast_write_rgba_span(ctx, &span);
  333.    }
  334.  
  335.    free(depth);
  336.  
  337. end:
  338.    if (overlapping)
  339.       free(tmpImage);
  340. }
  341.  
  342.  
  343.  
  344. static void
  345. copy_stencil_pixels( struct gl_context *ctx, GLint srcx, GLint srcy,
  346.                      GLint width, GLint height,
  347.                      GLint destx, GLint desty )
  348. {
  349.    struct gl_framebuffer *fb = ctx->ReadBuffer;
  350.    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
  351.    GLint sy, dy, stepy;
  352.    GLint j;
  353.    GLubyte *p, *tmpImage, *stencil;
  354.    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
  355.    GLint overlapping;
  356.  
  357.    if (!rb) {
  358.       /* no readbuffer - OK */
  359.       return;
  360.    }
  361.  
  362.    if (ctx->DrawBuffer == ctx->ReadBuffer) {
  363.       overlapping = regions_overlap(srcx, srcy, destx, desty, width, height,
  364.                                     ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
  365.    }
  366.    else {
  367.       overlapping = GL_FALSE;
  368.    }
  369.  
  370.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  371.    if (!overlapping && srcy < desty) {
  372.       /* top-down  max-to-min */
  373.       sy = srcy + height - 1;
  374.       dy = desty + height - 1;
  375.       stepy = -1;
  376.    }
  377.    else {
  378.       /* bottom-up  min-to-max */
  379.       sy = srcy;
  380.       dy = desty;
  381.       stepy = 1;
  382.    }
  383.  
  384.    if (overlapping) {
  385.       GLint ssy = sy;
  386.       tmpImage = malloc(width * height * sizeof(GLubyte));
  387.       if (!tmpImage) {
  388.          _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
  389.          return;
  390.       }
  391.       p = tmpImage;
  392.       for (j = 0; j < height; j++, ssy += stepy) {
  393.          _swrast_read_stencil_span( ctx, rb, width, srcx, ssy, p );
  394.          p += width;
  395.       }
  396.       p = tmpImage;
  397.    }
  398.    else {
  399.       tmpImage = NULL;  /* silence compiler warning */
  400.       p = NULL;
  401.    }
  402.  
  403.    stencil = malloc(width * sizeof(GLubyte));
  404.    if (!stencil) {
  405.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels()");
  406.       goto end;
  407.    }
  408.  
  409.    for (j = 0; j < height; j++, sy += stepy, dy += stepy) {
  410.       /* Get stencil values */
  411.       if (overlapping) {
  412.          memcpy(stencil, p, width * sizeof(GLubyte));
  413.          p += width;
  414.       }
  415.       else {
  416.          _swrast_read_stencil_span( ctx, rb, width, srcx, sy, stencil );
  417.       }
  418.  
  419.       _mesa_apply_stencil_transfer_ops(ctx, width, stencil);
  420.  
  421.       /* Write stencil values */
  422.       if (zoom) {
  423.          _swrast_write_zoomed_stencil_span(ctx, destx, desty, width,
  424.                                            destx, dy, stencil);
  425.       }
  426.       else {
  427.          _swrast_write_stencil_span( ctx, width, destx, dy, stencil );
  428.       }
  429.    }
  430.  
  431.    free(stencil);
  432.  
  433. end:
  434.    if (overlapping)
  435.       free(tmpImage);
  436. }
  437.  
  438.  
  439. /**
  440.  * Try to do a fast 1:1 blit with memcpy.
  441.  * \return GL_TRUE if successful, GL_FALSE otherwise.
  442.  */
  443. GLboolean
  444. swrast_fast_copy_pixels(struct gl_context *ctx,
  445.                         GLint srcX, GLint srcY, GLsizei width, GLsizei height,
  446.                         GLint dstX, GLint dstY, GLenum type)
  447. {
  448.    struct gl_framebuffer *srcFb = ctx->ReadBuffer;
  449.    struct gl_framebuffer *dstFb = ctx->DrawBuffer;
  450.    struct gl_renderbuffer *srcRb, *dstRb;
  451.    GLint row;
  452.    GLuint pixelBytes, widthInBytes;
  453.    GLubyte *srcMap, *dstMap;
  454.    GLint srcRowStride, dstRowStride;
  455.  
  456.    if (type == GL_COLOR) {
  457.       if (dstFb->_NumColorDrawBuffers != 1)
  458.          return GL_FALSE;
  459.       srcRb = srcFb->_ColorReadBuffer;
  460.       dstRb = dstFb->_ColorDrawBuffers[0];
  461.    }
  462.    else if (type == GL_STENCIL) {
  463.       srcRb = srcFb->Attachment[BUFFER_STENCIL].Renderbuffer;
  464.       dstRb = dstFb->Attachment[BUFFER_STENCIL].Renderbuffer;
  465.    }
  466.    else if (type == GL_DEPTH) {
  467.       srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
  468.       dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
  469.    }
  470.    else {
  471.       ASSERT(type == GL_DEPTH_STENCIL_EXT);
  472.       /* XXX correct? */
  473.       srcRb = srcFb->Attachment[BUFFER_DEPTH].Renderbuffer;
  474.       dstRb = dstFb->Attachment[BUFFER_DEPTH].Renderbuffer;
  475.    }
  476.  
  477.    /* src and dst renderbuffers must be same format */
  478.    if (!srcRb || !dstRb || srcRb->Format != dstRb->Format) {
  479.       return GL_FALSE;
  480.    }
  481.  
  482.    if (type == GL_STENCIL || type == GL_DEPTH_COMPONENT) {
  483.       /* can't handle packed depth+stencil here */
  484.       if (_mesa_is_format_packed_depth_stencil(srcRb->Format) ||
  485.           _mesa_is_format_packed_depth_stencil(dstRb->Format))
  486.          return GL_FALSE;
  487.    }
  488.    else if (type == GL_DEPTH_STENCIL) {
  489.       /* can't handle separate depth/stencil buffers */
  490.       if (srcRb != srcFb->Attachment[BUFFER_STENCIL].Renderbuffer ||
  491.           dstRb != dstFb->Attachment[BUFFER_STENCIL].Renderbuffer)
  492.          return GL_FALSE;
  493.    }
  494.  
  495.    /* clipping not supported */
  496.    if (srcX < 0 || srcX + width > (GLint) srcFb->Width ||
  497.        srcY < 0 || srcY + height > (GLint) srcFb->Height ||
  498.        dstX < dstFb->_Xmin || dstX + width > dstFb->_Xmax ||
  499.        dstY < dstFb->_Ymin || dstY + height > dstFb->_Ymax) {
  500.       return GL_FALSE;
  501.    }
  502.  
  503.    pixelBytes = _mesa_get_format_bytes(srcRb->Format);
  504.    widthInBytes = width * pixelBytes;
  505.  
  506.    if (srcRb == dstRb) {
  507.       /* map whole buffer for read/write */
  508.       /* XXX we could be clever and just map the union region of the
  509.        * source and dest rects.
  510.        */
  511.       GLubyte *map;
  512.       GLint rowStride;
  513.  
  514.       ctx->Driver.MapRenderbuffer(ctx, srcRb, 0, 0,
  515.                                   srcRb->Width, srcRb->Height,
  516.                                   GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
  517.                                   &map, &rowStride);
  518.       if (!map) {
  519.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
  520.          return GL_TRUE; /* don't retry with slow path */
  521.       }
  522.  
  523.       srcMap = map + srcY * rowStride + srcX * pixelBytes;
  524.       dstMap = map + dstY * rowStride + dstX * pixelBytes;
  525.  
  526.       /* this handles overlapping copies */
  527.       if (srcY < dstY) {
  528.          /* copy in reverse (top->down) order */
  529.          srcMap += rowStride * (height - 1);
  530.          dstMap += rowStride * (height - 1);
  531.          srcRowStride = -rowStride;
  532.          dstRowStride = -rowStride;
  533.       }
  534.       else {
  535.          /* copy in normal (bottom->up) order */
  536.          srcRowStride = rowStride;
  537.          dstRowStride = rowStride;
  538.       }
  539.    }
  540.    else {
  541.       /* different src/dst buffers */
  542.       ctx->Driver.MapRenderbuffer(ctx, srcRb, srcX, srcY,
  543.                                   width, height,
  544.                                   GL_MAP_READ_BIT, &srcMap, &srcRowStride);
  545.       if (!srcMap) {
  546.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
  547.          return GL_TRUE; /* don't retry with slow path */
  548.       }
  549.       ctx->Driver.MapRenderbuffer(ctx, dstRb, dstX, dstY,
  550.                                   width, height,
  551.                                   GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
  552.       if (!dstMap) {
  553.          ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
  554.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
  555.          return GL_TRUE; /* don't retry with slow path */
  556.       }
  557.    }
  558.  
  559.    for (row = 0; row < height; row++) {
  560.       /* memmove() in case of overlap */
  561.       memmove(dstMap, srcMap, widthInBytes);
  562.       dstMap += dstRowStride;
  563.       srcMap += srcRowStride;
  564.    }
  565.  
  566.    ctx->Driver.UnmapRenderbuffer(ctx, srcRb);
  567.    if (dstRb != srcRb) {
  568.       ctx->Driver.UnmapRenderbuffer(ctx, dstRb);
  569.    }
  570.  
  571.    return GL_TRUE;
  572. }
  573.  
  574.  
  575. /**
  576.  * Find/map the renderbuffer that we'll be reading from.
  577.  * The swrast_render_start() function only maps the drawing buffers,
  578.  * not the read buffer.
  579.  */
  580. static struct gl_renderbuffer *
  581. map_readbuffer(struct gl_context *ctx, GLenum type)
  582. {
  583.    struct gl_framebuffer *fb = ctx->ReadBuffer;
  584.    struct gl_renderbuffer *rb;
  585.    struct swrast_renderbuffer *srb;
  586.  
  587.    switch (type) {
  588.    case GL_COLOR:
  589.       rb = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer;
  590.       break;
  591.    case GL_DEPTH:
  592.    case GL_DEPTH_STENCIL:
  593.       rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
  594.       break;
  595.    case GL_STENCIL:
  596.       rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
  597.       break;
  598.    default:
  599.       return NULL;
  600.    }
  601.  
  602.    srb = swrast_renderbuffer(rb);
  603.  
  604.    if (!srb || srb->Map) {
  605.       /* no buffer, or buffer is mapped already, we're done */
  606.       return NULL;
  607.    }
  608.  
  609.    ctx->Driver.MapRenderbuffer(ctx, rb,
  610.                                0, 0, rb->Width, rb->Height,
  611.                                GL_MAP_READ_BIT,
  612.                                &srb->Map, &srb->RowStride);
  613.  
  614.    return rb;
  615. }
  616.  
  617.  
  618. /**
  619.  * Do software-based glCopyPixels.
  620.  * By time we get here, all parameters will have been error-checked.
  621.  */
  622. void
  623. _swrast_CopyPixels( struct gl_context *ctx,
  624.                     GLint srcx, GLint srcy, GLsizei width, GLsizei height,
  625.                     GLint destx, GLint desty, GLenum type )
  626. {
  627.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  628.    struct gl_renderbuffer *rb;
  629.      
  630.    if (!_mesa_check_conditional_render(ctx))
  631.       return; /* don't copy */
  632.  
  633.    if (swrast->NewState)
  634.       _swrast_validate_derived( ctx );
  635.  
  636.    if (!(SWRAST_CONTEXT(ctx)->_RasterMask != 0x0 ||
  637.          ctx->Pixel.ZoomX != 1.0F ||
  638.          ctx->Pixel.ZoomY != 1.0F ||
  639.          ctx->_ImageTransferState) &&
  640.        swrast_fast_copy_pixels(ctx, 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.