From 7ad4a269e0c7c02d30ce3a80720ad0c23fd584f6 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Thu, 13 Mar 2014 15:54:58 +0900 Subject: [PATCH] Evas gl_x11: Fix usage of glReadPixels It is not necessary to dynamically link to glReadPixels since this is not an extension. This code wouldn't even work on some devices. Also, the pixels returned are not premultiplied (yeah >_<) And some devices (EGL) don't support GL_BGRA... so glReadPixels would just fail and not fill in the pixels. Conversion is required. --- .../evas/engines/gl_common/evas_gl_common.h | 2 -- .../evas/engines/gl_common/evas_gl_context.c | 3 --- src/modules/evas/engines/gl_x11/evas_engine.c | 24 ++++++++++++++++++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 3f5bab2c91..70db622e32 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -839,8 +839,6 @@ extern void (*glsym_glReleaseShaderCompiler)(void); extern void *(*glsym_glMapBuffer) (GLenum a, GLenum b); extern GLboolean (*glsym_glUnmapBuffer) (GLenum a); -extern void (*glsym_glReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *data); - #ifdef GL_GLES extern void *(*secsym_eglCreateImage) (void *a, void *b, GLenum c, void *d, const int *e); extern unsigned int (*secsym_eglDestroyImage) (void *a, void *b); diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index 000a396190..2e447d9925 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -29,7 +29,6 @@ void *(*glsym_glMapBuffer) (GLenum a, GLenum b) = NULL; GLboolean (*glsym_glUnmapBuffer) (GLenum a) = NULL; void (*glsym_glStartTiling) (GLuint a, GLuint b, GLuint c, GLuint d, GLuint e) = NULL; void (*glsym_glEndTiling) (GLuint a) = NULL; -void (*glsym_glReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *data) = NULL; #ifdef GL_GLES // just used for finding symbols :) @@ -212,8 +211,6 @@ gl_symbols(void) FINDSYM(secsym_eglGetImageAttribSEC, "eglGetImageAttribSEC", secsym_func_uint); #endif - - FINDSYM(glsym_glReadPixels, "glReadPixels", glsym_func_void); } static void shader_array_flush(Evas_Engine_GL_Context *gc); diff --git a/src/modules/evas/engines/gl_x11/evas_engine.c b/src/modules/evas/engines/gl_x11/evas_engine.c index 96d2726d85..82ffd05a56 100644 --- a/src/modules/evas/engines/gl_x11/evas_engine.c +++ b/src/modules/evas/engines/gl_x11/evas_engine.c @@ -3435,9 +3435,31 @@ eng_gl_surface_read_pixels(void *data, void *surface, # endif #endif + /* Since this is an FBO, the pixels are already in the right Y order. + * But some devices don't support GL_BGRA, so we still need to convert. + */ + glsym_glBindFramebuffer(GL_FRAMEBUFFER, im->tex->pt->fb); - glsym_glReadPixels(x, y, w, h, GL_BGRA, GL_UNSIGNED_BYTE, pixels); + if (im->tex->pt->format == GL_BGRA) + glReadPixels(x, y, w, h, GL_BGRA, GL_UNSIGNED_BYTE, pixels); + else + { + DATA32 *ptr = pixels; + int k; + + glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + for (k = w * h; k; --k) + { + const DATA32 v = *ptr; + *ptr++ = (v & 0xFF00FF00) + | ((v & 0x00FF0000) >> 16) + | ((v & 0x000000FF) << 16); + } + } glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0); + + evas_common_convert_argb_premul(pixels, w * h); + return EINA_TRUE; } //--------------------------------//