diff options
author | Robert Bragg <robert@linux.intel.com> | 2011-07-13 18:28:49 +0100 |
---|---|---|
committer | Robert Bragg <robert@linux.intel.com> | 2011-07-13 19:06:19 +0100 |
commit | 6f79eb8a5a530fc2fd0a9aed90da172fbf05f742 (patch) | |
tree | e4be3c78e077fb1c1675422238fe1ce17970db76 | |
parent | 1527b017c51d5c91cec117f626a916ffbd3ae570 (diff) | |
download | cogl-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.h | 1 | ||||
-rw-r--r-- | cogl/cogl.c | 27 | ||||
-rw-r--r-- | 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 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) |