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-2008  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. #include "glheader.h"
  26. #include "imports.h"
  27. #include "bufferobj.h"
  28. #include "context.h"
  29. #include "readpix.h"
  30. #include "framebuffer.h"
  31. #include "formats.h"
  32. #include "image.h"
  33. #include "state.h"
  34.  
  35.  
  36. /**
  37.  * Do error checking of the format/type parameters to glReadPixels and
  38.  * glDrawPixels.
  39.  * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
  40.  *                for ReadPixels.
  41.  * \return GL_TRUE if error detected, GL_FALSE if no errors
  42.  */
  43. GLboolean
  44. _mesa_error_check_format_type(struct gl_context *ctx, GLenum format, GLenum type,
  45.                               GLboolean drawing)
  46. {
  47.    const char *readDraw = drawing ? "Draw" : "Read";
  48.    const GLboolean reading = !drawing;
  49.  
  50.    /* state validation should have already been done */
  51.    ASSERT(ctx->NewState == 0x0);
  52.  
  53.    if (ctx->Extensions.EXT_packed_depth_stencil
  54.        && type == GL_UNSIGNED_INT_24_8_EXT
  55.        && format != GL_DEPTH_STENCIL_EXT) {
  56.       _mesa_error(ctx, GL_INVALID_OPERATION,
  57.                   "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw);
  58.       return GL_TRUE;
  59.    }
  60.  
  61.    /* basic combinations test */
  62.    if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
  63.       _mesa_error(ctx, GL_INVALID_ENUM,
  64.                   "gl%sPixels(format or type)", readDraw);
  65.       return GL_TRUE;
  66.    }
  67.  
  68.    /* additional checks */
  69.    switch (format) {
  70.    case GL_RG:
  71.    case GL_RED:
  72.    case GL_GREEN:
  73.    case GL_BLUE:
  74.    case GL_ALPHA:
  75.    case GL_LUMINANCE:
  76.    case GL_LUMINANCE_ALPHA:
  77.    case GL_RGB:
  78.    case GL_BGR:
  79.    case GL_RGBA:
  80.    case GL_BGRA:
  81.    case GL_ABGR_EXT:
  82.    case GL_RED_INTEGER_EXT:
  83.    case GL_GREEN_INTEGER_EXT:
  84.    case GL_BLUE_INTEGER_EXT:
  85.    case GL_ALPHA_INTEGER_EXT:
  86.    case GL_RGB_INTEGER_EXT:
  87.    case GL_RGBA_INTEGER_EXT:
  88.    case GL_BGR_INTEGER_EXT:
  89.    case GL_BGRA_INTEGER_EXT:
  90.    case GL_LUMINANCE_INTEGER_EXT:
  91.    case GL_LUMINANCE_ALPHA_INTEGER_EXT:
  92.       if (!drawing) {
  93.          /* reading */
  94.          if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
  95.             _mesa_error(ctx, GL_INVALID_OPERATION,
  96.                         "glReadPixels(no color buffer)");
  97.             return GL_TRUE;
  98.          }
  99.       }
  100.       break;
  101.    case GL_COLOR_INDEX:
  102.       if (drawing) {
  103.          if (ctx->PixelMaps.ItoR.Size == 0 ||
  104.              ctx->PixelMaps.ItoG.Size == 0 ||
  105.              ctx->PixelMaps.ItoB.Size == 0) {
  106.             _mesa_error(ctx, GL_INVALID_OPERATION,
  107.                    "glDrawPixels(drawing color index pixels into RGB buffer)");
  108.             return GL_TRUE;
  109.          }
  110.       }
  111.       else {
  112.          /* reading */
  113.          if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
  114.             _mesa_error(ctx, GL_INVALID_OPERATION,
  115.                         "glReadPixels(no color buffer)");
  116.             return GL_TRUE;
  117.          }
  118.          /* We no longer support CI-mode color buffers so trying to read
  119.           * GL_COLOR_INDEX pixels is always an error.
  120.           */
  121.          _mesa_error(ctx, GL_INVALID_OPERATION,
  122.                      "glReadPixels(color buffer is RGB)");
  123.          return GL_TRUE;
  124.       }
  125.       break;
  126.    case GL_STENCIL_INDEX:
  127.       if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
  128.           (reading && !_mesa_source_buffer_exists(ctx, format))) {
  129.          _mesa_error(ctx, GL_INVALID_OPERATION,
  130.                      "gl%sPixels(no stencil buffer)", readDraw);
  131.          return GL_TRUE;
  132.       }
  133.       break;
  134.    case GL_DEPTH_COMPONENT:
  135.       if ((drawing && !_mesa_dest_buffer_exists(ctx, format))) {
  136.          _mesa_error(ctx, GL_INVALID_OPERATION,
  137.                      "gl%sPixels(no depth buffer)", readDraw);
  138.          return GL_TRUE;
  139.       }
  140.       break;
  141.    case GL_DEPTH_STENCIL_EXT:
  142.       if (!ctx->Extensions.EXT_packed_depth_stencil ||
  143.           type != GL_UNSIGNED_INT_24_8_EXT) {
  144.          _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
  145.          return GL_TRUE;
  146.       }
  147.       if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
  148.           (reading && !_mesa_source_buffer_exists(ctx, format))) {
  149.          _mesa_error(ctx, GL_INVALID_OPERATION,
  150.                      "gl%sPixels(no depth or stencil buffer)", readDraw);
  151.          return GL_TRUE;
  152.       }
  153.       break;
  154.    default:
  155.       /* this should have been caught in _mesa_is_legal_format_type() */
  156.       _mesa_problem(ctx, "unexpected format in _mesa_%sPixels", readDraw);
  157.       return GL_TRUE;
  158.    }
  159.  
  160.    /* no errors */
  161.    return GL_FALSE;
  162. }
  163.      
  164.  
  165.  
  166. void GLAPIENTRY
  167. _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
  168.                   GLenum format, GLenum type, GLvoid *pixels )
  169. {
  170.    GET_CURRENT_CONTEXT(ctx);
  171.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  172.  
  173.    FLUSH_CURRENT(ctx, 0);
  174.  
  175.    if (width < 0 || height < 0) {
  176.       _mesa_error( ctx, GL_INVALID_VALUE,
  177.                    "glReadPixels(width=%d height=%d)", width, height );
  178.       return;
  179.    }
  180.  
  181.    if (ctx->NewState)
  182.       _mesa_update_state(ctx);
  183.  
  184.    if (_mesa_error_check_format_type(ctx, format, type, GL_FALSE)) {
  185.       /* found an error */
  186.       return;
  187.    }
  188.  
  189.    /* Check that the destination format and source buffer are both
  190.     * integer-valued or both non-integer-valued.
  191.     */
  192.    if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
  193.       const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
  194.       const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
  195.       const GLboolean dstInteger = _mesa_is_integer_format(format);
  196.       if (dstInteger != srcInteger) {
  197.          _mesa_error(ctx, GL_INVALID_OPERATION,
  198.                      "glReadPixels(integer / non-integer format mismatch");
  199.          return;
  200.       }
  201.    }
  202.  
  203.    if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
  204.       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
  205.                   "glReadPixels(incomplete framebuffer)" );
  206.       return;
  207.    }
  208.  
  209.    if (!_mesa_source_buffer_exists(ctx, format)) {
  210.       _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
  211.       return;
  212.    }
  213.  
  214.    if (width == 0 || height == 0)
  215.       return; /* nothing to do */
  216.  
  217.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  218.       if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
  219.                                      format, type, pixels)) {
  220.          _mesa_error(ctx, GL_INVALID_OPERATION,
  221.                      "glReadPixels(invalid PBO access)");
  222.          return;
  223.       }
  224.  
  225.       if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
  226.          /* buffer is mapped - that's an error */
  227.          _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
  228.          return;
  229.       }
  230.    }
  231.  
  232.    ctx->Driver.ReadPixels(ctx, x, y, width, height,
  233.                           format, type, &ctx->Pack, pixels);
  234. }
  235.