[cogl] Use MESA_pack_invert to avoid read_pixels flip



commit 6f79eb8a5a530fc2fd0a9aed90da172fbf05f742
Author: Robert Bragg <robert linux intel com>
Date:   Wed Jul 13 18:28:49 2011 +0100

    Use MESA_pack_invert to avoid read_pixels flip
    
    cogl_read_pixels returns image data in a top-down memory order, but
    because OpenGL normally returns pixel data in a bottom-up order we
    have to flip the data before returning it to the user. If the OpenGL
    driver supports the GL_MESA_pack_invert extension though we can ask the
    driver to return the data in a top-down order in the first place.
    
    Signed-off-by: Neil Roberts <neil linux intel com>

 cogl/cogl-internal.h     |    1 +
 cogl/cogl.c              |   27 +++++++++++++++++++++++----
 cogl/driver/gl/cogl-gl.c |    3 +++
 3 files changed, 27 insertions(+), 4 deletions(-)
---
diff --git a/cogl/cogl-internal.h b/cogl/cogl-internal.h
index 022ea32..ca9e395 100644
--- a/cogl/cogl-internal.h
+++ b/cogl/cogl-internal.h
@@ -138,6 +138,7 @@ typedef enum
 typedef enum
 {
   COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE = 1L<<0,
+  COGL_PRIVATE_FEATURE_MESA_PACK_INVERT = 1L<<1
 } CoglPrivateFeatureFlags;
 
 gboolean
diff --git a/cogl/cogl.c b/cogl/cogl.c
index 7b2990e..15b9148 100644
--- a/cogl/cogl.c
+++ b/cogl/cogl.c
@@ -47,6 +47,10 @@
 #include "cogl-attribute-private.h"
 #include "cogl-framebuffer-private.h"
 
+#ifndef GL_PACK_INVERT_MESA
+#define GL_PACK_INVERT_MESA 0x8758
+#endif
+
 #ifdef COGL_GL_DEBUG
 /* GL error to string conversion */
 static const struct {
@@ -474,6 +478,7 @@ _cogl_read_pixels_with_rowstride (int x,
   GLenum           gl_format;
   GLenum           gl_type;
   CoglPixelFormat  bmp_format;
+  gboolean         pack_invert_set;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
@@ -546,6 +551,17 @@ _cogl_read_pixels_with_rowstride (int x,
                                            &gl_format,
                                            &gl_type);
 
+  /* NB: All offscreen rendering is done upside down so there is no need
+   * to flip in this case... */
+  if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_MESA_PACK_INVERT) &&
+      !cogl_is_offscreen (framebuffer))
+    {
+      GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, TRUE));
+      pack_invert_set = TRUE;
+    }
+  else
+    pack_invert_set = FALSE;
+
   /* Under GLES only GL_RGBA with GL_UNSIGNED_BYTE as well as an
      implementation specific format under
      GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES and
@@ -609,15 +625,18 @@ _cogl_read_pixels_with_rowstride (int x,
       _cogl_bitmap_convert_premult_status (bmp, format);
     }
 
+  /* Currently this function owns the pack_invert state and we don't want this
+   * to interfere with other Cogl components so all other code can assume that
+   * we leave the pack_invert state off. */
+  if (pack_invert_set)
+    GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, FALSE));
+
   /* NB: All offscreen rendering is done upside down so there is no need
    * to flip in this case... */
-  if (!cogl_is_offscreen (framebuffer))
+  if (!cogl_is_offscreen (framebuffer) && !pack_invert_set)
     {
       guint8 *temprow = g_alloca (rowstride * sizeof (guint8));
 
-      /* TODO: consider using the GL_MESA_pack_invert extension in the future
-       * to avoid this flip... */
-
       /* vertically flip the buffer in-place */
       for (y = 0; y < height / 2; y++)
         {
diff --git a/cogl/driver/gl/cogl-gl.c b/cogl/driver/gl/cogl-gl.c
index e2c1a3c..389908f 100644
--- a/cogl/driver/gl/cogl-gl.c
+++ b/cogl/driver/gl/cogl-gl.c
@@ -183,6 +183,9 @@ _cogl_gl_update_features (CoglContext *context)
     }
 #endif
 
+  if (_cogl_check_extension ("GL_MESA_pack_invert", gl_extensions))
+    private_flags |= COGL_PRIVATE_FEATURE_MESA_PACK_INVERT;
+
   GE( ctx, glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
   /* We need at least three stencil bits to combine clips */
   if (num_stencil_bits > 2)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]