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

  1. /* $Id: s_readpix.c,v 1.17 2002/10/24 23:57:24 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  4.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. #include "glheader.h"
  29. #include "colormac.h"
  30. #include "convolve.h"
  31. #include "context.h"
  32. #include "feedback.h"
  33. #include "image.h"
  34. #include "macros.h"
  35. #include "imports.h"
  36. #include "pixel.h"
  37.  
  38. #include "s_alphabuf.h"
  39. #include "s_context.h"
  40. #include "s_depth.h"
  41. #include "s_span.h"
  42. #include "s_stencil.h"
  43.  
  44.  
  45.  
  46. /*
  47.  * Read a block of color index pixels.
  48.  */
  49. static void
  50. read_index_pixels( GLcontext *ctx,
  51.                    GLint x, GLint y,
  52.                    GLsizei width, GLsizei height,
  53.                    GLenum type, GLvoid *pixels,
  54.                    const struct gl_pixelstore_attrib *packing )
  55. {
  56.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  57.    GLint i, readWidth;
  58.  
  59.    /* error checking */
  60.    if (ctx->Visual.rgbMode) {
  61.       _mesa_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
  62.       return;
  63.    }
  64.  
  65.    _swrast_use_read_buffer(ctx);
  66.  
  67.    readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
  68.  
  69.    /* process image row by row */
  70.    for (i = 0; i < height; i++) {
  71.       GLuint index[MAX_WIDTH];
  72.       GLvoid *dest;
  73.  
  74.       (*swrast->Driver.ReadCI32Span)(ctx, readWidth, x, y + i, index);
  75.  
  76.       dest = _mesa_image_address(packing, pixels, width, height,
  77.                                  GL_COLOR_INDEX, type, 0, i, 0);
  78.  
  79.       _mesa_pack_index_span(ctx, readWidth, type, dest, index,
  80.                             &ctx->Pack, ctx->_ImageTransferState);
  81.    }
  82.  
  83.    _swrast_use_draw_buffer(ctx);
  84. }
  85.  
  86.  
  87.  
  88. static void
  89. read_depth_pixels( GLcontext *ctx,
  90.                    GLint x, GLint y,
  91.                    GLsizei width, GLsizei height,
  92.                    GLenum type, GLvoid *pixels,
  93.                    const struct gl_pixelstore_attrib *packing )
  94. {
  95.    GLint readWidth;
  96.    GLboolean bias_or_scale;
  97.  
  98.    /* Error checking */
  99.    if (ctx->Visual.depthBits <= 0) {
  100.       /* No depth buffer */
  101.       _mesa_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
  102.       return;
  103.    }
  104.  
  105.    readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
  106.  
  107.    if (type != GL_BYTE &&
  108.        type != GL_UNSIGNED_BYTE &&
  109.        type != GL_SHORT &&
  110.        type != GL_UNSIGNED_SHORT &&
  111.        type != GL_INT &&
  112.        type != GL_UNSIGNED_INT &&
  113.        type != GL_FLOAT) {
  114.       _mesa_error( ctx, GL_INVALID_OPERATION, "glReadPixels(depth type)");
  115.       return;
  116.    }
  117.  
  118.    bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
  119.  
  120.    if (type==GL_UNSIGNED_SHORT && ctx->Visual.depthBits == 16
  121.        && !bias_or_scale && !packing->SwapBytes) {
  122.       /* Special case: directly read 16-bit unsigned depth values. */
  123.       GLint j;
  124.       for (j=0;j<height;j++,y++) {
  125.          GLdepth depth[MAX_WIDTH];
  126.          GLushort *dst = (GLushort*) _mesa_image_address( packing, pixels,
  127.                          width, height, GL_DEPTH_COMPONENT, type, 0, j, 0 );
  128.          GLint i;
  129.          _mesa_read_depth_span(ctx, width, x, y, depth);
  130.          for (i = 0; i < width; i++)
  131.             dst[i] = depth[i];
  132.       }
  133.    }
  134.    else if (type==GL_UNSIGNED_INT && ctx->Visual.depthBits == 32
  135.             && !bias_or_scale && !packing->SwapBytes) {
  136.       /* Special case: directly read 32-bit unsigned depth values. */
  137.       GLint j;
  138.       for (j=0;j<height;j++,y++) {
  139.          GLdepth *dst = (GLdepth *) _mesa_image_address( packing, pixels,
  140.                          width, height, GL_DEPTH_COMPONENT, type, 0, j, 0 );
  141.          _mesa_read_depth_span(ctx, width, x, y, dst);
  142.       }
  143.    }
  144.    else {
  145.       /* General case (slower) */
  146.       GLint j;
  147.       for (j=0;j<height;j++,y++) {
  148.          GLfloat depth[MAX_WIDTH];
  149.          GLvoid *dest;
  150.  
  151.          _mesa_read_depth_span_float(ctx, readWidth, x, y, depth);
  152.  
  153.          dest = _mesa_image_address(packing, pixels, width, height,
  154.                                     GL_DEPTH_COMPONENT, type, 0, j, 0);
  155.  
  156.          _mesa_pack_depth_span(ctx, readWidth, (GLdepth *) dest, type,
  157.                                depth, &ctx->Pack);
  158.       }
  159.    }
  160. }
  161.  
  162.  
  163.  
  164. static void
  165. read_stencil_pixels( GLcontext *ctx,
  166.                      GLint x, GLint y,
  167.                      GLsizei width, GLsizei height,
  168.                      GLenum type, GLvoid *pixels,
  169.                      const struct gl_pixelstore_attrib *packing )
  170. {
  171.    GLint j, readWidth;
  172.  
  173.    if (type != GL_BYTE &&
  174.        type != GL_UNSIGNED_BYTE &&
  175.        type != GL_SHORT &&
  176.        type != GL_UNSIGNED_SHORT &&
  177.        type != GL_INT &&
  178.        type != GL_UNSIGNED_INT &&
  179.        type != GL_FLOAT &&
  180.        type != GL_BITMAP) {
  181.       _mesa_error( ctx, GL_INVALID_OPERATION, "glReadPixels(stencil type)");
  182.       return;
  183.    }
  184.  
  185.    readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
  186.  
  187.    if (ctx->Visual.stencilBits <= 0) {
  188.       /* No stencil buffer */
  189.       _mesa_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
  190.       return;
  191.    }
  192.  
  193.    /* process image row by row */
  194.    for (j=0;j<height;j++,y++) {
  195.       GLvoid *dest;
  196.       GLstencil stencil[MAX_WIDTH];
  197.  
  198.       _mesa_read_stencil_span(ctx, readWidth, x, y, stencil);
  199.  
  200.       dest = _mesa_image_address(packing, pixels, width, height,
  201.                                  GL_STENCIL_INDEX, type, 0, j, 0);
  202.  
  203.       _mesa_pack_stencil_span(ctx, readWidth, type, dest, stencil, &ctx->Pack);
  204.    }
  205. }
  206.  
  207.  
  208.  
  209. /*
  210.  * Optimized glReadPixels for particular pixel formats:
  211.  *   GL_UNSIGNED_BYTE, GL_RGBA
  212.  * when pixel scaling, biasing and mapping are disabled.
  213.  */
  214. static GLboolean
  215. read_fast_rgba_pixels( GLcontext *ctx,
  216.                        GLint x, GLint y,
  217.                        GLsizei width, GLsizei height,
  218.                        GLenum format, GLenum type,
  219.                        GLvoid *pixels,
  220.                        const struct gl_pixelstore_attrib *packing )
  221. {
  222.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  223.    /* can't do scale, bias, mapping, etc */
  224.    if (ctx->_ImageTransferState)
  225.        return GL_FALSE;
  226.  
  227.    /* can't do fancy pixel packing */
  228.    if (packing->Alignment != 1 || packing->SwapBytes || packing->LsbFirst)
  229.       return GL_FALSE;
  230.  
  231.    {
  232.       GLint srcX = x;
  233.       GLint srcY = y;
  234.       GLint readWidth = width;           /* actual width read */
  235.       GLint readHeight = height;         /* actual height read */
  236.       GLint skipPixels = packing->SkipPixels;
  237.       GLint skipRows = packing->SkipRows;
  238.       GLint rowLength;
  239.  
  240.       if (packing->RowLength > 0)
  241.          rowLength = packing->RowLength;
  242.       else
  243.          rowLength = width;
  244.  
  245.       /* horizontal clipping */
  246.       if (srcX < 0) {
  247.          skipPixels -= srcX;
  248.          readWidth += srcX;
  249.          srcX = 0;
  250.       }
  251.       if (srcX + readWidth > (GLint) ctx->ReadBuffer->Width)
  252.          readWidth -= (srcX + readWidth - (GLint) ctx->ReadBuffer->Width);
  253.       if (readWidth <= 0)
  254.          return GL_TRUE;
  255.  
  256.       /* vertical clipping */
  257.       if (srcY < 0) {
  258.          skipRows -= srcY;
  259.          readHeight += srcY;
  260.          srcY = 0;
  261.       }
  262.       if (srcY + readHeight > (GLint) ctx->ReadBuffer->Height)
  263.          readHeight -= (srcY + readHeight - (GLint) ctx->ReadBuffer->Height);
  264.       if (readHeight <= 0)
  265.          return GL_TRUE;
  266.  
  267.       /*
  268.        * Ready to read!
  269.        * The window region at (destX, destY) of size (readWidth, readHeight)
  270.        * will be read back.
  271.        * We'll write pixel data to buffer pointed to by "pixels" but we'll
  272.        * skip "skipRows" rows and skip "skipPixels" pixels/row.
  273.        */
  274. #if CHAN_BITS == 8
  275.       if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
  276. #elif CHAN_BITS == 16
  277.       if (format == GL_RGBA && type == GL_UNSIGNED_SHORT) {
  278. #else
  279.       if (0) {
  280. #endif
  281.          GLchan *dest = (GLchan *) pixels
  282.                       + (skipRows * rowLength + skipPixels) * 4;
  283.          GLint row;
  284.  
  285.          if (packing->Invert) {
  286.             /* start at top and go down */
  287.             dest += (readHeight - 1) * rowLength * 4;
  288.             rowLength = -rowLength;
  289.          }
  290.  
  291.          for (row=0; row<readHeight; row++) {
  292.             (*swrast->Driver.ReadRGBASpan)(ctx, readWidth, srcX, srcY,
  293.                                         (GLchan (*)[4]) dest);
  294.             if (ctx->DrawBuffer->UseSoftwareAlphaBuffers) {
  295.                _mesa_read_alpha_span(ctx, readWidth, srcX, srcY,
  296.                                      (GLchan (*)[4]) dest);
  297.             }
  298.             dest += rowLength * 4;
  299.             srcY++;
  300.          }
  301.          return GL_TRUE;
  302.       }
  303.       else {
  304.          /* can't do this format/type combination */
  305.          return GL_FALSE;
  306.       }
  307.    }
  308. }
  309.  
  310.  
  311.  
  312. /*
  313.  * Read R, G, B, A, RGB, L, or LA pixels.
  314.  */
  315. static void
  316. read_rgba_pixels( GLcontext *ctx,
  317.                   GLint x, GLint y,
  318.                   GLsizei width, GLsizei height,
  319.                   GLenum format, GLenum type, GLvoid *pixels,
  320.                   const struct gl_pixelstore_attrib *packing )
  321. {
  322.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  323.    GLint readWidth;
  324.  
  325.    _swrast_use_read_buffer(ctx);
  326.  
  327.    /* Try optimized path first */
  328.    if (read_fast_rgba_pixels( ctx, x, y, width, height,
  329.                               format, type, pixels, packing )) {
  330.  
  331.       _swrast_use_draw_buffer(ctx);
  332.       return; /* done! */
  333.    }
  334.  
  335.    readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
  336.  
  337.    /* do error checking on pixel type, format was already checked by caller */
  338.    switch (type) {
  339.       case GL_UNSIGNED_BYTE:
  340.       case GL_BYTE:
  341.       case GL_UNSIGNED_SHORT:
  342.       case GL_SHORT:
  343.       case GL_UNSIGNED_INT:
  344.       case GL_INT:
  345.       case GL_FLOAT:
  346.       case GL_UNSIGNED_BYTE_3_3_2:
  347.       case GL_UNSIGNED_BYTE_2_3_3_REV:
  348.       case GL_UNSIGNED_SHORT_5_6_5:
  349.       case GL_UNSIGNED_SHORT_5_6_5_REV:
  350.       case GL_UNSIGNED_SHORT_4_4_4_4:
  351.       case GL_UNSIGNED_SHORT_4_4_4_4_REV:
  352.       case GL_UNSIGNED_SHORT_5_5_5_1:
  353.       case GL_UNSIGNED_SHORT_1_5_5_5_REV:
  354.       case GL_UNSIGNED_INT_8_8_8_8:
  355.       case GL_UNSIGNED_INT_8_8_8_8_REV:
  356.       case GL_UNSIGNED_INT_10_10_10_2:
  357.       case GL_UNSIGNED_INT_2_10_10_10_REV:
  358.          /* valid pixel type */
  359.          break;
  360.       default:
  361.          _mesa_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
  362.          return;
  363.    }
  364.  
  365.    if (!_mesa_is_legal_format_and_type(format, type) ||
  366.        format == GL_INTENSITY) {
  367.       _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(format or type)");
  368.       return;
  369.    }
  370.  
  371.    if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
  372.       const GLuint transferOps = ctx->_ImageTransferState;
  373.       GLfloat *dest, *src, *tmpImage, *convImage;
  374.       GLint row;
  375.  
  376.       tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
  377.       if (!tmpImage) {
  378.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
  379.          return;
  380.       }
  381.       convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
  382.       if (!convImage) {
  383.          FREE(tmpImage);
  384.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
  385.          return;
  386.       }
  387.  
  388.       /* read full RGBA, FLOAT image */
  389.       dest = tmpImage;
  390.       for (row = 0; row < height; row++, y++) {
  391.          GLchan rgba[MAX_WIDTH][4];
  392.          if (ctx->Visual.rgbMode) {
  393.             _mesa_read_rgba_span(ctx, ctx->ReadBuffer, readWidth, x, y, rgba);
  394.          }
  395.          else {
  396.             GLuint index[MAX_WIDTH];
  397.             (*swrast->Driver.ReadCI32Span)(ctx, readWidth, x, y, index);
  398.             if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset !=0 ) {
  399.                _mesa_map_ci(ctx, readWidth, index);
  400.             }
  401.             _mesa_map_ci_to_rgba_chan(ctx, readWidth, index, rgba);
  402.          }
  403.          _mesa_pack_rgba_span(ctx, readWidth, (const GLchan (*)[4]) rgba,
  404.                               GL_RGBA, GL_FLOAT, dest, &_mesa_native_packing,
  405.                               transferOps & IMAGE_PRE_CONVOLUTION_BITS);
  406.          dest += width * 4;
  407.       }
  408.  
  409.       /* do convolution */
  410.       if (ctx->Pixel.Convolution2DEnabled) {
  411.          _mesa_convolve_2d_image(ctx, &readWidth, &height, tmpImage, convImage);
  412.       }
  413.       else {
  414.          ASSERT(ctx->Pixel.Separable2DEnabled);
  415.          _mesa_convolve_sep_image(ctx, &readWidth, &height, tmpImage, convImage);
  416.       }
  417.       FREE(tmpImage);
  418.  
  419.       /* finish transfer ops and pack the resulting image */
  420.       src = convImage;
  421.       for (row = 0; row < height; row++) {
  422.          GLvoid *dest;
  423.          dest = _mesa_image_address(packing, pixels, readWidth, height,
  424.                                     format, type, 0, row, 0);
  425.          _mesa_pack_float_rgba_span(ctx, readWidth,
  426.                                     (const GLfloat (*)[4]) src,
  427.                                     format, type, dest, packing,
  428.                                     transferOps & IMAGE_POST_CONVOLUTION_BITS);
  429.          src += readWidth * 4;
  430.       }
  431.    }
  432.    else {
  433.       /* no convolution */
  434.       GLint row;
  435.       for (row = 0; row < height; row++, y++) {
  436.          GLchan rgba[MAX_WIDTH][4];
  437.          GLvoid *dst;
  438.          if (ctx->Visual.rgbMode) {
  439.             _mesa_read_rgba_span(ctx, ctx->ReadBuffer, readWidth, x, y, rgba);
  440.          }
  441.          else {
  442.             GLuint index[MAX_WIDTH];
  443.             (*swrast->Driver.ReadCI32Span)(ctx, readWidth, x, y, index);
  444.             if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) {
  445.                _mesa_map_ci(ctx, readWidth, index);
  446.             }
  447.             _mesa_map_ci_to_rgba_chan(ctx, readWidth, index, rgba);
  448.          }
  449.          dst = _mesa_image_address(packing, pixels, width, height,
  450.                                    format, type, 0, row, 0);
  451.          if (ctx->Visual.redBits < CHAN_BITS ||
  452.              ctx->Visual.greenBits < CHAN_BITS ||
  453.              ctx->Visual.blueBits < CHAN_BITS) {
  454.             /* Requantize the color values into floating point and go from
  455.              * there.  This fixes conformance failures with 16-bit color
  456.              * buffers, for example.
  457.              */
  458.             DEFMARRAY(GLfloat, rgbaf, MAX_WIDTH, 4);  /* mac 32k limitation */
  459.             CHECKARRAY(rgbaf, return);  /* mac 32k limitation */
  460.             _mesa_chan_to_float_span(ctx, readWidth,
  461.                                      (CONST GLchan (*)[4]) rgba, rgbaf);
  462.             _mesa_pack_float_rgba_span(ctx, readWidth,
  463.                                        (CONST GLfloat (*)[4]) rgbaf,
  464.                                        format, type, dst, packing,
  465.                                        ctx->_ImageTransferState);
  466.             UNDEFARRAY(rgbaf);  /* mac 32k limitation */
  467.          }
  468.          else {
  469.             /* GLubytes are fine */
  470.             _mesa_pack_rgba_span(ctx, readWidth, (CONST GLchan (*)[4]) rgba,
  471.                                  format, type, dst, packing,
  472.                                  ctx->_ImageTransferState);
  473.          }
  474.       }
  475.    }
  476.  
  477.    _swrast_use_draw_buffer(ctx);
  478. }
  479.  
  480.  
  481.  
  482. void
  483. _swrast_ReadPixels( GLcontext *ctx,
  484.             GLint x, GLint y, GLsizei width, GLsizei height,
  485.             GLenum format, GLenum type,
  486.             const struct gl_pixelstore_attrib *pack,
  487.             GLvoid *pixels )
  488. {
  489.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  490.    (void) pack;
  491.  
  492.    if (swrast->NewState)
  493.       _swrast_validate_derived( ctx );
  494.  
  495.    RENDER_START(swrast,ctx);
  496.  
  497.    switch (format) {
  498.       case GL_COLOR_INDEX:
  499.          read_index_pixels(ctx, x, y, width, height, type, pixels, &ctx->Pack);
  500.      break;
  501.       case GL_STENCIL_INDEX:
  502.      read_stencil_pixels(ctx, x,y, width,height, type, pixels, &ctx->Pack);
  503.          break;
  504.       case GL_DEPTH_COMPONENT:
  505.      read_depth_pixels(ctx, x, y, width, height, type, pixels, &ctx->Pack);
  506.      break;
  507.       case GL_RED:
  508.       case GL_GREEN:
  509.       case GL_BLUE:
  510.       case GL_ALPHA:
  511.       case GL_RGB:
  512.       case GL_LUMINANCE:
  513.       case GL_LUMINANCE_ALPHA:
  514.       case GL_RGBA:
  515.       case GL_BGR:
  516.       case GL_BGRA:
  517.       case GL_ABGR_EXT:
  518.          read_rgba_pixels(ctx, x, y, width, height,
  519.                           format, type, pixels, &ctx->Pack);
  520.      break;
  521.       default:
  522.      _mesa_error( ctx, GL_INVALID_ENUM, "glReadPixels(format)" );
  523.    }
  524.  
  525.    RENDER_FINISH(swrast,ctx);
  526. }
  527.