[gtk+/wip/ebassi/gdk-egl-x11: 55/58] gl: Add private glReadPixels() wrapper
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/ebassi/gdk-egl-x11: 55/58] gl: Add private glReadPixels() wrapper
- Date: Mon, 16 Jan 2017 14:03:54 +0000 (UTC)
commit f0317594ad2d7ea954e4e693f9dff2f1d7e4d632
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 | 31 +++-----------------------
gdk/gdkglcontext.c | 51 +++++++++++++++++++++++++++++++++++++++++++++
gdk/gdkglcontextprivate.h | 6 +++++
3 files changed, 61 insertions(+), 27 deletions(-)
---
diff --git a/gdk/gdkgl.c b/gdk/gdkgl.c
index e0ba772..fa08ccc 100644
--- a/gdk/gdkgl.c
+++ b/gdk/gdkgl.c
@@ -640,18 +640,6 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
else
{
/* Software fallback */
- int major, minor, version;
-
- gdk_gl_context_get_version (paint_context, &major, &minor);
- version = major * 100 + minor;
-
- /* TODO: Use glTexSubImage2D() and do a row-by-row copy to replace
- * the GL_UNPACK_ROW_LENGTH support
- */
- if (gdk_gl_context_get_use_es (paint_context) &&
- !(version >= 300 || gdk_gl_context_has_unpack_subimage (paint_context)))
- goto out;
-
/* TODO: avoid reading back non-required data due to dest clip */
image = cairo_surface_create_similar_image (cairo_get_target (cr),
(alpha_size == 0) ? CAIRO_FORMAT_RGB24 :
CAIRO_FORMAT_ARGB32,
@@ -675,24 +663,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, 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);
@@ -703,10 +682,8 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
cairo_surface_destroy (image);
}
-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 c79dca0..1891d47 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -237,6 +237,57 @@ 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);
+
+ 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, 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, 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,
int width,
diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h
index cb0b767..30c2239 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]