[gtk/wip/otte/gl-hdr: 7/12] egl: Move initialization code and port Wayland
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/gl-hdr: 7/12] egl: Move initialization code and port Wayland
- Date: Mon, 4 Oct 2021 01:28:42 +0000 (UTC)
commit 540cb31d7c8cc6502906d85feeda29e4f1b15ef9
Author: Benjamin Otte <otte redhat com>
Date: Sun Oct 3 06:22:21 2021 +0200
egl: Move initialization code and port Wayland
Moves the EGL initialization code to gdk/ so it can be shared between
backends.
Also port the Wayland backend to this code, so I know that it works.
gdk/gdkdisplay.c | 351 +++++++++++++++++++++++++++++++++++++
gdk/gdkdisplayprivate.h | 17 +-
gdk/wayland/gdkdisplay-wayland.h | 4 -
gdk/wayland/gdkglcontext-wayland.c | 316 ++++-----------------------------
gdk/wayland/gdksurface-wayland.c | 13 +-
5 files changed, 408 insertions(+), 293 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 71d47f1d30..6d47f7011a 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -36,6 +36,7 @@
#include "gdkglcontextprivate.h"
#include "gdkmonitorprivate.h"
+#include <epoxy/egl.h>
#include <math.h>
/**
@@ -87,6 +88,9 @@ struct _GdkDisplayPrivate {
GdkGLContext *gl_context;
GError *gl_error;
+ EGLDisplay egl_display;
+ EGLConfig egl_config;
+
guint rgba : 1;
guint composited : 1;
guint input_shapes : 1;
@@ -146,6 +150,24 @@ gdk_display_default_init_gl (GdkDisplay *display,
return NULL;
}
+static guint
+gdk_display_default_rate_egl_config (GdkDisplay *display,
+ gpointer egl_display,
+ gpointer config)
+{
+ guint distance = 0;
+ int tmp;
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_SAMPLE_BUFFERS, &tmp) || tmp != 0)
+ distance += 0x20000;
+
+ if (!eglGetConfigAttrib (egl_display, config, EGL_DEPTH_SIZE, &tmp) || tmp != 0 ||
+ !eglGetConfigAttrib (egl_display, config, EGL_STENCIL_SIZE, &tmp) || tmp != 0)
+ distance += 0x10000;
+
+ return distance;
+}
+
static GdkSeat *
gdk_display_real_get_default_seat (GdkDisplay *display)
{
@@ -173,6 +195,7 @@ gdk_display_class_init (GdkDisplayClass *class)
class->make_default = gdk_display_real_make_default;
class->get_app_launch_context = gdk_display_real_get_app_launch_context;
class->init_gl = gdk_display_default_init_gl;
+ class->rate_egl_config = gdk_display_default_rate_egl_config;
class->get_default_seat = gdk_display_real_get_default_seat;
class->opened = gdk_display_real_opened;
@@ -352,6 +375,7 @@ gdk_display_dispose (GObject *object)
g_queue_clear (&display->queued_events);
g_clear_object (&priv->gl_context);
+ g_clear_pointer (&priv->egl_display, eglTerminate);
g_clear_error (&priv->gl_error);
G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
@@ -1312,6 +1336,333 @@ gdk_display_get_gl_context (GdkDisplay *self)
return priv->gl_context;
}
+#ifdef G_ENABLE_DEBUG
+static int
+strvcmp (gconstpointer p1,
+ gconstpointer p2)
+{
+ const char * const *s1 = p1;
+ const char * const *s2 = p2;
+
+ return strcmp (*s1, *s2);
+}
+
+static char *
+describe_extensions (EGLDisplay egl_display)
+{
+ const char *extensions;
+ char **exts;
+ char *ext;
+
+ extensions = eglQueryString (egl_display, EGL_EXTENSIONS);
+
+ exts = g_strsplit (extensions, " ", -1);
+ qsort (exts, g_strv_length (exts), sizeof (char *), strvcmp);
+
+ ext = g_strjoinv ("\n\t", exts);
+ if (ext[0] == '\n')
+ ext[0] = ' ';
+
+ g_strfreev (exts);
+
+ return g_strstrip (ext);
+}
+
+static char *
+describe_egl_config (EGLDisplay egl_display,
+ EGLConfig egl_config)
+{
+ EGLint red, green, blue, alpha, type;
+
+ if (egl_config == NULL)
+ return g_strdup ("-");
+
+ if (!eglGetConfigAttrib (egl_display, egl_config, EGL_RED_SIZE, &red) ||
+ !eglGetConfigAttrib (egl_display, egl_config, EGL_GREEN_SIZE, &green) ||
+ !eglGetConfigAttrib (egl_display, egl_config, EGL_BLUE_SIZE, &blue) ||
+ !eglGetConfigAttrib (egl_display, egl_config, EGL_ALPHA_SIZE, &alpha))
+ return g_strdup ("Unknown");
+
+ if (epoxy_has_egl_extension (egl_display, "EGL_EXT_pixel_format_float"))
+ {
+ if (!eglGetConfigAttrib (egl_display, egl_config, EGL_COLOR_COMPONENT_TYPE_EXT, &type))
+ type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+ }
+ else
+ type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+
+ return g_strdup_printf ("R%dG%dB%dA%d%s", red, green, blue, alpha, type ==
EGL_COLOR_COMPONENT_TYPE_FIXED_EXT ? "" : " float");
+}
+#endif
+
+/*<private>
+ * gdk_display_get_egl_display:
+ * @self: a display
+ *
+ * Retrieves the EGL display connection object for the given GDK display.
+ *
+ * This function returns `NULL` if GL is not supported or GDK is using
+ * a different OpenGL framework than EGL.
+ *
+ * Returns: (nullable): the EGL display object
+ */
+gpointer
+gdk_display_get_egl_display (GdkDisplay *self)
+{
+ GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
+
+ g_return_val_if_fail (GDK_IS_DISPLAY (self), NULL);
+
+ if (!priv->egl_display &&
+ !gdk_display_prepare_gl (self, NULL))
+ return NULL;
+
+ return priv->egl_display;
+}
+
+gpointer
+gdk_display_get_egl_config (GdkDisplay *self)
+{
+ GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
+
+ return priv->egl_config;
+}
+
+static EGLDisplay
+gdk_display_create_egl_display (EGLenum platform,
+ gpointer native_display)
+{
+ G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
+ EGLDisplay egl_display = NULL;
+
+ if (epoxy_has_egl_extension (NULL, "EGL_KHR_platform_base"))
+ {
+ PFNEGLGETPLATFORMDISPLAYPROC getPlatformDisplay =
+ (void *) eglGetProcAddress ("eglGetPlatformDisplay");
+
+ if (getPlatformDisplay != NULL)
+ egl_display = getPlatformDisplay (platform, native_display, NULL);
+ if (egl_display != NULL)
+ goto out;
+ }
+
+ if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base"))
+ {
+ PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay =
+ (void *) eglGetProcAddress ("eglGetPlatformDisplayEXT");
+
+ if (getPlatformDisplay != NULL)
+ egl_display = getPlatformDisplay (platform, native_display, NULL);
+ if (egl_display != NULL)
+ goto out;
+ }
+
+ egl_display = eglGetDisplay ((EGLNativeDisplayType) native_display);
+
+out:
+ gdk_profiler_end_mark (start_time, "Create EGL display", NULL);
+
+ return egl_display;
+}
+
+#define MAX_EGL_ATTRS 30
+
+typedef enum {
+ GDK_EGL_CONFIG_PERFECT = (1 << 0)
+} GdkEGLConfigCreateFlags;
+
+static EGLConfig
+gdk_display_create_egl_config (GdkDisplay *self,
+ GdkEGLConfigCreateFlags flags,
+ GError **error)
+{
+ GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
+ G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
+ EGLint attrs[MAX_EGL_ATTRS];
+ EGLConfig *configs;
+ EGLint count, alloced;
+ EGLConfig best_config;
+ guint best_score;
+
+ int i = 0;
+
+ attrs[i++] = EGL_SURFACE_TYPE;
+ attrs[i++] = EGL_WINDOW_BIT;
+
+ attrs[i++] = EGL_COLOR_BUFFER_TYPE;
+ attrs[i++] = EGL_RGB_BUFFER;
+
+ attrs[i++] = EGL_RED_SIZE;
+ attrs[i++] = 8;
+ attrs[i++] = EGL_GREEN_SIZE;
+ attrs[i++] = 8;
+ attrs[i++] = EGL_BLUE_SIZE;
+ attrs[i++] = 8;
+ attrs[i++] = EGL_ALPHA_SIZE;
+ attrs[i++] = 8;
+
+ attrs[i++] = EGL_NONE;
+ g_assert (i < MAX_EGL_ATTRS);
+
+ if (!eglChooseConfig (priv->egl_display, attrs, NULL, -1, &alloced) || alloced == 0)
+ {
+ g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
+ _("No EGL configuration available"));
+ return NULL;
+ }
+
+ configs = g_new (EGLConfig, alloced);
+ if (!eglChooseConfig (priv->egl_display, attrs, configs, alloced, &count))
+ {
+ g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
+ _("Failed to get EGL configurations"));
+ return NULL;
+ }
+ g_warn_if_fail (alloced == count);
+
+ best_score = G_MAXUINT;
+ best_config = NULL;
+
+ for (i = 0; i < count; i++)
+ {
+ guint score = GDK_DISPLAY_GET_CLASS (self)->rate_egl_config (self, priv->egl_display, configs[i]);
+
+ if (score < best_score)
+ {
+ best_score = score;
+ best_config = configs[i];
+ }
+
+ if (score == 0)
+ break;
+ }
+
+ g_free (configs);
+
+ gdk_profiler_end_mark (start_time, "Create EGL config", NULL);
+
+ if (best_score == G_MAXUINT)
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("No EGL configuration with required features found"));
+ return NULL;
+ }
+ else if ((flags & GDK_EGL_CONFIG_PERFECT) && best_score != 0)
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("No perfect EGL configuration found"));
+ return NULL;
+ }
+
+ return best_config;
+}
+
+#undef MAX_EGL_ATTRS
+
+
+gboolean
+gdk_display_init_egl (GdkDisplay *self,
+ int platform,
+ gpointer native_display,
+ gboolean allow_any,
+ GError **error)
+{
+ GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
+ G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
+ G_GNUC_UNUSED gint64 start_time2;
+ int major, minor;
+
+ if (!gdk_gl_backend_can_be_used (GDK_GL_EGL, error))
+ return FALSE;
+
+ if (!epoxy_has_egl ())
+ {
+ gboolean sandboxed = gdk_running_in_sandbox ();
+
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ sandboxed ? _("libEGL not available in this sandbox")
+ : _("libEGL not available"));
+ return FALSE;
+ }
+
+ priv->egl_display = gdk_display_create_egl_display (platform, native_display);
+
+ if (priv->egl_display == NULL)
+ {
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("Failed to create EGL display"));
+ return FALSE;
+ }
+
+ start_time2 = GDK_PROFILER_CURRENT_TIME;
+ if (!eglInitialize (priv->egl_display, &major, &minor))
+ {
+ priv->egl_display = NULL;
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("Could not initialize EGL display"));
+ return FALSE;
+ }
+ gdk_profiler_end_mark (start_time2, "eglInitialize", NULL);
+
+ if (major < GDK_EGL_MIN_VERSION_MAJOR ||
+ (major == GDK_EGL_MIN_VERSION_MAJOR && minor < GDK_EGL_MIN_VERSION_MINOR))
+ {
+ g_clear_pointer (&priv->egl_display, eglTerminate);
+ g_set_error (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_NOT_AVAILABLE,
+ _("EGL version %d.%d is too old. GTK requires %d.%d"),
+ major, minor, GDK_EGL_MIN_VERSION_MAJOR, GDK_EGL_MIN_VERSION_MINOR);
+ return FALSE;
+ }
+
+ if (!epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_surfaceless_context"))
+ {
+ g_clear_pointer (&priv->egl_display, eglTerminate);
+ g_set_error_literal (error, GDK_GL_ERROR,
+ GDK_GL_ERROR_UNSUPPORTED_PROFILE,
+ _("Surfaceless contexts are not supported on this EGL implementation"));
+ return FALSE;
+ }
+
+ priv->egl_config = gdk_display_create_egl_config (self,
+ allow_any ? 0 : GDK_EGL_CONFIG_PERFECT,
+ error);
+ if (priv->egl_config == NULL)
+ {
+ g_clear_pointer (&priv->egl_display, eglTerminate);
+ return FALSE;
+ }
+
+ GDK_DISPLAY_NOTE (self, OPENGL, {
+ char *ext = describe_extensions (priv->egl_display);
+ char *cfg = describe_egl_config (priv->egl_display, priv->egl_config);
+ g_message ("EGL API version %d.%d found\n"
+ " - Vendor: %s\n"
+ " - Version: %s\n"
+ " - Client APIs: %s\n"
+ " - Extensions:\n"
+ "\t%s"
+ " - Selected fbconfig: %s",
+ major, minor,
+ eglQueryString (priv->egl_display, EGL_VENDOR),
+ eglQueryString (priv->egl_display, EGL_VERSION),
+ eglQueryString (priv->egl_display, EGL_CLIENT_APIS),
+ ext, cfg);
+ g_free (cfg);
+ g_free (ext);
+ });
+
+
+ gdk_profiler_end_mark (start_time, "init EGL", NULL);
+
+ return TRUE;
+}
+
GdkDebugFlags
gdk_display_get_debug_flags (GdkDisplay *display)
{
diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h
index a85b275db7..dd0b1359b2 100644
--- a/gdk/gdkdisplayprivate.h
+++ b/gdk/gdkdisplayprivate.h
@@ -140,10 +140,15 @@ struct _GdkDisplayClass
GdkKeymap * (*get_keymap) (GdkDisplay *display);
- GdkGLContext * (*init_gl) (GdkDisplay *display,
+ GdkGLContext * (* init_gl) (GdkDisplay *display,
GError **error);
+ /* Returns the distance from a perfect score EGL config.
+ * GDK chooses the one with the *LOWEST* score */
+ guint (* rate_egl_config) (GdkDisplay *display,
+ gpointer egl_display,
+ gpointer egl_config);
- GdkSeat * (*get_default_seat) (GdkDisplay *display);
+ GdkSeat * (*get_default_seat) (GdkDisplay *display);
GListModel * (*get_monitors) (GdkDisplay *self);
GdkMonitor * (*get_monitor_at_surface) (GdkDisplay *display,
@@ -208,6 +213,14 @@ GdkSurface * gdk_display_create_surface (GdkDisplay *display
GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display);
+gboolean gdk_display_init_egl (GdkDisplay *display,
+ int /*EGLenum*/ platform,
+ gpointer native_display,
+ gboolean allow_any,
+ GError **error);
+gpointer gdk_display_get_egl_display (GdkDisplay *display);
+gpointer gdk_display_get_egl_config (GdkDisplay *display);
+
void gdk_display_set_rgba (GdkDisplay *display,
gboolean rgba);
void gdk_display_set_composited (GdkDisplay *display,
diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h
index 932f39cb6c..265bcd1883 100644
--- a/gdk/wayland/gdkdisplay-wayland.h
+++ b/gdk/wayland/gdkdisplay-wayland.h
@@ -151,10 +151,6 @@ struct _GdkWaylandDisplay
gint64 last_bell_time_ms;
/* egl info */
- EGLDisplay egl_display;
- EGLConfig egl_config;
- int egl_major_version;
- int egl_minor_version;
guint have_egl_buffer_age : 1;
guint have_egl_swap_buffers_with_damage : 1;
diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c
index e256277add..2f239ee929 100644
--- a/gdk/wayland/gdkglcontext-wayland.c
+++ b/gdk/wayland/gdkglcontext-wayland.c
@@ -56,7 +56,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkGLContext *share = gdk_display_get_gl_context (display);
- GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (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;
@@ -121,8 +122,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
legacy_bit ? "yes" : "no",
use_es ? "yes" : "no"));
- ctx = eglCreateContext (display_wayland->egl_display,
- display_wayland->egl_config,
+ ctx = eglCreateContext (egl_display,
+ egl_config,
share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
: EGL_NO_CONTEXT,
context_attribs);
@@ -147,8 +148,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
GDK_DISPLAY_NOTE (display, OPENGL,
g_message ("eglCreateContext failed, switching to OpenGLĀ ES"));
- ctx = eglCreateContext (display_wayland->egl_display,
- display_wayland->egl_config,
+ ctx = eglCreateContext (egl_display,
+ egl_config,
share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
: EGL_NO_CONTEXT,
context_attribs);
@@ -176,8 +177,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
GDK_DISPLAY_NOTE (display, OPENGL,
g_message ("eglCreateContext failed, switching to legacy"));
- ctx = eglCreateContext (display_wayland->egl_display,
- display_wayland->egl_config,
+ ctx = eglCreateContext (egl_display,
+ egl_config,
share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
: EGL_NO_CONTEXT,
context_attribs);
@@ -216,7 +217,7 @@ gdk_wayland_gl_context_get_damage (GdkGLContext *context)
{
egl_surface = gdk_wayland_surface_get_egl_surface (surface);
gdk_gl_context_make_current (context);
- eglQuerySurface (display_wayland->egl_display, egl_surface,
+ eglQuerySurface (gdk_display_get_egl_display (display), egl_surface,
EGL_BUFFER_AGE_EXT, &buffer_age);
switch (buffer_age)
@@ -252,9 +253,8 @@ static gboolean
gdk_wayland_gl_context_clear_current (GdkGLContext *context)
{
GdkDisplay *display = gdk_gl_context_get_display (context);
- GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
- return eglMakeCurrent (display_wayland->egl_display,
+ return eglMakeCurrent (gdk_display_get_egl_display (display),
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT);
@@ -266,7 +266,6 @@ gdk_wayland_gl_context_make_current (GdkGLContext *context,
{
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
GdkDisplay *display = gdk_gl_context_get_display (context);
- GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
EGLSurface egl_surface;
if (!surfaceless)
@@ -274,7 +273,7 @@ gdk_wayland_gl_context_make_current (GdkGLContext *context,
else
egl_surface = EGL_NO_SURFACE;
- return eglMakeCurrent (display_wayland->egl_display,
+ return eglMakeCurrent (gdk_display_get_egl_display (display),
egl_surface,
egl_surface,
context_wayland->egl_context);
@@ -333,11 +332,11 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
rects[j++] = rect.width * scale;
rects[j++] = rect.height * scale;
}
- eglSwapBuffersWithDamageEXT (display_wayland->egl_display, egl_surface, rects, n_rects);
+ eglSwapBuffersWithDamageEXT (gdk_display_get_egl_display (display), egl_surface, rects, n_rects);
g_free (heap_rects);
}
else
- eglSwapBuffers (display_wayland->egl_display, egl_surface);
+ eglSwapBuffers (gdk_display_get_egl_display (display), egl_surface);
gdk_wayland_surface_notify_committed (surface);
}
@@ -380,289 +379,44 @@ gdk_wayland_gl_context_init (GdkWaylandGLContext *self)
gpointer
gdk_wayland_display_get_egl_display (GdkDisplay *display)
{
- GdkWaylandDisplay *display_wayland;
-
g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), NULL);
- if (!gdk_display_prepare_gl (display, NULL))
- return NULL;
-
- display_wayland = GDK_WAYLAND_DISPLAY (display);
-
- return display_wayland->egl_display;
-}
-
-static EGLDisplay
-get_egl_display (GdkWaylandDisplay *display_wayland)
-{
- EGLDisplay dpy = NULL;
-
- if (epoxy_has_egl_extension (NULL, "EGL_KHR_platform_base"))
- {
- PFNEGLGETPLATFORMDISPLAYPROC getPlatformDisplay =
- (void *) eglGetProcAddress ("eglGetPlatformDisplay");
-
- if (getPlatformDisplay != NULL)
- dpy = getPlatformDisplay (EGL_PLATFORM_WAYLAND_EXT,
- display_wayland->wl_display,
- NULL);
- if (dpy != NULL)
- goto out;
- }
-
- if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base"))
- {
- PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay =
- (void *) eglGetProcAddress ("eglGetPlatformDisplayEXT");
-
- if (getPlatformDisplay != NULL)
- dpy = getPlatformDisplay (EGL_PLATFORM_WAYLAND_EXT,
- display_wayland->wl_display,
- NULL);
- if (dpy != NULL)
- goto out;
- }
-
- dpy = eglGetDisplay ((EGLNativeDisplayType) display_wayland->wl_display);
-
-out:
- return dpy;
+ return gdk_display_get_egl_display (display);
}
-#define MAX_EGL_ATTRS 30
-
-static EGLConfig
-get_eglconfig (EGLDisplay dpy)
-{
- EGLint attrs[MAX_EGL_ATTRS];
- EGLint count;
- EGLConfig config;
- int i = 0;
-
- attrs[i++] = EGL_SURFACE_TYPE;
- attrs[i++] = EGL_WINDOW_BIT;
-
- attrs[i++] = EGL_COLOR_BUFFER_TYPE;
- attrs[i++] = EGL_RGB_BUFFER;
-
- attrs[i++] = EGL_RED_SIZE;
- attrs[i++] = 8;
- attrs[i++] = EGL_GREEN_SIZE;
- attrs[i++] = 8;
- attrs[i++] = EGL_BLUE_SIZE;
- attrs[i++] = 8;
- attrs[i++] = EGL_ALPHA_SIZE;
- attrs[i++] = 8;
-
- attrs[i++] = EGL_NONE;
- g_assert (i < MAX_EGL_ATTRS);
-
- /* Pick first valid configuration i guess? */
- if (!eglChooseConfig (dpy, attrs, &config, 1, &count) || count < 1)
- return NULL;
-
- return config;
-}
-
-#undef MAX_EGL_ATTRS
-
-#ifdef G_ENABLE_DEBUG
-static int
-strvcmp (gconstpointer p1,
- gconstpointer p2)
-{
- const char * const *s1 = p1;
- const char * const *s2 = p2;
-
- return strcmp (*s1, *s2);
-}
-
-static char *
-describe_extensions (EGLDisplay dpy)
-{
- const char *extensions;
- char **exts;
- char *ext;
-
- extensions = eglQueryString (dpy, EGL_EXTENSIONS);
-
- exts = g_strsplit (extensions, " ", -1);
- qsort (exts, g_strv_length (exts), sizeof (char *), strvcmp);
-
- ext = g_strjoinv ("\n\t", exts);
- if (ext[0] == '\n')
- ext[0] = ' ';
-
- g_strfreev (exts);
-
- return g_strstrip (ext);
-}
-
-static char *
-describe_egl_config (EGLDisplay dpy,
- EGLConfig config)
-{
- EGLint red, green, blue, alpha, type;
-
- if (config == 0)
- return g_strdup ("-");
-
- if (!eglGetConfigAttrib (dpy, config, EGL_RED_SIZE, &red) ||
- !eglGetConfigAttrib (dpy, config, EGL_GREEN_SIZE, &green) ||
- !eglGetConfigAttrib (dpy, config, EGL_BLUE_SIZE, &blue) ||
- !eglGetConfigAttrib (dpy, config, EGL_ALPHA_SIZE, &alpha))
- return g_strdup ("Unknown");
-
- if (epoxy_has_egl_extension (dpy, "EGL_EXT_pixel_format_float"))
- {
- if (!eglGetConfigAttrib (dpy, config, EGL_COLOR_COMPONENT_TYPE_EXT, &type))
- type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
- }
- else
- type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
-
- return g_strdup_printf ("R%dG%dB%dA%d%s", red, green, blue, alpha, type ==
EGL_COLOR_COMPONENT_TYPE_FIXED_EXT ? "" : " float");
-}
-#endif
-
GdkGLContext *
gdk_wayland_display_init_gl (GdkDisplay *display,
GError **error)
{
- GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
- EGLint major, minor;
- EGLDisplay dpy;
- GdkGLContext *ctx;
- G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
- G_GNUC_UNUSED gint64 start_time2;
-
- if (!gdk_gl_backend_can_be_used (GDK_GL_EGL, error))
- return FALSE;
-
- if (!epoxy_has_egl ())
- {
- gboolean sandboxed = gdk_running_in_sandbox ();
-
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_NOT_AVAILABLE,
- sandboxed ? _("libEGL not available in this sandbox")
- : _("libEGL not available"));
- return NULL;
- }
-
- start_time2 = GDK_PROFILER_CURRENT_TIME;
- dpy = get_egl_display (display_wayland);
- gdk_profiler_end_mark (start_time, "get_egl_display", NULL);
- if (dpy == NULL)
- {
- gboolean sandboxed = gdk_running_in_sandbox ();
-
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_NOT_AVAILABLE,
- sandboxed ? _("Sandbox does not provide an OpenGL implementation")
- : _("No OpenGL implementation available"));
- return NULL;
- }
-
- start_time2 = GDK_PROFILER_CURRENT_TIME;
- if (!eglInitialize (dpy, &major, &minor))
- {
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_NOT_AVAILABLE,
- _("Could not initialize EGL display"));
- return NULL;
- }
- gdk_profiler_end_mark (start_time2, "eglInitialize", NULL);
-
- if (major < GDK_EGL_MIN_VERSION_MAJOR ||
- (major == GDK_EGL_MIN_VERSION_MAJOR && minor < GDK_EGL_MIN_VERSION_MINOR))
- {
- eglTerminate (dpy);
- g_set_error (error, GDK_GL_ERROR,
- GDK_GL_ERROR_NOT_AVAILABLE,
- _("EGL version %d.%d is too old. GTK requires %d.%d"),
- major, minor, GDK_EGL_MIN_VERSION_MAJOR, GDK_EGL_MIN_VERSION_MINOR);
- return NULL;
- }
+ GdkWaylandDisplay *self = GDK_WAYLAND_DISPLAY (display);
+ EGLDisplay egl_display;
+
+ if (!gdk_display_init_egl (display,
+ EGL_PLATFORM_WAYLAND_EXT,
+ self->wl_display,
+ TRUE,
+ error))
+ return NULL;
- start_time2 = GDK_PROFILER_CURRENT_TIME;
if (!eglBindAPI (EGL_OPENGL_API))
{
- eglTerminate (dpy);
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("No GL implementation is available"));
return NULL;
}
- gdk_profiler_end_mark (start_time2, "eglBindAPI", NULL);
- if (!epoxy_has_egl_extension (dpy, "EGL_KHR_create_context"))
- {
- eglTerminate (dpy);
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_UNSUPPORTED_PROFILE,
- _("Core GL is not available on EGL implementation"));
- return NULL;
- }
+ egl_display = gdk_display_get_egl_display (display);
- if (!epoxy_has_egl_extension (dpy, "EGL_KHR_surfaceless_context"))
- {
- eglTerminate (dpy);
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_UNSUPPORTED_PROFILE,
- _("Surfaceless contexts are not supported on this EGL implementation"));
- return NULL;
- }
+ self->have_egl_buffer_age =
+ epoxy_has_egl_extension (egl_display, "EGL_EXT_buffer_age");
- start_time2 = GDK_PROFILER_CURRENT_TIME;
- display_wayland->egl_config = get_eglconfig (dpy);
- gdk_profiler_end_mark (start_time2, "get_eglconfig", NULL);
- if (!display_wayland->egl_config)
- {
- eglTerminate (dpy);
- g_set_error_literal (error, GDK_GL_ERROR,
- GDK_GL_ERROR_UNSUPPORTED_FORMAT,
- _("No available configurations for the given pixel format"));
- return NULL;
- }
+ self->have_egl_swap_buffers_with_damage =
+ epoxy_has_egl_extension (egl_display, "EGL_EXT_swap_buffers_with_damage");
- display_wayland->egl_display = dpy;
- display_wayland->egl_major_version = major;
- display_wayland->egl_minor_version = minor;
-
- display_wayland->have_egl_buffer_age =
- epoxy_has_egl_extension (dpy, "EGL_EXT_buffer_age");
-
- display_wayland->have_egl_swap_buffers_with_damage =
- epoxy_has_egl_extension (dpy, "EGL_EXT_swap_buffers_with_damage");
-
- GDK_DISPLAY_NOTE (display, OPENGL, {
- char *ext = describe_extensions (dpy);
- char *cfg = describe_egl_config (dpy, display_wayland->egl_config);
- g_message ("EGL API version %d.%d found\n"
- " - Vendor: %s\n"
- " - Version: %s\n"
- " - Client APIs: %s\n"
- " - Extensions:\n"
- "\t%s\n"
- " - Selected fbconfig: %s",
- display_wayland->egl_major_version,
- display_wayland->egl_minor_version,
- eglQueryString (dpy, EGL_VENDOR),
- eglQueryString (dpy, EGL_VERSION),
- eglQueryString (dpy, EGL_CLIENT_APIS),
- ext, cfg);
- g_free (cfg);
- g_free (ext);
- });
-
- ctx = g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT,
- "display", display,
- NULL);
-
- gdk_profiler_end_mark (start_time, "init Wayland GL", NULL);
-
- return ctx;
+ return g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT,
+ "display", display,
+ NULL);
}
static void
@@ -675,16 +429,14 @@ gdk_wayland_gl_context_dispose (GObject *gobject)
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
GdkSurface *surface = gdk_gl_context_get_surface (context);
GdkDisplay *display = gdk_surface_get_display (surface);
- GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+ EGLDisplay *egl_display = gdk_display_get_egl_display (display);
if (eglGetCurrentContext () == context_wayland->egl_context)
- eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
+ eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Destroying EGL context"));
- eglDestroyContext (display_wayland->egl_display,
- context_wayland->egl_context);
+ eglDestroyContext (egl_display, context_wayland->egl_context);
context_wayland->egl_context = NULL;
}
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index 4d1951e66d..c1f1357165 100644
--- a/gdk/wayland/gdksurface-wayland.c
+++ b/gdk/wayland/gdksurface-wayland.c
@@ -2893,7 +2893,8 @@ unmap_popups_for_surface (GdkSurface *surface)
static void
gdk_wayland_surface_hide_surface (GdkSurface *surface)
{
- GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
+ GdkDisplay *display = gdk_surface_get_display (surface);
+ GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
unmap_popups_for_surface (surface);
@@ -2902,7 +2903,7 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
{
if (impl->egl_surface)
{
- eglDestroySurface (display_wayland->egl_display, impl->egl_surface);
+ eglDestroySurface (gdk_display_get_egl_display (display), impl->egl_surface);
impl->egl_surface = NULL;
}
@@ -4351,7 +4352,7 @@ gdk_wayland_surface_get_wl_egl_window (GdkSurface *surface)
EGLSurface
gdk_wayland_surface_get_egl_surface (GdkSurface *surface)
{
- GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
+ GdkDisplay *display = gdk_surface_get_display (surface);
GdkWaylandSurface *impl;
struct wl_egl_window *egl_window;
@@ -4363,8 +4364,10 @@ gdk_wayland_surface_get_egl_surface (GdkSurface *surface)
{
egl_window = gdk_wayland_surface_get_wl_egl_window (surface);
- impl->egl_surface =
- eglCreateWindowSurface (display->egl_display, display->egl_config, egl_window, NULL);
+ impl->egl_surface = eglCreateWindowSurface (gdk_display_get_egl_display (display),
+ gdk_display_get_egl_config (display),
+ egl_window,
+ NULL);
}
return impl->egl_surface;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]