[gtk/wip/ebassi/gdk-egl-x11-v2: 3/7] gl: Add private glReadPixels() wrapper



commit 0e459dd93cf73b498c1e12c02c6c9f2ec0f54d4c
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Fri Dec 16 11:31:19 2016 +0000

    gl: Add private glReadPixels() wrapper
    
    For the software fallback path in gdk_cairo_draw_from_gl() we use
    glReadPixels() to read the contents of a framebuffer object in order to
    put it inside a Cairo image surface we can blend on the CPU. In order to
    do that, we use GL_PACK_ROW_LENGTH, which is only available in desktop
    GL, GLES 3.0, or if the GL_EXT_unpack_subimage extension is present.
    Older GLES 2.0 drivers would just be out of luck.
    
    Instead of bailing out, let's implement unpacking line by line, to
    adjust for the Cairo image surface stride, like we do when uploading
    textures.
    
    In order to avoid complicating an already big function, we should wrap
    our glReadPixels() call with our own wrapper that performs checks and
    calls the appropriate functions with the appropriate data.

 gdk/gdkgl.c               | 25 +++---------------
 gdk/gdkglcontext.c        | 66 +++++++++++++++++++++++++++++++++++++++++++++++
 gdk/gdkglcontextprivate.h |  6 +++++
 3 files changed, 76 insertions(+), 21 deletions(-)
---
diff --git a/gdk/gdkgl.c b/gdk/gdkgl.c
index be24be7e9f..035ada3867 100644
--- a/gdk/gdkgl.c
+++ b/gdk/gdkgl.c
@@ -645,13 +645,6 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
     {
       /* Software fallback */
       int major, minor, version;
-      gboolean es_read_bgra = FALSE;
-
-#ifdef GDK_WINDOWING_WIN32
-      /* on ANGLE GLES, we need to set the glReadPixel() format as GL_BGRA instead */
-      if (GDK_WIN32_IS_GL_CONTEXT(paint_context))
-        es_read_bgra = TRUE;
-#endif
 
       gdk_gl_context_get_version (paint_context, &major, &minor);
       version = major * 100 + minor;
@@ -686,24 +679,15 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
                                   GL_TEXTURE_2D, source, 0);
         }
 
-      glPixelStorei (GL_PACK_ALIGNMENT, 4);
-      glPixelStorei (GL_PACK_ROW_LENGTH, cairo_image_surface_get_stride (image) / 4);
-
-      /* The implicit format conversion is going to make this path slower */
-      if (!gdk_gl_context_get_use_es (paint_context))
-        glReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
-                      cairo_image_surface_get_data (image));
-      else
-        glReadPixels (x, y, width, height, es_read_bgra ? GL_BGRA : GL_RGBA, GL_UNSIGNED_BYTE,
-                      cairo_image_surface_get_data (image));
-
-      glPixelStorei (GL_PACK_ROW_LENGTH, 0);
+      gdk_gl_context_download_texture (paint_context,
+                                       x, y, width, height,
+                                       image);
 
       glBindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
 
       cairo_surface_mark_dirty (image);
 
-      /* Invert due to opengl having different origin */
+      /* Invert due to GL framebuffers having different origin */
       cairo_scale (cr, 1, -1);
       cairo_translate (cr, 0, -height / buffer_scale);
 
@@ -717,7 +701,6 @@ gdk_cairo_draw_from_gl (cairo_t              *cr,
 out:
   if (clip_region)
     cairo_region_destroy (clip_region);
-
 }
 
 /* This is always called with the paint context current */
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index dfbed63ca5..74dad4077c 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -236,6 +236,72 @@ gdk_gl_context_get_property (GObject    *gobject,
     }
 }
 
+void
+gdk_gl_context_download_texture (GdkGLContext    *context,
+                                 int              x,
+                                 int              y,
+                                 int              width,
+                                 int              height,
+                                 cairo_surface_t *image_surface)
+{
+  GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+  gboolean es_read_bgra = FALSE;
+
+#ifdef GDK_WINDOWING_WIN32
+  /* on ANGLE GLES, we need to set the glReadPixel() format as GL_BGRA instead */
+  if (GDK_WIN32_IS_GL_CONTEXT (context))
+    es_read_bgra = TRUE;
+#endif
+
+  g_return_if_fail (GDK_IS_GL_CONTEXT (context));
+
+  /* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if
+   * the GL_EXT_unpack_subimage extension for OpenGL ES 2.0 is available
+   */
+  if (!priv->use_es ||
+      (priv->use_es && (priv->gl_version >= 30 || priv->has_unpack_subimage)))
+    {
+      glPixelStorei (GL_PACK_ALIGNMENT, 4);
+      glPixelStorei (GL_PACK_ROW_LENGTH, cairo_image_surface_get_stride (image_surface) / 4);
+
+      if (priv->use_es)
+        glReadPixels (x, y, width, height,
+                      es_read_bgra ? GL_BGRA : GL_RGBA,
+                      GL_UNSIGNED_BYTE,
+                      cairo_image_surface_get_data (image_surface));
+      else
+        glReadPixels (x, y, width, height,
+                      GL_BGRA,
+                      GL_UNSIGNED_INT_8_8_8_8_REV,
+                      cairo_image_surface_get_data (image_surface));
+
+      glPixelStorei (GL_PACK_ROW_LENGTH, 0);
+    }
+  else
+    {
+      GLvoid *data = cairo_image_surface_get_data (image_surface);
+      int stride = cairo_image_surface_get_stride (image_surface);
+      int i;
+
+      if (priv->use_es)
+        {
+          for (i = y; i < height; i++)
+            glReadPixels (x, i, width, 1,
+                          es_read_bgra ? GL_BGRA : GL_RGBA,
+                          GL_UNSIGNED_BYTE,
+                          (unsigned char *) data + (i * stride));
+        }
+      else
+        {
+          for (i = y; i < height; i++)
+            glReadPixels (x, i, width, 1,
+                          GL_BGRA,
+                          GL_UNSIGNED_INT_8_8_8_8_REV,
+                          (unsigned char *) data + (i * stride));
+        }
+    }
+}
+
 void
 gdk_gl_context_upload_texture (GdkGLContext    *context,
                                cairo_surface_t *image_surface,
diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h
index cb0b76793f..30c2239f79 100644
--- a/gdk/gdkglcontextprivate.h
+++ b/gdk/gdkglcontextprivate.h
@@ -81,6 +81,12 @@ void                    gdk_gl_context_upload_texture           (GdkGLContext
                                                                  int              width,
                                                                  int              height,
                                                                  guint            texture_target);
+void                    gdk_gl_context_download_texture         (GdkGLContext    *context,
+                                                                 int              x,
+                                                                 int              y,
+                                                                 int              width,
+                                                                 int              height,
+                                                                 cairo_surface_t *image_surface);
 GdkGLContextPaintData * gdk_gl_context_get_paint_data           (GdkGLContext    *context);
 gboolean                gdk_gl_context_use_texture_rectangle    (GdkGLContext    *context);
 gboolean                gdk_gl_context_has_framebuffer_blit     (GdkGLContext    *context);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]