Evas gl_x11: Fix usage of glReadPixels
authorJean-Philippe Andre <jp.andre@samsung.com>
Thu, 13 Mar 2014 06:54:58 +0000 (15:54 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Thu, 13 Mar 2014 08:04:42 +0000 (17:04 +0900)
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.

src/modules/evas/engines/gl_common/evas_gl_common.h
src/modules/evas/engines/gl_common/evas_gl_context.c
src/modules/evas/engines/gl_x11/evas_engine.c

index 3f5bab2..70db622 100644 (file)
@@ -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);
index 000a396..2e447d9 100644 (file)
@@ -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);
index 96d2726..82ffd05 100644 (file)
@@ -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;
 }
 //--------------------------------//