summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2011-07-13 18:28:49 +0100
committerRobert Bragg <robert@linux.intel.com>2011-07-13 19:06:19 +0100
commit6f79eb8a5a530fc2fd0a9aed90da172fbf05f742 (patch)
treee4be3c78e077fb1c1675422238fe1ce17970db76
parent1527b017c51d5c91cec117f626a916ffbd3ae570 (diff)
downloadcogl-6f79eb8a5a530fc2fd0a9aed90da172fbf05f742.tar.gz
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>
-rw-r--r--cogl/cogl-internal.h1
-rw-r--r--cogl/cogl.c27
-rw-r--r--cogl/driver/gl/cogl-gl.c3
3 files changed, 27 insertions, 4 deletions
diff --git a/cogl/cogl-internal.h b/cogl/cogl-internal.h
index 022ea32a..ca9e3958 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 7b2990ec..15b91489 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 e2c1a3ce..389908fc 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)