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>
This commit is contained in:
parent
1527b017c5
commit
6f79eb8a5a
@ -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
|
||||
|
27
cogl/cogl.c
27
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++)
|
||||
{
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user