mesa: add read_pixels() helper
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Tue, 18 Jul 2017 15:26:34 +0000 (17:26 +0200)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Mon, 31 Jul 2017 11:53:39 +0000 (13:53 +0200)
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
src/mesa/main/readpix.c

index 606d1e58e5af8213461082fda013890acae16649..72aa6a3f31531b4bbf5bcf8d02970b96aa28a9e6 100644 (file)
@@ -984,10 +984,9 @@ read_pixels_es3_error_check(GLenum format, GLenum type,
 }
 
 
-void GLAPIENTRY
-_mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
-                     GLenum format, GLenum type, GLsizei bufSize,
-                      GLvoid *pixels )
+static ALWAYS_INLINE void
+read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
+            GLenum type, GLsizei bufSize, GLvoid *pixels, bool no_error)
 {
    GLenum err = GL_NO_ERROR;
    struct gl_renderbuffer *rb;
@@ -1005,7 +1004,7 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
                   _mesa_enum_to_string(type),
                   pixels);
 
-   if (width < 0 || height < 0) {
+   if (!no_error && (width < 0 || height < 0)) {
       _mesa_error( ctx, GL_INVALID_VALUE,
                    "glReadPixels(width=%d height=%d)", width, height );
       return;
@@ -1014,83 +1013,85 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
-   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+   if (!no_error && ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                   "glReadPixels(incomplete framebuffer)" );
       return;
    }
 
    rb = _mesa_get_read_renderbuffer_for_format(ctx, format);
-   if (rb == NULL) {
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glReadPixels(read buffer)");
-      return;
-   }
+   if (!no_error) {
+      if (rb == NULL) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glReadPixels(read buffer)");
+         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)) {
-      if (ctx->API == API_OPENGLES2 &&
-          _mesa_is_color_format(format) &&
-          _mesa_get_color_read_format(ctx, NULL, "glReadPixels") == format &&
-          _mesa_get_color_read_type(ctx, NULL, "glReadPixels") == type) {
-         err = GL_NO_ERROR;
-      } else if (ctx->Version < 30) {
-         err = _mesa_es_error_check_format_and_type(ctx, format, type, 2);
-         if (err == GL_NO_ERROR) {
-            if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
-               err = GL_INVALID_OPERATION;
+      /* 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)) {
+         if (ctx->API == API_OPENGLES2 &&
+             _mesa_is_color_format(format) &&
+             _mesa_get_color_read_format(ctx, NULL, "glReadPixels") == format &&
+             _mesa_get_color_read_type(ctx, NULL, "glReadPixels") == type) {
+            err = GL_NO_ERROR;
+         } else if (ctx->Version < 30) {
+            err = _mesa_es_error_check_format_and_type(ctx, format, type, 2);
+            if (err == GL_NO_ERROR) {
+               if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
+                  err = GL_INVALID_OPERATION;
+               }
             }
+         } else {
+            err = read_pixels_es3_error_check(format, type, rb);
+         }
+
+         if (err != GL_NO_ERROR) {
+            _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
+                        _mesa_enum_to_string(format),
+                        _mesa_enum_to_string(type));
+            return;
          }
-      } else {
-         err = read_pixels_es3_error_check(format, type, rb);
       }
 
+      err = _mesa_error_check_format_and_type(ctx, format, type);
       if (err != GL_NO_ERROR) {
          _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
                      _mesa_enum_to_string(format),
                      _mesa_enum_to_string(type));
          return;
       }
-   }
-
-   err = _mesa_error_check_format_and_type(ctx, format, type);
-   if (err != GL_NO_ERROR) {
-      _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
-                  _mesa_enum_to_string(format),
-                  _mesa_enum_to_string(type));
-      return;
-   }
 
-   if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
-       ctx->ReadBuffer->Visual.samples > 0) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
-      return;
-   }
-
-   if (!_mesa_source_buffer_exists(ctx, format)) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
-      return;
-   }
+      if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
+          ctx->ReadBuffer->Visual.samples > 0) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
+         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_enum_format_integer(format);
-      if (dstInteger != srcInteger) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glReadPixels(integer / non-integer format mismatch");
+      if (!_mesa_source_buffer_exists(ctx, format)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
          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_enum_format_integer(format);
+         if (dstInteger != srcInteger) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glReadPixels(integer / non-integer format mismatch");
+            return;
+         }
+      }
    }
 
    /* Do all needed clipping here, so that we can forget about it later */
@@ -1098,24 +1099,26 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
    if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking))
       return; /* nothing to do */
 
-   if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
-                                  format, type, bufSize, pixels)) {
-      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glReadPixels(out of bounds PBO access)");
-      } else {
-         _mesa_error(ctx, GL_INVALID_OPERATION,
-                     "glReadnPixelsARB(out of bounds access:"
-                     " bufSize (%d) is too small)", bufSize);
+   if (!no_error) {
+      if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
+                                     format, type, bufSize, pixels)) {
+         if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glReadPixels(out of bounds PBO access)");
+         } else {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glReadnPixelsARB(out of bounds access:"
+                        " bufSize (%d) is too small)", bufSize);
+         }
+         return;
       }
-      return;
-   }
 
-   if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
-       _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
-      /* buffer is mapped - that's an error */
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
-      return;
+      if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
+          _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
+         /* buffer is mapped - that's an error */
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
+         return;
+      }
    }
 
    ctx->Driver.ReadPixels(ctx, x, y, width, height,
@@ -1123,8 +1126,16 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
 }
 
 void GLAPIENTRY
-_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
-                 GLenum format, GLenum type, GLvoid *pixels )
+_mesa_ReadnPixelsARB(GLint x, GLint y, GLsizei width, GLsizei height,
+                     GLenum format, GLenum type, GLsizei bufSize,
+                     GLvoid *pixels)
+{
+   read_pixels(x, y, width, height, format, type, bufSize, pixels, false);
+}
+
+void GLAPIENTRY
+_mesa_ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+                 GLenum format, GLenum type, GLvoid *pixels)
 {
    _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
 }