Gtk: Make wayland surfaces toolkit-agnostic.

This commit is contained in:
BearOso 2023-05-31 17:08:52 -05:00
parent 02ebcb496a
commit cb6df570a4
6 changed files with 65 additions and 51 deletions

View File

@ -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()
{
#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;
}

View File

@ -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<WaylandSurface>();
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;
}

View File

@ -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<WaylandSurface>();
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);

View File

@ -9,7 +9,6 @@
#include "gtk_opengl_context.h"
#include "gtk_wayland_surface.h"
#include "gtk_compat.h"
#include <epoxy/egl.h>
#include <memory>
@ -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;

View File

@ -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<int, int> 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);

View File

@ -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<int, int> 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<int, int> 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;