mesa: Pass GL context to _mesa_create_save_table
[mesa.git] / src / mesa / main / readpix.c
index 31acfcbf13e4a1c6126406beaca83704bad11b39..f6680c91f44171adacc5df9dd044556e140703b4 100644 (file)
@@ -36,6 +36,8 @@
 #include "pack.h"
 #include "pbo.h"
 #include "state.h"
+#include "glformats.h"
+#include "fbobject.h"
 
 
 /**
@@ -135,7 +137,7 @@ read_depth_pixels( struct gl_context *ctx,
       return;
    }
 
-   depthValues = (GLfloat *) malloc(width * sizeof(GLfloat));
+   depthValues = malloc(width * sizeof(GLfloat));
 
    if (depthValues) {
       /* General case (slower) */
@@ -183,7 +185,7 @@ read_stencil_pixels( struct gl_context *ctx,
       return;
    }
 
-   stencil = (GLubyte *) malloc(width * sizeof(GLubyte));
+   stencil = malloc(width * sizeof(GLubyte));
 
    if (stencil) {
       /* process image row by row */
@@ -320,6 +322,8 @@ slow_read_rgba_pixels( struct gl_context *ctx,
    void *rgba;
    GLubyte *dst, *map;
    int dstStride, stride, j;
+   GLboolean dst_is_integer = _mesa_is_enum_format_integer(format);
+   GLboolean dst_is_uint = _mesa_is_format_unsigned(rbFormat);
 
    dstStride = _mesa_image_row_stride(packing, width, format, type);
    dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
@@ -337,12 +341,17 @@ slow_read_rgba_pixels( struct gl_context *ctx,
       goto done;
 
    for (j = 0; j < height; j++) {
-      if (_mesa_is_integer_format(format)) {
+      if (dst_is_integer) {
         _mesa_unpack_uint_rgba_row(rbFormat, width, map, (GLuint (*)[4]) rgba);
          _mesa_rebase_rgba_uint(width, (GLuint (*)[4]) rgba,
                                 rb->_BaseFormat);
-        _mesa_pack_rgba_span_int(ctx, width, (GLuint (*)[4]) rgba, format,
-                                  type, dst);
+         if (dst_is_uint) {
+            _mesa_pack_rgba_span_from_uints(ctx, width, (GLuint (*)[4]) rgba, format,
+                                            type, dst);
+         } else {
+            _mesa_pack_rgba_span_from_ints(ctx, width, (GLint (*)[4]) rgba, format,
+                                           type, dst);
+         }
       } else {
         _mesa_unpack_rgba_row(rbFormat, width, map, (GLfloat (*)[4]) rgba);
          _mesa_rebase_rgba_float(width, (GLfloat (*)[4]) rgba,
@@ -378,7 +387,7 @@ read_rgba_pixels( struct gl_context *ctx,
       return;
 
    if ((ctx->Color._ClampReadColor == GL_TRUE || type != GL_FLOAT) &&
-       !_mesa_is_integer_format(format)) {
+       !_mesa_is_enum_format_integer(format)) {
       transferOps |= IMAGE_CLAMP_BIT;
    }
 
@@ -471,7 +480,7 @@ fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
       return GL_TRUE;  /* don't bother trying the slow path */
    }
 
-   stencilVals = (GLubyte *) malloc(width * sizeof(GLubyte));
+   stencilVals = malloc(width * sizeof(GLubyte));
 
    if (stencilVals) {
       for (j = 0; j < height; j++) {
@@ -542,8 +551,8 @@ slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
       stencilStride = depthStride;
    }
 
-   stencilVals = (GLubyte *) malloc(width * sizeof(GLubyte));
-   depthVals = (GLfloat *) malloc(width * sizeof(GLfloat));
+   stencilVals = malloc(width * sizeof(GLubyte));
+   depthVals = malloc(width * sizeof(GLfloat));
 
    if (stencilVals && depthVals) {
       for (j = 0; j < height; j++) {
@@ -690,6 +699,33 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
       return;
    }
 
+   /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
+    * combinations of format and type that can be used.
+    *
+    * Technically, only two combinations are actually allowed:
+    * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
+    * preferred combination.  This code doesn't know what that preferred
+    * combination is, and Mesa can handle anything valid.  Just work instead.
+    */
+   if (_mesa_is_gles(ctx) && ctx->Version < 30) {
+      err = _mesa_es_error_check_format_and_type(format, type, 2);
+      if (err == GL_NO_ERROR) {
+         if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
+            err = GL_INVALID_OPERATION;
+         } else if (format == GL_DEPTH_COMPONENT
+                    || format == GL_DEPTH_STENCIL) {
+            err = GL_INVALID_ENUM;
+         }
+      }
+
+      if (err != GL_NO_ERROR) {
+         _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
+                     _mesa_lookup_enum_by_nr(format),
+                     _mesa_lookup_enum_by_nr(type));
+         return;
+      }
+   }
+
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
@@ -701,13 +737,19 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
       return;
    }
 
+   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+                  "glReadPixels(incomplete framebuffer)" );
+      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);
+      const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
       if (dstInteger != srcInteger) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glReadPixels(integer / non-integer format mismatch");
@@ -715,13 +757,8 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
       }
    }
 
-   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
-      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
-                  "glReadPixels(incomplete framebuffer)" );
-      return;
-   }
-
-   if (ctx->ReadBuffer->Name != 0 && ctx->ReadBuffer->Visual.samples > 0) {
+   if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
+       ctx->ReadBuffer->Visual.samples > 0) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
       return;
    }