From cb6df570a4fc83fcc65b2e5d8577685cf15d2cbe Mon Sep 17 00:00:00 2001 From: BearOso Date: Wed, 31 May 2023 17:08:52 -0500 Subject: [PATCH] Gtk: Make wayland surfaces toolkit-agnostic. --- gtk/src/gtk_display_driver_opengl.cpp | 27 +++++++++++++++++++-- gtk/src/gtk_display_driver_vulkan.cpp | 15 ++++++++++-- gtk/src/gtk_wayland_egl_context.cpp | 13 +++------- gtk/src/gtk_wayland_egl_context.h | 8 +++--- gtk/src/gtk_wayland_surface.cpp | 35 +++++++++------------------ gtk/src/gtk_wayland_surface.h | 18 ++++++-------- 6 files changed, 65 insertions(+), 51 deletions(-) diff --git a/gtk/src/gtk_display_driver_opengl.cpp b/gtk/src/gtk_display_driver_opengl.cpp index c98674d3..53f324d6 100644 --- a/gtk/src/gtk_display_driver_opengl.cpp +++ b/gtk/src/gtk_display_driver_opengl.cpp @@ -65,6 +65,14 @@ static const GLchar *stock_fragment_shader_140 = " fragcolor = texture(texmap, texcoord);\n" "}\n"; +#ifdef GDK_WINDOWING_WAYLAND +static WaylandSurface::Metrics get_metrics(Gtk::DrawingArea &w) +{ + int x, y, width, height; + w.get_window()->get_geometry(x, y, width, height); + return { x, y, width, height, w.get_window()->get_scale_factor() }; +} +#endif static GLfloat coords[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; @@ -335,7 +343,20 @@ void S9xOpenGLDisplayDriver::refresh() void S9xOpenGLDisplayDriver::resize() { - context->resize(); +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_WINDOW(gdk_window)) + { + ((WaylandEGLContext *)context)->resize(get_metrics(*drawing_area)); + } +#endif +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_WINDOW(gdk_window)) + { + context->resize(); + } +#endif + + context->swap_interval(config->sync_to_vblank); Gtk::Allocation allocation = drawing_area->get_allocation(); output_window_width = allocation.get_width(); @@ -350,7 +371,9 @@ bool S9xOpenGLDisplayDriver::create_context() #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_WINDOW(gdk_window)) { - if (!wl.attach(GTK_WIDGET(drawing_area->gobj()))) + wl_surface *surface = gdk_wayland_window_get_wl_surface(drawing_area->get_window()->gobj()); + wl_display *display = gdk_wayland_display_get_wl_display(drawing_area->get_display()->gobj()); + if (!wl.attach(display, surface, get_metrics(*drawing_area))) return false; context = &wl; } diff --git a/gtk/src/gtk_display_driver_vulkan.cpp b/gtk/src/gtk_display_driver_vulkan.cpp index 64220b8a..7ba7b622 100644 --- a/gtk/src/gtk_display_driver_vulkan.cpp +++ b/gtk/src/gtk_display_driver_vulkan.cpp @@ -15,6 +15,15 @@ #include "snes9x_imgui.h" #include "../../external/imgui/imgui_impl_vulkan.h" +#ifdef GDK_WINDOWING_WAYLAND +static WaylandSurface::Metrics get_metrics(Gtk::DrawingArea &w) +{ + int x, y, width, height; + w.get_window()->get_geometry(x, y, width, height); + return { x, y, width, height, w.get_window()->get_scale_factor() }; +} +#endif + S9xVulkanDisplayDriver::S9xVulkanDisplayDriver(Snes9xWindow *_window, Snes9xConfig *_config) { window = _window; @@ -83,7 +92,7 @@ void S9xVulkanDisplayDriver::refresh() #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj())) { - wayland_surface->resize(); + wayland_surface->resize(get_metrics(*drawing_area)); std::tie(new_width, new_height) = wayland_surface->get_size(); } else @@ -113,7 +122,9 @@ int S9xVulkanDisplayDriver::init() if (GDK_IS_WAYLAND_WINDOW(drawing_area->get_window()->gobj())) { wayland_surface = std::make_unique(); - if (!wayland_surface->attach(GTK_WIDGET(drawing_area->gobj()))) + wl_surface *surface = gdk_wayland_window_get_wl_surface(drawing_area->get_window()->gobj()); + wl_display *display = gdk_wayland_display_get_wl_display(drawing_area->get_display()->gobj()); + if (!wayland_surface->attach(display, surface, get_metrics(*drawing_area))) { return -1; } diff --git a/gtk/src/gtk_wayland_egl_context.cpp b/gtk/src/gtk_wayland_egl_context.cpp index ab28c64e..99c8be9d 100644 --- a/gtk/src/gtk_wayland_egl_context.cpp +++ b/gtk/src/gtk_wayland_egl_context.cpp @@ -33,15 +33,10 @@ WaylandEGLContext::~WaylandEGLContext() wl_egl_window_destroy(egl_window); } -bool WaylandEGLContext::attach(GtkWidget *widget) +bool WaylandEGLContext::attach(wl_display *display, wl_surface *surface, WaylandSurface::Metrics m) { - GdkWindow *window = gtk_widget_get_window(widget); - - if (!GDK_IS_WAYLAND_WINDOW(window)) - return false; - wayland_surface = std::make_unique(); - wayland_surface->attach(widget); + wayland_surface->attach(display, surface, m); return true; } @@ -109,9 +104,9 @@ bool WaylandEGLContext::create_context() return true; } -void WaylandEGLContext::resize() +void WaylandEGLContext::resize(WaylandSurface::Metrics m) { - wayland_surface->resize(); + wayland_surface->resize(m); std::tie(width, height) = wayland_surface->get_size(); wl_egl_window_resize(egl_window, width, height, 0, 0); diff --git a/gtk/src/gtk_wayland_egl_context.h b/gtk/src/gtk_wayland_egl_context.h index 9af30751..c9513ffa 100644 --- a/gtk/src/gtk_wayland_egl_context.h +++ b/gtk/src/gtk_wayland_egl_context.h @@ -9,7 +9,6 @@ #include "gtk_opengl_context.h" #include "gtk_wayland_surface.h" -#include "gtk_compat.h" #include #include @@ -20,16 +19,15 @@ class WaylandEGLContext : public OpenGLContext public: WaylandEGLContext(); ~WaylandEGLContext(); - bool attach(GtkWidget *widget); + bool attach(wl_display *display, wl_surface *surface, WaylandSurface::Metrics m); bool create_context(); - void resize(); + void resize() {}; + void resize(WaylandSurface::Metrics m); void swap_buffers(); void swap_interval(int frames); void make_current(); bool ready(); - GdkWindow *gdk_window; - EGLDisplay egl_display; EGLSurface egl_surface; EGLContext egl_context; diff --git a/gtk/src/gtk_wayland_surface.cpp b/gtk/src/gtk_wayland_surface.cpp index 4d832c00..933ee0d6 100644 --- a/gtk/src/gtk_wayland_surface.cpp +++ b/gtk/src/gtk_wayland_surface.cpp @@ -106,19 +106,11 @@ wp_fractional_scale_v1_listener fractional_scale_v1_listener = preferred_scale }; -bool WaylandSurface::attach(GtkWidget *widget) +bool WaylandSurface::attach(wl_display *display, wl_surface *surface, Metrics m) { - GdkWindow *window = gtk_widget_get_window(widget); - - if (!GDK_IS_WAYLAND_WINDOW(window)) - return false; - - gdk_window = window; - gdk_window_get_geometry(gdk_window, &x, &y, &width, &height); - gdk_scale = gdk_window_get_scale_factor(gdk_window); - - display = gdk_wayland_display_get_wl_display(gdk_window_get_display(gdk_window)); - parent = gdk_wayland_window_get_wl_surface(gdk_window); + metrics = m; + this->display = display; + parent = surface; registry = wl_display_get_registry(display); wl_registry_add_listener(registry, &wl_registry_listener, this); @@ -133,7 +125,7 @@ bool WaylandSurface::attach(GtkWidget *widget) wl_surface_set_input_region(child, region); wl_subsurface_set_desync(subsurface); - wl_subsurface_set_position(subsurface, x, y); + wl_subsurface_set_position(subsurface, m.x, m.y); if (fractional_scale_manager) { @@ -147,29 +139,26 @@ bool WaylandSurface::attach(GtkWidget *widget) zwp_idle_inhibit_manager_v1_create_inhibitor(idle_inhibit_manager, child); } - resize(); + resize(m); return true; } std::tuple WaylandSurface::get_size() { - gdk_window_get_geometry(gdk_window, &x, &y, &width, &height); - if (actual_scale == 0.0) { - gdk_scale = gdk_window_get_scale_factor(gdk_window); - - return { width * gdk_scale, height * gdk_scale }; + return { metrics.width * metrics.scale, metrics.height * metrics.scale }; } - return { width * actual_scale, height * actual_scale }; + return { metrics.width * actual_scale, metrics.height * actual_scale }; } -void WaylandSurface::resize() +void WaylandSurface::resize(Metrics m) { + metrics = m; auto [w, h] = get_size(); - wl_subsurface_set_position(subsurface, x, y); + wl_subsurface_set_position(subsurface, m.x, m.y); if (!viewport) viewport = wp_viewporter_get_viewport(viewporter, child); @@ -177,7 +166,7 @@ void WaylandSurface::resize() wp_viewport_set_source(viewport, wl_fixed_from_int(0), wl_fixed_from_int(0), wl_fixed_from_int(w), wl_fixed_from_int(h)); - wp_viewport_set_destination(viewport, width, height); + wp_viewport_set_destination(viewport, m.width, m.height); wl_surface_commit(child); wl_surface_commit(parent); diff --git a/gtk/src/gtk_wayland_surface.h b/gtk/src/gtk_wayland_surface.h index ddc5d21e..cead1baf 100644 --- a/gtk/src/gtk_wayland_surface.h +++ b/gtk/src/gtk_wayland_surface.h @@ -6,7 +6,6 @@ #pragma once -#include "gtk_compat.h" #include "viewporter-client-protocol.h" #include "fractional-scale-v1.h" @@ -15,11 +14,14 @@ class WaylandSurface public: WaylandSurface(); ~WaylandSurface(); - bool attach(GtkWidget *widget); - void resize(); - std::tuple get_size(); - GdkWindow *gdk_window; + struct Metrics { + int x, y, width, height, scale; + }; + + bool attach(wl_display *display, wl_surface *surface, Metrics source_metrics); + void resize(Metrics new_metrics); + std::tuple get_size(); struct wl_display *display; struct wl_registry *registry; @@ -31,11 +33,7 @@ class WaylandSurface struct wl_subsurface *subsurface; struct wl_region *region; - int x; - int y; - int width; - int height; - int gdk_scale; + Metrics metrics; double actual_scale; struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;