mesa: move PBO-related functions into a new file
[mesa.git] / src / mesa / main / readpix.c
index dfdd297b6e715ed7561b339b89e0a41193dfb7f7..6e09a52c88a1614423d0943ae7ecd4ee323b7dc8 100644 (file)
 #include "imports.h"
 #include "bufferobj.h"
 #include "context.h"
+#include "enums.h"
 #include "readpix.h"
 #include "framebuffer.h"
+#include "formats.h"
 #include "image.h"
+#include "mtypes.h"
+#include "pbo.h"
 #include "state.h"
 
 
  * \return GL_TRUE if error detected, GL_FALSE if no errors
  */
 GLboolean
-_mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
+_mesa_error_check_format_type(struct gl_context *ctx, GLenum format, GLenum type,
                               GLboolean drawing)
 {
    const char *readDraw = drawing ? "Draw" : "Read";
+   const GLboolean reading = !drawing;
+
+   /* state validation should have already been done */
+   ASSERT(ctx->NewState == 0x0);
 
    if (ctx->Extensions.EXT_packed_depth_stencil
        && type == GL_UNSIGNED_INT_24_8_EXT
@@ -62,6 +70,7 @@ _mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
 
    /* additional checks */
    switch (format) {
+   case GL_RG:
    case GL_RED:
    case GL_GREEN:
    case GL_BLUE:
@@ -73,32 +82,53 @@ _mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
    case GL_RGBA:
    case GL_BGRA:
    case GL_ABGR_EXT:
-      if (drawing && !ctx->Visual.rgbMode) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                   "glDrawPixels(drawing RGB pixels into color index buffer)");
-         return GL_TRUE;
-      }
-      if (!drawing && !_mesa_dest_buffer_exists(ctx, GL_COLOR)) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glReadPixels(no color buffer)");
-         return GL_TRUE;
+   case GL_RED_INTEGER_EXT:
+   case GL_GREEN_INTEGER_EXT:
+   case GL_BLUE_INTEGER_EXT:
+   case GL_ALPHA_INTEGER_EXT:
+   case GL_RGB_INTEGER_EXT:
+   case GL_RGBA_INTEGER_EXT:
+   case GL_BGR_INTEGER_EXT:
+   case GL_BGRA_INTEGER_EXT:
+   case GL_LUMINANCE_INTEGER_EXT:
+   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
+      if (!drawing) {
+         /* reading */
+         if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glReadPixels(no color buffer)");
+            return GL_TRUE;
+         }
       }
       break;
    case GL_COLOR_INDEX:
-      if (!drawing && ctx->Visual.rgbMode) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                    "glReadPixels(reading color index format from RGB buffer)");
-         return GL_TRUE;
+      if (drawing) {
+         if (ctx->PixelMaps.ItoR.Size == 0 ||
+            ctx->PixelMaps.ItoG.Size == 0 ||
+            ctx->PixelMaps.ItoB.Size == 0) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                   "glDrawPixels(drawing color index pixels into RGB buffer)");
+            return GL_TRUE;
+         }
       }
-      if (!drawing && !_mesa_dest_buffer_exists(ctx, GL_COLOR)) {
+      else {
+         /* reading */
+         if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glReadPixels(no color buffer)");
+            return GL_TRUE;
+         }
+         /* We no longer support CI-mode color buffers so trying to read
+          * GL_COLOR_INDEX pixels is always an error.
+          */
          _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glReadPixels(no color buffer)");
+                     "glReadPixels(color buffer is RGB)");
          return GL_TRUE;
       }
       break;
    case GL_STENCIL_INDEX:
       if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
-          (!drawing && !_mesa_source_buffer_exists(ctx, format))) {
+          (reading && !_mesa_source_buffer_exists(ctx, format))) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "gl%sPixels(no stencil buffer)", readDraw);
          return GL_TRUE;
@@ -118,7 +148,7 @@ _mesa_error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
          return GL_TRUE;
       }
       if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
-          (!drawing && !_mesa_source_buffer_exists(ctx, format))) {
+          (reading && !_mesa_source_buffer_exists(ctx, format))) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "gl%sPixels(no depth or stencil buffer)", readDraw);
          return GL_TRUE;
@@ -145,6 +175,13 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
 
    FLUSH_CURRENT(ctx, 0);
 
+   if (MESA_VERBOSE & VERBOSE_API)
+      _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
+                  width, height,
+                  _mesa_lookup_enum_by_nr(format),
+                  _mesa_lookup_enum_by_nr(type),
+                  pixels);
+
    if (width < 0 || height < 0) {
       _mesa_error( ctx, GL_INVALID_VALUE,
                    "glReadPixels(width=%d height=%d)", width, height );
@@ -159,6 +196,20 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
       return;
    }
 
+   /* Check that the destination format and source buffer are both
+    * integer-valued or both non-integer-valued.
+    */
+   if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
+      const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
+      const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
+      const GLboolean dstInteger = _mesa_is_integer_format(format);
+      if (dstInteger != srcInteger) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glReadPixels(integer / non-integer format mismatch");
+         return;
+      }
+   }
+
    if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                   "glReadPixels(incomplete framebuffer)" );
@@ -170,7 +221,10 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
       return;
    }
 
-   if (ctx->Pack.BufferObj->Name) {
+   if (width == 0 || height == 0)
+      return; /* nothing to do */
+
+   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
       if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
                                      format, type, pixels)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
@@ -178,7 +232,7 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
          return;
       }
 
-      if (ctx->Pack.BufferObj->Pointer) {
+      if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
          /* buffer is mapped - that's an error */
          _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
          return;