From: Benjamin Otte Date: Sun, 3 Oct 2021 04:22:21 +0000 (+0200) Subject: egl: Move initialization code and port Wayland X-Git-Tag: archive/raspbian/4.6.5+ds-1+rpi1~1^2~19^2~5^2~258^2~16 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=bfb158d773bc686a014cc818985bf99aff347b17;p=gtk4.git 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. --- diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index 71d47f1d30..6f9bdec930 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -36,6 +36,9 @@ #include "gdkglcontextprivate.h" #include "gdkmonitorprivate.h" +#ifdef HAVE_EGL +#include +#endif #include /** @@ -87,6 +90,11 @@ struct _GdkDisplayPrivate { GdkGLContext *gl_context; GError *gl_error; +#ifdef HAVE_EGL + EGLDisplay egl_display; + EGLConfig egl_config; +#endif + guint rgba : 1; guint composited : 1; guint input_shapes : 1; @@ -146,6 +154,26 @@ 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; +#ifdef HAVE_EGL + 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; +#endif + + return distance; +} + static GdkSeat * gdk_display_real_get_default_seat (GdkDisplay *display) { @@ -173,6 +201,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 +381,9 @@ gdk_display_dispose (GObject *object) g_queue_clear (&display->queued_events); g_clear_object (&priv->gl_context); +#ifdef HAVE_EGL + g_clear_pointer (&priv->egl_display, eglTerminate); +#endif g_clear_error (&priv->gl_error); G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object); @@ -1312,6 +1344,335 @@ gdk_display_get_gl_context (GdkDisplay *self) return priv->gl_context; } +#ifdef HAVE_EGL +#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 + +/* + * 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; +} +#endif + 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 834cbc8510..29d2761ddd 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); @@ -332,11 +331,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); } @@ -379,289 +378,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 @@ -674,16 +428,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;