[gtk/wip/otte/gl-hdr: 13/18] egl: Unify contexts
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/gl-hdr: 13/18] egl: Unify contexts
- Date: Wed, 6 Oct 2021 01:45:28 +0000 (UTC)
commit 2ff1ea555fb075a1a595364e28881432b447fc90
Author: Benjamin Otte <otte redhat com>
Date: Wed Oct 6 00:34:10 2021 +0200
egl: Unify contexts
Unify the X11 and Wayland EGL contexts.
This is a bit ugly to implement, because I don't want to create an
interface and I can't make them inherit from the same object, because
one needs to inherit from X11GLContext and the other from
WaylandGLContext.
So we have to put the code in GdkGLContext and make sure non-EGL
contexts can't accidentally run it. This is rather easy because we can
just check for priv->egl_context != NULL.
gdk/gdkglcontext.c | 323 ++++++++++++++++++++++++++++++++++++-
gdk/gdkglcontextprivate.h | 1 -
gdk/wayland/gdkglcontext-wayland.c | 306 +----------------------------------
gdk/wayland/gdkglcontext-wayland.h | 2 -
gdk/x11/gdkglcontext-egl.c | 292 +--------------------------------
5 files changed, 327 insertions(+), 597 deletions(-)
---
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 04e21e5b0e..0fea1e7614 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -80,6 +80,7 @@
#include "gdkdisplayprivate.h"
#include "gdkintl.h"
#include "gdkmemorytextureprivate.h"
+#include "gdkprofilerprivate.h"
#include "gdk-private.h"
@@ -88,6 +89,9 @@
#endif
#include <epoxy/gl.h>
+#ifdef HAVE_EGL
+#include <epoxy/egl.h>
+#endif
typedef struct {
int major;
@@ -107,6 +111,10 @@ typedef struct {
int use_es;
int max_debug_label_length;
+
+#ifdef HAVE_EGL
+ EGLContext egl_context;
+#endif
} GdkGLContextPrivate;
enum {
@@ -161,6 +169,24 @@ static void
gdk_gl_context_dispose (GObject *gobject)
{
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
+#ifdef HAVE_EGL
+ GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+
+ if (priv->egl_context != NULL)
+ {
+ GdkSurface *surface = gdk_gl_context_get_surface (context);
+ GdkDisplay *display = gdk_surface_get_display (surface);
+ EGLDisplay *egl_display = gdk_display_get_egl_display (display);
+
+ if (eglGetCurrentContext () == priv->egl_context)
+ eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+ GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Destroying EGL context"));
+
+ eglDestroyContext (egl_display, priv->egl_context);
+ priv->egl_context = NULL;
+ }
+#endif
gdk_gl_context_clear_old_updated_area (context);
@@ -320,20 +346,219 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
g_free (copy);
}
+#define N_EGL_ATTRS 16
+
static gboolean
-gdk_gl_context_real_realize (GdkGLContext *self,
+gdk_gl_context_real_realize (GdkGLContext *context,
GError **error)
{
+#if HAVE_EGL
+ GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+ GdkDisplay *display = gdk_gl_context_get_display (context);
+ EGLDisplay egl_display = gdk_display_get_egl_display (display);
+
+ if (egl_display)
+ {
+ EGLConfig egl_config = gdk_display_get_egl_config (display);
+ GdkGLContext *share = gdk_display_get_gl_context (display);
+ GdkGLContextPrivate *share_priv = gdk_gl_context_get_instance_private (share);
+ EGLContext ctx;
+ EGLint context_attribs[N_EGL_ATTRS];
+ int major, minor, flags;
+ gboolean debug_bit, forward_bit, legacy_bit, use_es;
+ int i = 0;
+ G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
+
+ gdk_gl_context_get_required_version (context, &major, &minor);
+ debug_bit = gdk_gl_context_get_debug_enabled (context);
+ forward_bit = gdk_gl_context_get_forward_compatible (context);
+ legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ||
+ (share != NULL && gdk_gl_context_is_legacy (share));
+ use_es = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES) ||
+ (share != NULL && gdk_gl_context_get_use_es (share));
+
+ flags = 0;
+
+ if (debug_bit)
+ flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
+ if (forward_bit)
+ flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
+
+ if (!use_es)
+ {
+ eglBindAPI (EGL_OPENGL_API);
+
+ /* We want a core profile, unless in legacy mode */
+ context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
+ context_attribs[i++] = legacy_bit
+ ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR
+ : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
+
+ /* Specify the version */
+ context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR;
+ context_attribs[i++] = legacy_bit ? 3 : major;
+ context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR;
+ context_attribs[i++] = legacy_bit ? 0 : minor;
+ }
+ else
+ {
+ eglBindAPI (EGL_OPENGL_ES_API);
+
+ context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
+ if (major == 3)
+ context_attribs[i++] = 3;
+ else
+ context_attribs[i++] = 2;
+ }
+
+ /* Specify the flags */
+ context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
+ context_attribs[i++] = flags;
+
+ context_attribs[i++] = EGL_NONE;
+ g_assert (i < N_EGL_ATTRS);
+
+ GDK_DISPLAY_NOTE (display, OPENGL,
+ g_message ("Creating EGL context version %d.%d (debug:%s, forward:%s, legacy:%s, es:%s)",
+ major, minor,
+ debug_bit ? "yes" : "no",
+ forward_bit ? "yes" : "no",
+ legacy_bit ? "yes" : "no",
+ use_es ? "yes" : "no"));
+
+ ctx = eglCreateContext (egl_display,
+ egl_config,
+ share != NULL ? share_priv->egl_context
+ : EGL_NO_CONTEXT,
+ context_attribs);
+
+ /* If context creation failed without the ES bit, let's try again with it */
+ if (ctx == NULL)
+ {
+ i = 0;
+ context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION;
+ context_attribs[i++] = 2;
+ context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION;
+ context_attribs[i++] = 0;
+ context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
+ context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
+ context_attribs[i++] = EGL_NONE;
+ g_assert (i < N_EGL_ATTRS);
+
+ eglBindAPI (EGL_OPENGL_ES_API);
+
+ legacy_bit = FALSE;
+ use_es = TRUE;
+
+ GDK_DISPLAY_NOTE (display, OPENGL,
+ g_message ("eglCreateContext failed, switching to OpenGLĀ ES"));
+ ctx = eglCreateContext (egl_display,
+ egl_config,
+ share != NULL ? share_priv->egl_context
+ : EGL_NO_CONTEXT,
+ context_attribs);
+ }
+
+ /* If context creation failed without the legacy bit, let's try again with it */
+ if (ctx == NULL)
+ {
+ i = 0;
+ context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
+ context_attribs[i++] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
+ context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION;
+ context_attribs[i++] = 3;
+ context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION;
+ context_attribs[i++] = 0;
+ context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
+ context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
+ context_attribs[i++] = EGL_NONE;
+ g_assert (i < N_EGL_ATTRS);
+
+ eglBindAPI (EGL_OPENGL_API);
+
+ legacy_bit = TRUE;
+ use_es = FALSE;
+
+ GDK_DISPLAY_NOTE (display, OPENGL,
+ g_message ("eglCreateContext failed, switching to legacy"));
+ ctx = eglCreateContext (egl_display,
+ egl_config,
+ share != NULL ? share_priv->egl_context
+ : EGL_NO_CONTEXT,
+ context_attribs);
+ }
+
+ if (ctx == NULL)
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("Unable to create a GL context"));
+ return FALSE;
+ }
+
+ GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Created EGL context[%p]", ctx));
+
+ priv->egl_context = ctx;
+
+ gdk_gl_context_set_is_legacy (context, legacy_bit);
+ gdk_gl_context_set_use_es (context, use_es);
+
+ gdk_profiler_end_mark (start_time, "realize GdkWaylandGLContext", NULL);
+
+ return TRUE;
+ }
+#endif
+
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
"The current backend does not support OpenGL");
-
return FALSE;
}
+#undef N_EGL_ATTRS
+
static cairo_region_t *
gdk_gl_context_real_get_damage (GdkGLContext *context)
{
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
+#ifdef HAVE_EGL
+ GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+ GdkDisplay *display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context));
+
+ if (priv->egl_context && display->have_egl_buffer_age)
+ {
+ EGLSurface egl_surface;
+ int buffer_age = 0;
+ egl_surface = gdk_surface_get_egl_surface (surface);
+ gdk_gl_context_make_current (context);
+ eglQuerySurface (gdk_display_get_egl_display (display), egl_surface,
+ EGL_BUFFER_AGE_EXT, &buffer_age);
+
+ switch (buffer_age)
+ {
+ case 1:
+ return cairo_region_create ();
+ break;
+
+ case 2:
+ if (context->old_updated_area[0])
+ return cairo_region_copy (context->old_updated_area[0]);
+ break;
+
+ case 3:
+ if (context->old_updated_area[0] &&
+ context->old_updated_area[1])
+ {
+ cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
+ cairo_region_union (damage, context->old_updated_area[1]);
+ return damage;
+ }
+ break;
+
+ default:
+ ;
+ }
+ }
+#endif
return cairo_region_create_rectangle (&(GdkRectangle) {
0, 0,
@@ -354,6 +579,51 @@ gdk_gl_context_real_is_shared (GdkGLContext *self,
return TRUE;
}
+static gboolean
+gdk_gl_context_real_clear_current (GdkGLContext *context)
+{
+ GdkDisplay *display = gdk_gl_context_get_display (context);
+#ifdef HAVE_EGL
+ GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+
+ if (priv->egl_context == NULL)
+ return FALSE;
+
+ return eglMakeCurrent (gdk_display_get_egl_display (display),
+ EGL_NO_SURFACE,
+ EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+#else
+ return FALSE;
+#endif
+}
+
+static gboolean
+gdk_gl_context_real_make_current (GdkGLContext *context,
+ gboolean surfaceless)
+{
+#ifdef HAVE_EGL
+ GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+ GdkDisplay *display = gdk_gl_context_get_display (context);
+ EGLSurface egl_surface;
+
+ if (priv->egl_context == NULL)
+ return FALSE;
+
+ if (!surfaceless)
+ egl_surface = gdk_surface_get_egl_surface (gdk_gl_context_get_surface (context));
+ else
+ egl_surface = EGL_NO_SURFACE;
+
+ return eglMakeCurrent (gdk_display_get_egl_display (display),
+ egl_surface,
+ egl_surface,
+ priv->egl_context);
+#else
+ return FALSE;
+#endif
+}
+
static void
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *region)
@@ -392,6 +662,52 @@ static void
gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
+#ifdef HAVE_EGL
+ GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
+ GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+ GdkSurface *surface = gdk_gl_context_get_surface (context);
+ GdkDisplay *display = gdk_surface_get_display (surface);
+ EGLSurface egl_surface;
+
+ if (priv->egl_context == NULL)
+ return;
+
+ gdk_gl_context_make_current (context);
+
+ egl_surface = gdk_surface_get_egl_surface (surface);
+
+ gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "EGL", "swap buffers");
+
+ if (display->have_egl_swap_buffers_with_damage)
+ {
+ EGLint stack_rects[4 * 4]; /* 4 rects */
+ EGLint *heap_rects = NULL;
+ int i, j, n_rects = cairo_region_num_rectangles (painted);
+ int surface_height = gdk_surface_get_height (surface);
+ int scale = gdk_surface_get_scale_factor (surface);
+ EGLint *rects;
+
+ if (n_rects < G_N_ELEMENTS (stack_rects) / 4)
+ rects = (EGLint *)&stack_rects;
+ else
+ heap_rects = rects = g_new (EGLint, n_rects * 4);
+
+ for (i = 0, j = 0; i < n_rects; i++)
+ {
+ cairo_rectangle_int_t rect;
+
+ cairo_region_get_rectangle (painted, i, &rect);
+ rects[j++] = rect.x * scale;
+ rects[j++] = (surface_height - rect.height - rect.y) * scale;
+ rects[j++] = rect.width * scale;
+ rects[j++] = rect.height * scale;
+ }
+ eglSwapBuffersWithDamageEXT (gdk_display_get_egl_display (display), egl_surface, rects, n_rects);
+ g_free (heap_rects);
+ }
+ else
+ eglSwapBuffers (gdk_display_get_egl_display (display), egl_surface);
+#endif
}
static void
@@ -411,6 +727,8 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
klass->realize = gdk_gl_context_real_realize;
klass->get_damage = gdk_gl_context_real_get_damage;
klass->is_shared = gdk_gl_context_real_is_shared;
+ klass->make_current = gdk_gl_context_real_make_current;
+ klass->clear_current = gdk_gl_context_real_clear_current;
draw_context_class->begin_frame = gdk_gl_context_real_begin_frame;
draw_context_class->end_frame = gdk_gl_context_real_end_frame;
@@ -1357,3 +1675,4 @@ gdk_gl_backend_use (GdkGLBackend backend_type)
g_assert (the_gl_backend_type == backend_type);
}
+
diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h
index db7ab4ce9c..add799d381 100644
--- a/gdk/gdkglcontextprivate.h
+++ b/gdk/gdkglcontextprivate.h
@@ -133,7 +133,6 @@ gboolean gdk_gl_context_has_debug (GdkGLContext
gboolean gdk_gl_context_use_es_bgra (GdkGLContext *context);
-
G_END_DECLS
#endif /* __GDK_GL_CONTEXT_PRIVATE_H__ */
diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c
index 287ee5552b..97b5bcbbbe 100644
--- a/gdk/wayland/gdkglcontext-wayland.c
+++ b/gdk/wayland/gdkglcontext-wayland.c
@@ -45,239 +45,6 @@
G_DEFINE_TYPE (GdkWaylandGLContext, gdk_wayland_gl_context, GDK_TYPE_GL_CONTEXT)
-static void gdk_wayland_gl_context_dispose (GObject *gobject);
-
-#define N_EGL_ATTRS 16
-
-static gboolean
-gdk_wayland_gl_context_realize (GdkGLContext *context,
- GError **error)
-{
- GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
- GdkDisplay *display = gdk_gl_context_get_display (context);
- GdkGLContext *share = gdk_display_get_gl_context (display);
- EGLDisplay egl_display = gdk_display_get_egl_display (display);
- EGLConfig egl_config = gdk_display_get_egl_config (display);
- EGLContext ctx;
- EGLint context_attribs[N_EGL_ATTRS];
- int major, minor, flags;
- gboolean debug_bit, forward_bit, legacy_bit, use_es;
- int i = 0;
- G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
-
- gdk_gl_context_get_required_version (context, &major, &minor);
- debug_bit = gdk_gl_context_get_debug_enabled (context);
- forward_bit = gdk_gl_context_get_forward_compatible (context);
- legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ||
- (share != NULL && gdk_gl_context_is_legacy (share));
- use_es = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES) ||
- (share != NULL && gdk_gl_context_get_use_es (share));
-
- flags = 0;
-
- if (debug_bit)
- flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
- if (forward_bit)
- flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
-
- if (!use_es)
- {
- eglBindAPI (EGL_OPENGL_API);
-
- /* We want a core profile, unless in legacy mode */
- context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
- context_attribs[i++] = legacy_bit
- ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR
- : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
-
- /* Specify the version */
- context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR;
- context_attribs[i++] = legacy_bit ? 3 : major;
- context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR;
- context_attribs[i++] = legacy_bit ? 0 : minor;
- }
- else
- {
- eglBindAPI (EGL_OPENGL_ES_API);
-
- context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
- if (major == 3)
- context_attribs[i++] = 3;
- else
- context_attribs[i++] = 2;
- }
-
- /* Specify the flags */
- context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
- context_attribs[i++] = flags;
-
- context_attribs[i++] = EGL_NONE;
- g_assert (i < N_EGL_ATTRS);
-
- GDK_DISPLAY_NOTE (display, OPENGL,
- g_message ("Creating EGL context version %d.%d (debug:%s, forward:%s, legacy:%s, es:%s)",
- major, minor,
- debug_bit ? "yes" : "no",
- forward_bit ? "yes" : "no",
- legacy_bit ? "yes" : "no",
- use_es ? "yes" : "no"));
-
- ctx = eglCreateContext (egl_display,
- egl_config,
- share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
- : EGL_NO_CONTEXT,
- context_attribs);
-
- /* If context creation failed without the ES bit, let's try again with it */
- if (ctx == NULL)
- {
- i = 0;
- context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION;
- context_attribs[i++] = 2;
- context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION;
- context_attribs[i++] = 0;
- context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
- context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
- context_attribs[i++] = EGL_NONE;
- g_assert (i < N_EGL_ATTRS);
-
- eglBindAPI (EGL_OPENGL_ES_API);
-
- legacy_bit = FALSE;
- use_es = TRUE;
-
- GDK_DISPLAY_NOTE (display, OPENGL,
- g_message ("eglCreateContext failed, switching to OpenGLĀ ES"));
- ctx = eglCreateContext (egl_display,
- egl_config,
- share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
- : EGL_NO_CONTEXT,
- context_attribs);
- }
-
- /* If context creation failed without the legacy bit, let's try again with it */
- if (ctx == NULL)
- {
- i = 0;
- context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
- context_attribs[i++] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
- context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION;
- context_attribs[i++] = 3;
- context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION;
- context_attribs[i++] = 0;
- context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
- context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
- context_attribs[i++] = EGL_NONE;
- g_assert (i < N_EGL_ATTRS);
-
- eglBindAPI (EGL_OPENGL_API);
-
- legacy_bit = TRUE;
- use_es = FALSE;
-
- GDK_DISPLAY_NOTE (display, OPENGL,
- g_message ("eglCreateContext failed, switching to legacy"));
- ctx = eglCreateContext (egl_display,
- egl_config,
- share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
- : EGL_NO_CONTEXT,
- context_attribs);
- }
-
- if (ctx == NULL)
- {
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_NOT_AVAILABLE,
- _("Unable to create a GL context"));
- return FALSE;
- }
-
- GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Created EGL context[%p]", ctx));
-
- context_wayland->egl_context = ctx;
-
- gdk_gl_context_set_is_legacy (context, legacy_bit);
- gdk_gl_context_set_use_es (context, use_es);
-
- gdk_profiler_end_mark (start_time, "realize GdkWaylandGLContext", NULL);
-
- return TRUE;
-}
-
-static cairo_region_t *
-gdk_wayland_gl_context_get_damage (GdkGLContext *context)
-{
- GdkDisplay *display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context));
- EGLSurface egl_surface;
- GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
- int buffer_age = 0;
-
- if (display->have_egl_buffer_age)
- {
- egl_surface = gdk_surface_get_egl_surface (surface);
- gdk_gl_context_make_current (context);
- eglQuerySurface (gdk_display_get_egl_display (display), egl_surface,
- EGL_BUFFER_AGE_EXT, &buffer_age);
-
- switch (buffer_age)
- {
- case 1:
- return cairo_region_create ();
- break;
-
- case 2:
- if (context->old_updated_area[0])
- return cairo_region_copy (context->old_updated_area[0]);
- break;
-
- case 3:
- if (context->old_updated_area[0] &&
- context->old_updated_area[1])
- {
- cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
- cairo_region_union (damage, context->old_updated_area[1]);
- return damage;
- }
- break;
-
- default:
- ;
- }
- }
-
- return GDK_GL_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->get_damage (context);
-}
-
-static gboolean
-gdk_wayland_gl_context_clear_current (GdkGLContext *context)
-{
- GdkDisplay *display = gdk_gl_context_get_display (context);
-
- return eglMakeCurrent (gdk_display_get_egl_display (display),
- EGL_NO_SURFACE,
- EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
-}
-
-static gboolean
-gdk_wayland_gl_context_make_current (GdkGLContext *context,
- gboolean surfaceless)
-{
- GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
- GdkDisplay *display = gdk_gl_context_get_display (context);
- EGLSurface egl_surface;
-
- if (!surfaceless)
- egl_surface = gdk_surface_get_egl_surface (gdk_gl_context_get_surface (context));
- else
- egl_surface = EGL_NO_SURFACE;
-
- return eglMakeCurrent (gdk_display_get_egl_display (display),
- egl_surface,
- egl_surface,
- context_wayland->egl_context);
-}
-
static void
gdk_wayland_gl_context_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *region)
@@ -293,49 +60,12 @@ static void
gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
- GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
- GdkSurface *surface = gdk_gl_context_get_surface (context);
- GdkDisplay *display = gdk_surface_get_display (surface);
- EGLSurface egl_surface;
-
- GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->end_frame (draw_context, painted);
+ GdkSurface *surface = gdk_draw_context_get_surface (draw_context);
- gdk_gl_context_make_current (context);
-
- egl_surface = gdk_surface_get_egl_surface (surface);
gdk_wayland_surface_sync (surface);
gdk_wayland_surface_request_frame (surface);
- gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "wayland", "swap buffers");
- if (display->have_egl_swap_buffers_with_damage)
- {
- EGLint stack_rects[4 * 4]; /* 4 rects */
- EGLint *heap_rects = NULL;
- int i, j, n_rects = cairo_region_num_rectangles (painted);
- int surface_height = gdk_surface_get_height (surface);
- int scale = gdk_surface_get_scale_factor (surface);
- EGLint *rects;
-
- if (n_rects < G_N_ELEMENTS (stack_rects) / 4)
- rects = (EGLint *)&stack_rects;
- else
- heap_rects = rects = g_new (EGLint, n_rects * 4);
-
- for (i = 0, j = 0; i < n_rects; i++)
- {
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (painted, i, &rect);
- rects[j++] = rect.x * scale;
- rects[j++] = (surface_height - rect.height - rect.y) * scale;
- rects[j++] = rect.width * scale;
- rects[j++] = rect.height * scale;
- }
- eglSwapBuffersWithDamageEXT (gdk_display_get_egl_display (display), egl_surface, rects, n_rects);
- g_free (heap_rects);
- }
- else
- eglSwapBuffers (gdk_display_get_egl_display (display), egl_surface);
+ GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->end_frame (draw_context, painted);
gdk_wayland_surface_notify_committed (surface);
}
@@ -343,20 +73,12 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
static void
gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
- gobject_class->dispose = gdk_wayland_gl_context_dispose;
-
draw_context_class->begin_frame = gdk_wayland_gl_context_begin_frame;
draw_context_class->end_frame = gdk_wayland_gl_context_end_frame;
- context_class->realize = gdk_wayland_gl_context_realize;
- context_class->make_current = gdk_wayland_gl_context_make_current;
- context_class->clear_current = gdk_wayland_gl_context_clear_current;
- context_class->get_damage = gdk_wayland_gl_context_get_damage;
-
context_class->backend_type = GDK_GL_EGL;
}
@@ -401,27 +123,3 @@ gdk_wayland_display_init_gl (GdkDisplay *display,
NULL);
}
-static void
-gdk_wayland_gl_context_dispose (GObject *gobject)
-{
- GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (gobject);
-
- if (context_wayland->egl_context != NULL)
- {
- GdkGLContext *context = GDK_GL_CONTEXT (gobject);
- GdkSurface *surface = gdk_gl_context_get_surface (context);
- GdkDisplay *display = gdk_surface_get_display (surface);
- EGLDisplay *egl_display = gdk_display_get_egl_display (display);
-
- if (eglGetCurrentContext () == context_wayland->egl_context)
- eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
- GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Destroying EGL context"));
-
- eglDestroyContext (egl_display, context_wayland->egl_context);
- context_wayland->egl_context = NULL;
- }
-
- G_OBJECT_CLASS (gdk_wayland_gl_context_parent_class)->dispose (gobject);
-}
-
diff --git a/gdk/wayland/gdkglcontext-wayland.h b/gdk/wayland/gdkglcontext-wayland.h
index 04a7053bb4..c35e1e6700 100644
--- a/gdk/wayland/gdkglcontext-wayland.h
+++ b/gdk/wayland/gdkglcontext-wayland.h
@@ -33,8 +33,6 @@ G_BEGIN_DECLS
struct _GdkWaylandGLContext
{
GdkGLContext parent_instance;
-
- EGLContext egl_context;
};
struct _GdkWaylandGLContextClass
diff --git a/gdk/x11/gdkglcontext-egl.c b/gdk/x11/gdkglcontext-egl.c
index 16aaca9361..b417718c28 100644
--- a/gdk/x11/gdkglcontext-egl.c
+++ b/gdk/x11/gdkglcontext-egl.c
@@ -32,8 +32,6 @@ struct _GdkX11GLContextEGL
{
GdkX11GLContext parent_instance;
- EGLContext egl_context;
-
guint do_frame_sync : 1;
};
@@ -70,66 +68,6 @@ gdk_x11_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
glDrawBuffers (1, (GLenum[1]) { GL_BACK });
}
-static void
-gdk_x11_gl_context_egl_end_frame (GdkDrawContext *draw_context,
- cairo_region_t *painted)
-{
- GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
- GdkSurface *surface = gdk_gl_context_get_surface (context);
- GdkDisplay *display = gdk_surface_get_display (surface);
- EGLSurface egl_surface;
-
- GDK_DRAW_CONTEXT_CLASS (gdk_x11_gl_context_egl_parent_class)->end_frame (draw_context, painted);
-
- gdk_gl_context_make_current (context);
-
- egl_surface = gdk_surface_get_egl_surface (surface);
-
- gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "x11", "swap buffers");
- if (display->have_egl_swap_buffers_with_damage)
- {
- int i, j, n_rects = cairo_region_num_rectangles (painted);
- int surface_height = gdk_surface_get_height (surface);
- int scale = gdk_surface_get_scale_factor (surface);
- EGLint stack_rects[4 * 4]; /* 4 rects */
- EGLint *heap_rects = NULL;
- EGLint *rects;
-
- if (n_rects < G_N_ELEMENTS (stack_rects) / 4)
- rects = (EGLint *) &stack_rects;
- else
- rects = heap_rects = g_new (EGLint, n_rects * 4);
-
- for (i = 0, j = 0; i < n_rects; i++)
- {
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (painted, i, &rect);
-
- rects[j++] = rect.x * scale;
- rects[j++] = (surface_height - rect.height - rect.y) * scale;
- rects[j++] = rect.width * scale;
- rects[j++] = rect.height * scale;
- }
-
- eglSwapBuffersWithDamageEXT (gdk_display_get_egl_display (display), egl_surface, rects, n_rects);
- g_free (heap_rects);
- }
- else
- eglSwapBuffers (gdk_display_get_egl_display (display), egl_surface);
-}
-
-static gboolean
-gdk_x11_gl_context_egl_clear_current (GdkGLContext *context)
-{
- GdkDisplay *display = gdk_gl_context_get_display (context);
-
- return eglMakeCurrent (gdk_display_get_egl_display (display),
- EGL_NO_SURFACE,
- EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
-}
-
static gboolean
gdk_x11_gl_context_egl_make_current (GdkGLContext *context,
gboolean surfaceless)
@@ -137,31 +75,14 @@ gdk_x11_gl_context_egl_make_current (GdkGLContext *context,
GdkX11GLContextEGL *self = GDK_X11_GL_CONTEXT_EGL (context);
GdkDisplay *display = gdk_gl_context_get_display (context);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
- GdkSurface *surface;
- EGLSurface egl_surface;
gboolean do_frame_sync = FALSE;
- if (surfaceless)
- {
- return eglMakeCurrent (egl_display,
- EGL_NO_SURFACE,
- EGL_NO_SURFACE,
- self->egl_context);
- }
-
- surface = gdk_gl_context_get_surface (context);
- egl_surface = gdk_surface_get_egl_surface (surface);
-
- GDK_DISPLAY_NOTE (display, OPENGL,
- g_message ("Making EGL context %p current to surface %p",
- self->egl_context, egl_surface));
-
- if (!eglMakeCurrent (gdk_display_get_egl_display (display),
- egl_surface,
- egl_surface,
- self->egl_context))
+ if (!GDK_GL_CONTEXT_CLASS (gdk_x11_gl_context_egl_parent_class)->make_current (context, surfaceless))
return FALSE;
+ if (surfaceless)
+ return TRUE;
+
/* If the WM is compositing there is no particular need to delay
* the swap when drawing on the offscreen, rendering to the screen
* happens later anyway, and its up to the compositor to sync that
@@ -181,222 +102,17 @@ gdk_x11_gl_context_egl_make_current (GdkGLContext *context,
return TRUE;
}
-static cairo_region_t *
-gdk_x11_gl_context_egl_get_damage (GdkGLContext *context)
-{
- GdkDisplay *display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context));
-
- if (display->have_egl_buffer_age)
- {
- GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
- EGLSurface egl_surface;
- int buffer_age = 0;
-
- egl_surface = gdk_surface_get_egl_surface (surface);
- gdk_gl_context_make_current (context);
-
- eglQuerySurface (gdk_display_get_egl_display (display),
- egl_surface,
- EGL_BUFFER_AGE_EXT,
- &buffer_age);
-
- switch (buffer_age)
- {
- case 1:
- return cairo_region_create ();
-
- case 2:
- if (context->old_updated_area[0])
- return cairo_region_copy (context->old_updated_area[0]);
- break;
-
- case 3:
- if (context->old_updated_area[0] && context->old_updated_area[1])
- {
- cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
- cairo_region_union (damage, context->old_updated_area[1]);
- return damage;
- }
- break;
-
- default:
- break;
- }
- }
-
- return GDK_GL_CONTEXT_CLASS (gdk_x11_gl_context_egl_parent_class)->get_damage (context);
-}
-
-#define N_EGL_ATTRS 16
-
-static gboolean
-gdk_x11_gl_context_egl_realize (GdkGLContext *context,
- GError **error)
-{
- GdkDisplay *display;
- GdkX11GLContextEGL *context_egl;
- GdkGLContext *share;
- EGLDisplay egl_display;
- EGLConfig egl_config;
- gboolean debug_bit, forward_bit, legacy_bit, use_es;
- int major, minor, flags, i = 0;
- EGLint context_attrs[N_EGL_ATTRS];
-
- display = gdk_gl_context_get_display (context);
-
- context_egl = GDK_X11_GL_CONTEXT_EGL (context);
- share = gdk_display_get_gl_context (display);
- egl_display = gdk_display_get_egl_display (display),
- egl_config = gdk_display_get_egl_config (display),
-
- gdk_gl_context_get_required_version (context, &major, &minor);
- debug_bit = gdk_gl_context_get_debug_enabled (context);
- forward_bit = gdk_gl_context_get_forward_compatible (context);
- legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ||
- (share != NULL && gdk_gl_context_is_legacy (share));
- use_es = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES) ||
- (share != NULL && gdk_gl_context_get_use_es (share));
-
- flags = 0;
- if (debug_bit)
- flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
- if (forward_bit)
- flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
-
- if (!use_es)
- {
- eglBindAPI (EGL_OPENGL_API);
-
- /* We want a core profile, unless in legacy mode */
- context_attrs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
- context_attrs[i++] = legacy_bit
- ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR
- : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
-
- /* Specify the version */
- context_attrs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR;
- context_attrs[i++] = legacy_bit ? 3 : major;
- context_attrs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR;
- context_attrs[i++] = legacy_bit ? 0 : minor;
- context_attrs[i++] = EGL_CONTEXT_FLAGS_KHR;
- }
- else
- {
- eglBindAPI (EGL_OPENGL_ES_API);
-
- context_attrs[i++] = EGL_CONTEXT_CLIENT_VERSION;
- if (major == 3)
- context_attrs[i++] = 3;
- else
- context_attrs[i++] = 2;
- }
-
- context_attrs[i++] = EGL_CONTEXT_FLAGS_KHR;
- context_attrs[i++] = flags;
-
- context_attrs[i++] = EGL_NONE;
- g_assert (i < N_EGL_ATTRS);
-
- GDK_DISPLAY_NOTE (display, OPENGL,
- g_message ("Creating EGL context version %d.%d (shared:%s, debug:%s, forward:%s,
legacy:%s, es:%s)",
- major, minor,
- share != NULL ? "yes" : "no",
- debug_bit ? "yes" : "no",
- forward_bit ? "yes" : "no",
- legacy_bit ? "yes" : "no",
- use_es ? "yes" : "no"));
-
- context_egl->egl_context =
- eglCreateContext (egl_display,
- egl_config,
- share != NULL
- ? GDK_X11_GL_CONTEXT_EGL (share)->egl_context
- : EGL_NO_CONTEXT,
- context_attrs);
-
- /* If we're not asking for a GLES context, and we don't have the legacy bit set
- * already, try again with a legacy context
- */
- if (context_egl->egl_context == NULL && !use_es && !legacy_bit)
- {
- context_attrs[1] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
- context_attrs[3] = 3;
- context_attrs[5] = 0;
-
- legacy_bit = TRUE;
- use_es = FALSE;
-
- GDK_NOTE (OPENGL,
- g_message ("Context creation failed; trying legacy EGL context"));
-
- context_egl->egl_context =
- eglCreateContext (egl_display,
- egl_config,
- share != NULL
- ? GDK_X11_GL_CONTEXT_EGL (share)->egl_context
- : EGL_NO_CONTEXT,
- context_attrs);
- }
-
- if (context_egl->egl_context == NULL)
- {
- g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
- _("Unable to create a GL context"));
- return FALSE;
- }
-
- gdk_gl_context_set_is_legacy (context, legacy_bit);
- gdk_gl_context_set_use_es (context, use_es);
-
- GDK_NOTE (OPENGL,
- g_message ("Realized EGL context[%p]",
- context_egl->egl_context));
-
- return TRUE;
-}
-
-#undef N_EGL_ATTRS
-
-static void
-gdk_x11_gl_context_egl_dispose (GObject *gobject)
-{
- GdkX11GLContextEGL *context_egl = GDK_X11_GL_CONTEXT_EGL (gobject);
-
- if (context_egl->egl_context != NULL)
- {
- GdkGLContext *context = GDK_GL_CONTEXT (gobject);
- GdkDisplay *display = gdk_gl_context_get_display (context);
-
- /* Unset the current context if we're disposing it */
- if (eglGetCurrentContext () == context_egl->egl_context)
- eglMakeCurrent (gdk_display_get_egl_display (display), EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
-
- GDK_NOTE (OPENGL, g_message ("Destroying EGL context"));
- eglDestroyContext (gdk_display_get_egl_display (display), context_egl->egl_context);
- context_egl->egl_context = NULL;
- }
-
- G_OBJECT_CLASS (gdk_x11_gl_context_egl_parent_class)->dispose (gobject);
-}
-
static void
gdk_x11_gl_context_egl_class_init (GdkX11GLContextEGLClass *klass)
{
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
context_class->backend_type = GDK_GL_EGL;
- context_class->realize = gdk_x11_gl_context_egl_realize;
context_class->make_current = gdk_x11_gl_context_egl_make_current;
- context_class->clear_current = gdk_x11_gl_context_egl_clear_current;
- context_class->get_damage = gdk_x11_gl_context_egl_get_damage;
draw_context_class->begin_frame = gdk_x11_gl_context_egl_begin_frame;
- draw_context_class->end_frame = gdk_x11_gl_context_egl_end_frame;
-
- gobject_class->dispose = gdk_x11_gl_context_egl_dispose;
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]