From e70675db9843c4d8757fa4ed8e97bdf1d9bf7a13 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 18 Oct 2018 17:47:39 -0500 Subject: [PATCH] Basic OpenGL on Wayland. Fullscreen is broken. --- gtk/configure.ac | 7 ++ gtk/src/gtk_display.cpp | 12 ++- gtk/src/gtk_display_driver_opengl.cpp | 110 +++++++++++++++++++++++--- gtk/src/gtk_display_driver_opengl.h | 21 +++++ gtk/src/gtk_preferences.cpp | 1 - 5 files changed, 134 insertions(+), 17 deletions(-) diff --git a/gtk/configure.ac b/gtk/configure.ac index 54c109dc..0ac8e514 100644 --- a/gtk/configure.ac +++ b/gtk/configure.ac @@ -223,6 +223,13 @@ if test yes = "$with_opengl" ; then LIBS="$LIBS $EPOXY_LIBS" fi +PKG_CHECK_MODULES([WAYLAND_EGL],[wayland-egl],[ + CFLAGS="$CFLAGS $WAYLAND_EGL_CFLAGS" + LIBS="$LIBS $WAYLAND_EGL_LIBS" +],[ + echo "Not using Wayland-EGL." +]) + GTKJOY=0 SDL_CFLAGS="" SDL_LIBS="" diff --git a/gtk/src/gtk_display.cpp b/gtk/src/gtk_display.cpp index 7616e55b..3845d0b9 100644 --- a/gtk/src/gtk_display.cpp +++ b/gtk/src/gtk_display.cpp @@ -1595,8 +1595,6 @@ S9xQueryDrivers (void) #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_DISPLAY (display)) { - int error_base_p, event_base_p; - int major_version, minor_version; Display *dpy = gdk_x11_display_get_xdisplay (gtk_widget_get_display (GTK_WIDGET (top_level->get_window()))); Window xid = gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (top_level->get_window()))); @@ -1616,15 +1614,15 @@ S9xDeinitUpdate (int width, int height) { GdkWindow *gdk_window = gtk_widget_get_window (GTK_WIDGET (top_level->get_window ())); -#ifdef GDK_WINDOWING_X11 - if (GDK_IS_X11_WINDOW (gdk_window)) +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_WINDOW (gdk_window) && gui_config->hw_accel == 0) { - return S9xRealDeinitUpdate (width, height); + gtk_widget_queue_draw (GTK_WIDGET (top_level->drawing_area)); + return TRUE; } #endif - gtk_widget_queue_draw (GTK_WIDGET (top_level->drawing_area)); - return TRUE; + return S9xRealDeinitUpdate (width, height); } bool8 diff --git a/gtk/src/gtk_display_driver_opengl.cpp b/gtk/src/gtk_display_driver_opengl.cpp index 282151dc..da160f1a 100644 --- a/gtk/src/gtk_display_driver_opengl.cpp +++ b/gtk/src/gtk_display_driver_opengl.cpp @@ -19,6 +19,15 @@ #include "shaders/shader_helpers.h" +static bool +on_wayland (void) +{ +#ifdef GDK_WINDOWING_WAYLAND + return (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())); +#endif + return 0; +} + static void S9xViewportCallback (int src_width, int src_height, int viewport_x, int viewport_y, int viewport_width, int viewport_height, @@ -65,9 +74,11 @@ S9xOpenGLDisplayDriver::update (int width, int height, int yoffset) #if GTK_CHECK_VERSION(3,10,0) int gdk_scale_factor = gdk_window_get_scale_factor (gdk_window); - allocation.width *= gdk_scale_factor; - allocation.height *= gdk_scale_factor; - + if (!on_wayland ()) + { + allocation.width *= gdk_scale_factor; + allocation.height *= gdk_scale_factor; + } #endif if (using_glsl_shaders) @@ -683,6 +694,36 @@ S9xOpenGLDisplayDriver::resize_window (int width, int height) return; } +#ifdef GDK_WINDOWING_WAYLAND +static void wl_global (void *data, + struct wl_registry *wl_registry, + uint32_t name, + const char *interface, + uint32_t version) +{ + struct wl_collection *wl = (struct wl_collection *) data; + + if (!strcmp (interface, "wl_compositor")) + wl->compositor = (struct wl_compositor *) wl_registry_bind (wl_registry, name, &wl_compositor_interface, 1); + else if (!strcmp (interface, "wl_subcompositor")) + wl->subcompositor = (struct wl_subcompositor *) wl_registry_bind (wl_registry, name, &wl_subcompositor_interface, 1); + + return; +} + +static void wl_global_remove (void *data, + struct wl_registry *wl_registry, + uint32_t name) +{ + return; +} + +static const struct wl_registry_listener wl_registry_listener = { + wl_global, + wl_global_remove +}; +#endif + void S9xOpenGLDisplayDriver::create_window (int width, int height) { @@ -695,15 +736,44 @@ S9xOpenGLDisplayDriver::create_window (int width, int height) if (GDK_IS_X11_WINDOW (gdk_window)) { xwindow = GDK_COMPAT_WINDOW_XID (gdk_window); - egl_surface = eglCreateWindowSurface (egl_display, egl_config, xwindow, NULL); + egl_surface = eglCreateWindowSurface (egl_display, egl_config, (EGLNativeWindowType) xwindow, NULL); } #endif #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_WINDOW (gdk_window)) { - struct wl_surface *surface; - surface = gdk_wayland_window_get_wl_surface (gdk_window); - egl_surface = eglCreatePlatformWindowSurface (egl_display, egl_config, surface, NULL); + int x, y, w, h; + gdk_window_get_geometry (gdk_window, &x, &y, &w, &h); + + /* Gets whole window surface */ + wl.parent = gdk_wayland_window_get_wl_surface (gdk_window); + wl.display = gdk_wayland_display_get_wl_display (gdk_window_get_display (gdk_window)); + wl.registry = wl_display_get_registry (wl.display); + wl.compositor = NULL; + wl.subcompositor = NULL; + wl_registry_add_listener (wl.registry, &wl_registry_listener, &wl); + wl_display_roundtrip (wl.display); + + if (!wl.compositor || !wl.subcompositor) + return; + + if (!wl.child) + wl.child = wl_compositor_create_surface (wl.compositor); + + if (!wl.subsurface) + { + wl.subsurface = wl_subcompositor_get_subsurface (wl.subcompositor, wl.child, wl.parent); + wl_subsurface_set_desync (wl.subsurface); + wl_subsurface_set_position (wl.subsurface, x, y); + } + + if (wl.egl_window) + wl_egl_window_resize (wl.egl_window, w, h, 0, 0); + else + wl.egl_window = wl_egl_window_create (wl.child, w, h); + + if (!egl_surface) + egl_surface = eglCreateWindowSurface (egl_display, egl_config, (EGLNativeWindowType) wl.egl_window, NULL); } #endif } @@ -754,14 +824,14 @@ S9xOpenGLDisplayDriver::init_gl (void) if (GDK_IS_X11_DISPLAY (d)) { display = GDK_DISPLAY_XDISPLAY (d); - egl_display = eglGetDisplay (display); + egl_display = eglGetDisplay ((EGLNativeDisplayType) display); } #endif #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_DISPLAY (d)) { struct wl_display *wl_d = gdk_wayland_display_get_wl_display (d); - egl_display = eglGetPlatformDisplay (EGL_PLATFORM_WAYLAND_KHR, wl_d, NULL); + egl_display = eglGetDisplay ((EGLNativeDisplayType) wl_d); } #endif if (!egl_display) @@ -777,6 +847,10 @@ S9xOpenGLDisplayDriver::init_gl (void) return 0; } +#ifdef GDK_WINDOWING_WAYLAND + if (on_wayland ()) + memset (&wl, 0, sizeof (wl)); +#endif create_window (1, 1); if (!egl_surface) { @@ -938,7 +1012,13 @@ void S9xOpenGLDisplayDriver::gl_swap (void) { if (using_egl) + { eglSwapBuffers (egl_display, egl_surface); +#ifdef GDK_WINDOWING_WAYLAND + if (on_wayland ()) + wl_surface_commit (wl.child); +#endif + } #ifdef GDK_WINDOWING_X11 else glXSwapBuffers (display, xwindow); @@ -997,6 +1077,17 @@ S9xOpenGLDisplayDriver::deinit (void) { eglDestroyContext (egl_display, egl_context); eglDestroySurface (egl_display, egl_surface); +#ifdef GDK_WINDOWING_WAYLAND + if (on_wayland ()) + { + if (wl.egl_window) + wl_egl_window_destroy (wl.egl_window); + if (wl.subsurface) + wl_subsurface_destroy (wl.subsurface); + if (wl.child) + wl_surface_destroy (wl.child); + } +#endif } #ifdef GDK_WINDOWING_X11 else @@ -1007,6 +1098,7 @@ S9xOpenGLDisplayDriver::deinit (void) XFreeColormap (display, xcolormap); } #endif + return; } diff --git a/gtk/src/gtk_display_driver_opengl.h b/gtk/src/gtk_display_driver_opengl.h index dbfc1628..9023e4cd 100644 --- a/gtk/src/gtk_display_driver_opengl.h +++ b/gtk/src/gtk_display_driver_opengl.h @@ -28,6 +28,23 @@ #define PBO_GET_FORMAT(x) (((x) == PBO_FMT_32) ? GL_BGRA : GL_RGB) #define PBO_GET_PACKING(x) (((x) == PBO_FMT_16) ? GL_UNSIGNED_SHORT_5_6_5 : (((x) == PBO_FMT_24) ? GL_UNSIGNED_BYTE : PBO_BGRA_NATIVE_ORDER)) +#ifdef GDK_WINDOWING_WAYLAND +#include +#include + +struct wl_collection { + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_subcompositor *subcompositor; + struct wl_surface *parent; + struct wl_surface *child; + struct wl_subsurface *subsurface; + struct wl_egl_window *egl_window; +}; + +#endif + class S9xOpenGLDisplayDriver : public S9xDisplayDriver { public: @@ -87,6 +104,10 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver GLXContext glx_context; #endif +#ifdef GDK_WINDOWING_WAYLAND + struct wl_collection wl; +#endif + bool using_egl; EGLDisplay egl_display; EGLContext egl_context; diff --git a/gtk/src/gtk_preferences.cpp b/gtk/src/gtk_preferences.cpp index 67b47474..6c4584f8 100644 --- a/gtk/src/gtk_preferences.cpp +++ b/gtk/src/gtk_preferences.cpp @@ -1129,7 +1129,6 @@ Snes9xPreferences::show (void) else { gtk_widget_hide (get_widget ("resolution_box")); - gtk_widget_hide (get_widget ("set_input_rate_button")); } #ifdef USE_HQ2X