Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * 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
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28.  
  29. /**
  30.  * glReadPixels interface to pipe
  31.  *
  32.  * \author Brian Paul
  33.  */
  34.  
  35.  
  36. #include "main/imports.h"
  37. #include "main/bufferobj.h"
  38. #include "main/context.h"
  39. #include "main/image.h"
  40. #include "main/pack.h"
  41.  
  42. #include "pipe/p_context.h"
  43. #include "pipe/p_defines.h"
  44. #include "util/u_inlines.h"
  45. #include "util/u_tile.h"
  46.  
  47. #include "st_debug.h"
  48. #include "st_context.h"
  49. #include "st_atom.h"
  50. #include "st_cb_bitmap.h"
  51. #include "st_cb_readpixels.h"
  52. #include "st_cb_fbo.h"
  53.  
  54. /**
  55.  * Special case for reading stencil buffer.
  56.  * For color/depth we use get_tile().  For stencil, map the stencil buffer.
  57.  */
  58. void
  59. st_read_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
  60.                        GLsizei width, GLsizei height,
  61.                        GLenum format, GLenum type,
  62.                        const struct gl_pixelstore_attrib *packing,
  63.                        GLvoid *pixels)
  64. {
  65.    struct gl_framebuffer *fb = ctx->ReadBuffer;
  66.    struct pipe_context *pipe = st_context(ctx)->pipe;
  67.    struct st_renderbuffer *strb = st_renderbuffer(fb->_StencilBuffer);
  68.    struct pipe_transfer *pt;
  69.    ubyte *stmap;
  70.    GLint j;
  71.  
  72.    if (strb->Base.Wrapped) {
  73.       strb = st_renderbuffer(strb->Base.Wrapped);
  74.    }
  75.  
  76.    if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
  77.       y = ctx->DrawBuffer->Height - y - height;
  78.    }
  79.  
  80.    /* Create a read transfer from the renderbuffer's texture */
  81.  
  82.    pt = pipe_get_transfer(pipe, strb->texture,
  83.                           0, 0,
  84.                           PIPE_TRANSFER_READ,
  85.                           x, y, width, height);
  86.  
  87.    /* map the stencil buffer */
  88.    stmap = pipe_transfer_map(pipe, pt);
  89.  
  90.    /* width should never be > MAX_WIDTH since we did clipping earlier */
  91.    ASSERT(width <= MAX_WIDTH);
  92.  
  93.    /* process image row by row */
  94.    for (j = 0; j < height; j++) {
  95.       GLvoid *dest;
  96.       GLstencil sValues[MAX_WIDTH];
  97.       GLfloat zValues[MAX_WIDTH];
  98.       GLint srcY;
  99.  
  100.       if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
  101.          srcY = height - j - 1;
  102.       }
  103.       else {
  104.          srcY = j;
  105.       }
  106.  
  107.       /* get stencil (and Z) values */
  108.       switch (pt->resource->format) {
  109.       case PIPE_FORMAT_S8_USCALED:
  110.          {
  111.             const ubyte *src = stmap + srcY * pt->stride;
  112.             memcpy(sValues, src, width);
  113.          }
  114.          break;
  115.       case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
  116.          if (format == GL_DEPTH_STENCIL) {
  117.             const uint *src = (uint *) (stmap + srcY * pt->stride);
  118.             const GLfloat scale = 1.0f / (0xffffff);
  119.             GLint k;
  120.             for (k = 0; k < width; k++) {
  121.                sValues[k] = src[k] >> 24;
  122.                zValues[k] = (src[k] & 0xffffff) * scale;
  123.             }
  124.          }
  125.          else {
  126.             const uint *src = (uint *) (stmap + srcY * pt->stride);
  127.             GLint k;
  128.             for (k = 0; k < width; k++) {
  129.                sValues[k] = src[k] >> 24;
  130.             }
  131.          }
  132.          break;
  133.       case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
  134.          if (format == GL_DEPTH_STENCIL) {
  135.             const uint *src = (uint *) (stmap + srcY * pt->stride);
  136.             const GLfloat scale = 1.0f / (0xffffff);
  137.             GLint k;
  138.             for (k = 0; k < width; k++) {
  139.                sValues[k] = src[k] & 0xff;
  140.                zValues[k] = (src[k] >> 8) * scale;
  141.             }
  142.          }
  143.          else {
  144.             const uint *src = (uint *) (stmap + srcY * pt->stride);
  145.             GLint k;
  146.             for (k = 0; k < width; k++) {
  147.                sValues[k] = src[k] & 0xff;
  148.             }
  149.          }
  150.          break;
  151.       default:
  152.          assert(0);
  153.       }
  154.  
  155.       /* store */
  156.       dest = _mesa_image_address2d(packing, pixels, width, height,
  157.                                    format, type, j, 0);
  158.       if (format == GL_DEPTH_STENCIL) {
  159.          _mesa_pack_depth_stencil_span(ctx, width, dest,
  160.                                        zValues, sValues, packing);
  161.       }
  162.       else {
  163.          _mesa_pack_stencil_span(ctx, width, type, dest, sValues, packing);
  164.       }
  165.    }
  166.  
  167.    /* unmap the stencil buffer */
  168.    pipe_transfer_unmap(pipe, pt);
  169.    pipe->transfer_destroy(pipe, pt);
  170. }
  171.  
  172.  
  173. /**
  174.  * Return renderbuffer to use for reading color pixels for glRead/CopyPixel
  175.  * commands.
  176.  */
  177. struct st_renderbuffer *
  178. st_get_color_read_renderbuffer(struct gl_context *ctx)
  179. {
  180.    struct gl_framebuffer *fb = ctx->ReadBuffer;
  181.    struct st_renderbuffer *strb =
  182.       st_renderbuffer(fb->_ColorReadBuffer);
  183.  
  184.    return strb;
  185. }
  186.  
  187.  
  188. /**
  189.  * Try to do glReadPixels in a fast manner for common cases.
  190.  * \return GL_TRUE for success, GL_FALSE for failure
  191.  */
  192. static GLboolean
  193. st_fast_readpixels(struct gl_context *ctx, struct st_renderbuffer *strb,
  194.                    GLint x, GLint y, GLsizei width, GLsizei height,
  195.                    GLenum format, GLenum type,
  196.                    const struct gl_pixelstore_attrib *pack,
  197.                    GLvoid *dest)
  198. {
  199.    enum combination {
  200.       A8R8G8B8_UNORM_TO_RGBA_UBYTE,
  201.       A8R8G8B8_UNORM_TO_RGB_UBYTE,
  202.       A8R8G8B8_UNORM_TO_BGRA_UINT
  203.    } combo;
  204.  
  205.    if (ctx->_ImageTransferState)
  206.       return GL_FALSE;
  207.  
  208.    if (strb->format == PIPE_FORMAT_B8G8R8A8_UNORM &&
  209.        format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
  210.       combo = A8R8G8B8_UNORM_TO_RGBA_UBYTE;
  211.    }
  212.    else if (strb->format == PIPE_FORMAT_B8G8R8A8_UNORM &&
  213.             format == GL_RGB && type == GL_UNSIGNED_BYTE) {
  214.       combo = A8R8G8B8_UNORM_TO_RGB_UBYTE;
  215.    }
  216.    else if (strb->format == PIPE_FORMAT_B8G8R8A8_UNORM &&
  217.             format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
  218.       combo = A8R8G8B8_UNORM_TO_BGRA_UINT;
  219.    }
  220.    else {
  221.       return GL_FALSE;
  222.    }
  223.  
  224.    /*printf("st_fast_readpixels combo %d\n", (GLint) combo);*/
  225.  
  226.    {
  227.       struct pipe_context *pipe = st_context(ctx)->pipe;
  228.       struct pipe_transfer *trans;
  229.       const GLubyte *map;
  230.       GLubyte *dst;
  231.       GLint row, col, dy, dstStride;
  232.  
  233.       if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
  234.          /* convert GL Y to Gallium Y */
  235.          y = strb->texture->height0 - y - height;
  236.       }
  237.  
  238.       trans = pipe_get_transfer(pipe, strb->texture,
  239.                                 0, 0,
  240.                                 PIPE_TRANSFER_READ,
  241.                                 x, y, width, height);
  242.       if (!trans) {
  243.          return GL_FALSE;
  244.       }
  245.  
  246.       map = pipe_transfer_map(pipe, trans);
  247.       if (!map) {
  248.          pipe->transfer_destroy(pipe, trans);
  249.          return GL_FALSE;
  250.       }
  251.  
  252.       /* We always write to the user/dest buffer from low addr to high addr
  253.        * but the read order depends on renderbuffer orientation
  254.        */
  255.       if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
  256.          /* read source rows from bottom to top */
  257.          y = height - 1;
  258.          dy = -1;
  259.       }
  260.       else {
  261.          /* read source rows from top to bottom */
  262.          y = 0;
  263.          dy = 1;
  264.       }
  265.  
  266.       dst = _mesa_image_address2d(pack, dest, width, height,
  267.                                   format, type, 0, 0);
  268.       dstStride = _mesa_image_row_stride(pack, width, format, type);
  269.  
  270.       switch (combo) {
  271.       case A8R8G8B8_UNORM_TO_RGBA_UBYTE:
  272.          for (row = 0; row < height; row++) {
  273.             const GLubyte *src = map + y * trans->stride;
  274.             for (col = 0; col < width; col++) {
  275.                GLuint pixel = ((GLuint *) src)[col];
  276.                dst[col*4+0] = (pixel >> 16) & 0xff;
  277.                dst[col*4+1] = (pixel >>  8) & 0xff;
  278.                dst[col*4+2] = (pixel >>  0) & 0xff;
  279.                dst[col*4+3] = (pixel >> 24) & 0xff;
  280.             }
  281.             dst += dstStride;
  282.             y += dy;
  283.          }
  284.          break;
  285.       case A8R8G8B8_UNORM_TO_RGB_UBYTE:
  286.          for (row = 0; row < height; row++) {
  287.             const GLubyte *src = map + y * trans->stride;
  288.             for (col = 0; col < width; col++) {
  289.                GLuint pixel = ((GLuint *) src)[col];
  290.                dst[col*3+0] = (pixel >> 16) & 0xff;
  291.                dst[col*3+1] = (pixel >>  8) & 0xff;
  292.                dst[col*3+2] = (pixel >>  0) & 0xff;
  293.             }
  294.             dst += dstStride;
  295.             y += dy;
  296.          }
  297.          break;
  298.       case A8R8G8B8_UNORM_TO_BGRA_UINT:
  299.          for (row = 0; row < height; row++) {
  300.             const GLubyte *src = map + y * trans->stride;
  301.             memcpy(dst, src, 4 * width);
  302.             dst += dstStride;
  303.             y += dy;
  304.          }
  305.          break;
  306.       default:
  307.          ; /* nothing */
  308.       }
  309.  
  310.       pipe_transfer_unmap(pipe, trans);
  311.       pipe->transfer_destroy(pipe, trans);
  312.    }
  313.  
  314.    return GL_TRUE;
  315. }
  316.  
  317.  
  318. /**
  319.  * Do glReadPixels by getting rows from the framebuffer transfer with
  320.  * get_tile().  Convert to requested format/type with Mesa image routines.
  321.  * Image transfer ops are done in software too.
  322.  */
  323. static void
  324. st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
  325.               GLenum format, GLenum type,
  326.               const struct gl_pixelstore_attrib *pack,
  327.               GLvoid *dest)
  328. {
  329.    struct st_context *st = st_context(ctx);
  330.    struct pipe_context *pipe = st->pipe;
  331.    GLfloat (*temp)[4];
  332.    const GLbitfield transferOps = ctx->_ImageTransferState;
  333.    GLsizei i, j;
  334.    GLint yStep, dfStride;
  335.    GLfloat *df;
  336.    struct st_renderbuffer *strb;
  337.    struct gl_pixelstore_attrib clippedPacking = *pack;
  338.    struct pipe_transfer *trans;
  339.  
  340.    assert(ctx->ReadBuffer->Width > 0);
  341.  
  342.    st_validate_state(st);
  343.  
  344.    /* Do all needed clipping here, so that we can forget about it later */
  345.    if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
  346.       /* The ReadPixels transfer is totally outside the window bounds */
  347.       return;
  348.    }
  349.  
  350.    st_flush_bitmap_cache(st);
  351.  
  352.    dest = _mesa_map_pbo_dest(ctx, &clippedPacking, dest);
  353.    if (!dest)
  354.       return;
  355.  
  356.    if (format == GL_STENCIL_INDEX ||
  357.        format == GL_DEPTH_STENCIL) {
  358.       st_read_stencil_pixels(ctx, x, y, width, height,
  359.                              format, type, pack, dest);
  360.       return;
  361.    }
  362.    else if (format == GL_DEPTH_COMPONENT) {
  363.       strb = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
  364.       if (strb->Base.Wrapped) {
  365.          strb = st_renderbuffer(strb->Base.Wrapped);
  366.       }
  367.    }
  368.    else {
  369.       /* Read color buffer */
  370.       strb = st_get_color_read_renderbuffer(ctx);
  371.    }
  372.  
  373.    if (!strb)
  374.       return;
  375.  
  376.    /* try a fast-path readpixels before anything else */
  377.    if (st_fast_readpixels(ctx, strb, x, y, width, height,
  378.                           format, type, pack, dest)) {
  379.       /* success! */
  380.       _mesa_unmap_pbo_dest(ctx, &clippedPacking);
  381.       return;
  382.    }
  383.  
  384.    /* allocate temp pixel row buffer */
  385.    temp = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
  386.    if (!temp) {
  387.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
  388.       return;
  389.    }
  390.  
  391.    if (format == GL_RGBA && type == GL_FLOAT) {
  392.       /* write tile(row) directly into user's buffer */
  393.       df = (GLfloat *) _mesa_image_address2d(&clippedPacking, dest, width,
  394.                                              height, format, type, 0, 0);
  395.       dfStride = width * 4;
  396.    }
  397.    else {
  398.       /* write tile(row) into temp row buffer */
  399.       df = (GLfloat *) temp;
  400.       dfStride = 0;
  401.    }
  402.  
  403.    if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
  404.       /* convert GL Y to Gallium Y */
  405.       y = strb->Base.Height - y - height;
  406.    }
  407.  
  408.    /* Create a read transfer from the renderbuffer's texture */
  409.    trans = pipe_get_transfer(pipe, strb->texture,
  410.                              0, 0,
  411.                              PIPE_TRANSFER_READ,
  412.                              x, y, width, height);
  413.  
  414.    /* determine bottom-to-top vs. top-to-bottom order */
  415.    if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
  416.       y = height - 1;
  417.       yStep = -1;
  418.    }
  419.    else {
  420.       y = 0;
  421.       yStep = 1;
  422.    }
  423.  
  424.    if (ST_DEBUG & DEBUG_FALLBACK)
  425.       debug_printf("%s: fallback processing\n", __FUNCTION__);
  426.  
  427.    /*
  428.     * Copy pixels from pipe_transfer to user memory
  429.     */
  430.    {
  431.       /* dest of first pixel in client memory */
  432.       GLubyte *dst = _mesa_image_address2d(&clippedPacking, dest, width,
  433.                                            height, format, type, 0, 0);
  434.       /* dest row stride */
  435.       const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width,
  436.                                                      format, type);
  437.  
  438.       if (trans->resource->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED ||
  439.           trans->resource->format == PIPE_FORMAT_Z24X8_UNORM) {
  440.          if (format == GL_DEPTH_COMPONENT) {
  441.             for (i = 0; i < height; i++) {
  442.                GLuint ztemp[MAX_WIDTH];
  443.                GLfloat zfloat[MAX_WIDTH];
  444.                const double scale = 1.0 / ((1 << 24) - 1);
  445.                pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0);
  446.                y += yStep;
  447.                for (j = 0; j < width; j++) {
  448.                   zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff));
  449.                }
  450.                _mesa_pack_depth_span(ctx, width, dst, type,
  451.                                      zfloat, &clippedPacking);
  452.                dst += dstStride;
  453.             }
  454.          }
  455.          else {
  456.             /* XXX: unreachable code -- should be before st_read_stencil_pixels */
  457.             assert(format == GL_DEPTH_STENCIL_EXT);
  458.             for (i = 0; i < height; i++) {
  459.                GLuint *zshort = (GLuint *)dst;
  460.                pipe_get_tile_raw(pipe, trans, 0, y, width, 1, dst, 0);
  461.                y += yStep;
  462.                /* Reverse into 24/8 */
  463.                for (j = 0; j < width; j++) {
  464.                   zshort[j] = (zshort[j] << 8) | (zshort[j] >> 24);
  465.                }
  466.                dst += dstStride;
  467.             }
  468.          }
  469.       }
  470.       else if (trans->resource->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM ||
  471.                trans->resource->format == PIPE_FORMAT_X8Z24_UNORM) {
  472.          if (format == GL_DEPTH_COMPONENT) {
  473.             for (i = 0; i < height; i++) {
  474.                GLuint ztemp[MAX_WIDTH];
  475.                GLfloat zfloat[MAX_WIDTH];
  476.                const double scale = 1.0 / ((1 << 24) - 1);
  477.                pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0);
  478.                y += yStep;
  479.                for (j = 0; j < width; j++) {
  480.                   zfloat[j] = (float) (scale * ((ztemp[j] >> 8) & 0xffffff));
  481.                }
  482.                _mesa_pack_depth_span(ctx, width, dst, type,
  483.                                      zfloat, &clippedPacking);
  484.                dst += dstStride;
  485.             }
  486.          }
  487.          else {
  488.             /* XXX: unreachable code -- should be before st_read_stencil_pixels */
  489.             assert(format == GL_DEPTH_STENCIL_EXT);
  490.             for (i = 0; i < height; i++) {
  491.                pipe_get_tile_raw(pipe, trans, 0, y, width, 1, dst, 0);
  492.                y += yStep;
  493.                dst += dstStride;
  494.             }
  495.          }
  496.       }
  497.       else if (trans->resource->format == PIPE_FORMAT_Z16_UNORM) {
  498.          for (i = 0; i < height; i++) {
  499.             GLushort ztemp[MAX_WIDTH];
  500.             GLfloat zfloat[MAX_WIDTH];
  501.             const double scale = 1.0 / 0xffff;
  502.             pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0);
  503.             y += yStep;
  504.             for (j = 0; j < width; j++) {
  505.                zfloat[j] = (float) (scale * ztemp[j]);
  506.             }
  507.             _mesa_pack_depth_span(ctx, width, dst, type,
  508.                                   zfloat, &clippedPacking);
  509.             dst += dstStride;
  510.          }
  511.       }
  512.       else if (trans->resource->format == PIPE_FORMAT_Z32_UNORM) {
  513.          for (i = 0; i < height; i++) {
  514.             GLuint ztemp[MAX_WIDTH];
  515.             GLfloat zfloat[MAX_WIDTH];
  516.             const double scale = 1.0 / 0xffffffff;
  517.             pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0);
  518.             y += yStep;
  519.             for (j = 0; j < width; j++) {
  520.                zfloat[j] = (float) (scale * ztemp[j]);
  521.             }
  522.             _mesa_pack_depth_span(ctx, width, dst, type,
  523.                                   zfloat, &clippedPacking);
  524.             dst += dstStride;
  525.          }
  526.       }
  527.       else {
  528.          /* RGBA format */
  529.          /* Do a row at a time to flip image data vertically */
  530.          for (i = 0; i < height; i++) {
  531.             pipe_get_tile_rgba(pipe, trans, 0, y, width, 1, df);
  532.             y += yStep;
  533.             df += dfStride;
  534.             if (!dfStride) {
  535.                _mesa_pack_rgba_span_float(ctx, width, temp, format, type, dst,
  536.                                           &clippedPacking, transferOps);
  537.                dst += dstStride;
  538.             }
  539.          }
  540.       }
  541.    }
  542.  
  543.    free(temp);
  544.  
  545.    pipe->transfer_destroy(pipe, trans);
  546.  
  547.    _mesa_unmap_pbo_dest(ctx, &clippedPacking);
  548. }
  549.  
  550.  
  551. void st_init_readpixels_functions(struct dd_function_table *functions)
  552. {
  553.    functions->ReadPixels = st_readpixels;
  554. }
  555.