From fd04c8ca57f876e0967eacd192a7546aee558193 Mon Sep 17 00:00:00 2001 From: zoltanvb <101990835+zoltanvb@users.noreply.github.com> Date: Thu, 30 Nov 2023 12:29:38 +0100 Subject: [PATCH] Rebase of wakira's wp_fractional_scale_v1 support (#15965) A rebase of earlier PR https://github.com/libretro/RetroArch/pull/15355 No changes added (except for one log). --- .gitignore | 4 + Makefile.common | 1 + .../staging/fractional-scale/README | 4 + .../fractional-scale/fractional-scale-v1.xml | 102 ++++++++++++++++++ gfx/common/wayland/generate_wayland_protos.sh | 2 +- gfx/common/wayland_common.c | 73 ++++++++----- gfx/drivers_context/wayland_ctx.c | 9 +- gfx/drivers_context/wayland_vk_ctx.c | 4 +- input/common/wayland_common.c | 54 +++++++--- input/common/wayland_common.h | 14 ++- 10 files changed, 220 insertions(+), 47 deletions(-) create mode 100644 deps/wayland-protocols/staging/fractional-scale/README create mode 100644 deps/wayland-protocols/staging/fractional-scale/fractional-scale-v1.xml diff --git a/.gitignore b/.gitignore index 49eb8cbffb..996bbf2437 100644 --- a/.gitignore +++ b/.gitignore @@ -213,6 +213,10 @@ retroarch_switch.nso *_irx.c # Wayland +gfx/common/wayland/fractional-scale-v1.c +gfx/common/wayland/fractional-scale-v1.h +gfx/common/wayland/viewporter.c +gfx/common/wayland/viewporter.h gfx/common/wayland/idle-inhibit-unstable-v1.c gfx/common/wayland/idle-inhibit-unstable-v1.h gfx/common/wayland/xdg-shell-unstable-v6.c diff --git a/Makefile.common b/Makefile.common index ef418f679b..ecab263bbd 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1240,6 +1240,7 @@ ifeq ($(HAVE_WAYLAND), 1) input/common/wayland_common.o \ input/drivers/wayland_input.o \ gfx/common/wayland_common.o \ + gfx/common/wayland/fractional-scale-v1.o \ gfx/common/wayland/viewporter.o \ gfx/common/wayland/xdg-shell.o \ gfx/common/wayland/idle-inhibit-unstable-v1.o \ diff --git a/deps/wayland-protocols/staging/fractional-scale/README b/deps/wayland-protocols/staging/fractional-scale/README new file mode 100644 index 0000000000..6cb0475f27 --- /dev/null +++ b/deps/wayland-protocols/staging/fractional-scale/README @@ -0,0 +1,4 @@ +wp fractional scale protocol + +Maintainers: +Kenny Levinsen diff --git a/deps/wayland-protocols/staging/fractional-scale/fractional-scale-v1.xml b/deps/wayland-protocols/staging/fractional-scale/fractional-scale-v1.xml new file mode 100644 index 0000000000..350bfc01ea --- /dev/null +++ b/deps/wayland-protocols/staging/fractional-scale/fractional-scale-v1.xml @@ -0,0 +1,102 @@ + + + + Copyright © 2022 Kenny Levinsen + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This protocol allows a compositor to suggest for surfaces to render at + fractional scales. + + A client can submit scaled content by utilizing wp_viewport. This is done by + creating a wp_viewport object for the surface and setting the destination + rectangle to the surface size before the scale factor is applied. + + The buffer size is calculated by multiplying the surface size by the + intended scale. + + The wl_surface buffer scale should remain set to 1. + + If a surface has a surface-local size of 100 px by 50 px and wishes to + submit buffers with a scale of 1.5, then a buffer of 150px by 75 px should + be used and the wp_viewport destination rectangle should be 100 px by 50 px. + + For toplevel surfaces, the size is rounded halfway away from zero. The + rounding algorithm for subsurface position and size is not defined. + + + + + A global interface for requesting surfaces to use fractional scales. + + + + + Informs the server that the client will not be using this protocol + object anymore. This does not affect any other objects, + wp_fractional_scale_v1 objects included. + + + + + + + + + + Create an add-on object for the the wl_surface to let the compositor + request fractional scales. If the given wl_surface already has a + wp_fractional_scale_v1 object associated, the fractional_scale_exists + protocol error is raised. + + + + + + + + + An additional interface to a wl_surface object which allows the compositor + to inform the client of the preferred scale. + + + + + Destroy the fractional scale object. When this object is destroyed, + preferred_scale events will no longer be sent. + + + + + + Notification of a new preferred scale for this surface that the + compositor suggests that the client should use. + + The sent scale is the numerator of a fraction with a denominator of 120. + + + + + diff --git a/gfx/common/wayland/generate_wayland_protos.sh b/gfx/common/wayland/generate_wayland_protos.sh index 1670b26eb4..5c9347428b 100755 --- a/gfx/common/wayland/generate_wayland_protos.sh +++ b/gfx/common/wayland/generate_wayland_protos.sh @@ -67,4 +67,4 @@ generate_source 'unstable/xdg-decoration' 'xdg-decoration-unstable-v1' generate_source 'unstable/idle-inhibit' 'idle-inhibit-unstable-v1' generate_source 'unstable/pointer-constraints' 'pointer-constraints-unstable-v1' generate_source 'unstable/relative-pointer' 'relative-pointer-unstable-v1' - +generate_source 'staging/fractional-scale' 'fractional-scale-v1' diff --git a/gfx/common/wayland_common.c b/gfx/common/wayland_common.c index a0a2158d1a..817f9e3cc7 100644 --- a/gfx/common/wayland_common.c +++ b/gfx/common/wayland_common.c @@ -128,11 +128,13 @@ void xdg_toplevel_handle_configure_common(gfx_ctx_wayland_data_t *wl, if ( (width > 0) && (height > 0)) { - wl->width = width; - wl->height = height; - wl->buffer_width = wl->width * wl->buffer_scale; - wl->buffer_height = wl->height * wl->buffer_scale; - wl->resize = true; + wl->width = width; + wl->height = height; + wl->buffer_width = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(wl->width, wl->fractional_scale_num) : wl->width * wl->buffer_scale; + wl->buffer_height = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(wl->height, wl->fractional_scale_num) : wl->height * wl->buffer_scale; + wl->resize = true; if (wl->viewport) /* Update viewport */ wp_viewport_set_destination(wl->viewport, wl->width, wl->height); } @@ -193,8 +195,10 @@ void libdecor_frame_handle_configure_common(struct libdecor_frame *frame, { wl->width = width; wl->height = height; - wl->buffer_width = width * wl->buffer_scale; - wl->buffer_height = height * wl->buffer_scale; + wl->buffer_width = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(width, wl->fractional_scale_num) : width * wl->buffer_scale; + wl->buffer_height = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(height, wl->fractional_scale_num) : height * wl->buffer_scale; wl->resize = true; if (wl->viewport) /* Update viewport */ wp_viewport_set_destination(wl->viewport, wl->width, wl->height); @@ -243,8 +247,10 @@ void gfx_ctx_wl_get_video_size_common(void *data, } else { - *width = wl->width * wl->pending_buffer_scale; - *height = wl->height * wl->pending_buffer_scale; + *width = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(wl->width, wl->pending_fractional_scale_num) : wl->width * wl->pending_buffer_scale; + *height = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(wl->height, wl->pending_fractional_scale_num) : wl->height * wl->pending_buffer_scale; } } @@ -271,6 +277,8 @@ void gfx_ctx_wl_destroy_resources_common(gfx_ctx_wayland_data_t *wl) if (wl->viewport) wp_viewport_destroy(wl->viewport); + if (wl->fractional_scale) + wp_fractional_scale_v1_destroy(wl->fractional_scale); if (wl->idle_inhibitor) zwp_idle_inhibitor_v1_destroy(wl->idle_inhibitor); if (wl->deco) @@ -322,6 +330,8 @@ void gfx_ctx_wl_destroy_resources_common(gfx_ctx_wayland_data_t *wl) wl_shm_destroy (wl->shm); if (wl->viewporter) wp_viewporter_destroy(wl->viewporter); + if (wl->fractional_scale_manager) + wp_fractional_scale_manager_v1_destroy(wl->fractional_scale_manager); if (wl->compositor) wl_compositor_destroy(wl->compositor); if (wl->registry) @@ -578,8 +588,8 @@ static void shm_buffer_paint_checkerboard( static bool wl_draw_splash_screen(gfx_ctx_wayland_data_t *wl) { shm_buffer_t *buffer = create_shm_buffer(wl, - wl->width * wl->buffer_scale, - wl->height * wl->buffer_scale, + wl->buffer_width, + wl->buffer_height, WL_SHM_FORMAT_XRGB8888); if (!buffer) @@ -630,12 +640,15 @@ bool gfx_ctx_wl_init_common( frontend_driver_destroy_signal_handler_state(); - wl->input.dpy = wl_display_connect(NULL); - wl->last_buffer_scale = 1; - wl->buffer_scale = 1; - wl->pending_buffer_scale = 1; - wl->floating_width = SPLASH_WINDOW_WIDTH; - wl->floating_height = SPLASH_WINDOW_HEIGHT; + wl->input.dpy = wl_display_connect(NULL); + wl->last_buffer_scale = 1; + wl->buffer_scale = 1; + wl->pending_buffer_scale = 1; + wl->last_fractional_scale_num = FRACTIONAL_SCALE_V1_DEN; + wl->fractional_scale_num = FRACTIONAL_SCALE_V1_DEN; + wl->pending_fractional_scale_num = FRACTIONAL_SCALE_V1_DEN; + wl->floating_width = SPLASH_WINDOW_WIDTH; + wl->floating_height = SPLASH_WINDOW_HEIGHT; if (!wl->input.dpy) { @@ -683,6 +696,13 @@ bool gfx_ctx_wl_init_common( wl->surface = wl_compositor_create_surface(wl->compositor); if (wl->viewporter) wl->viewport = wp_viewporter_get_viewport(wl->viewporter, wl->surface); + if (wl->fractional_scale_manager) + { + wl->fractional_scale = wp_fractional_scale_manager_v1_get_fractional_scale( + wl->fractional_scale_manager, wl->surface); + wp_fractional_scale_v1_add_listener(wl->fractional_scale, &wp_fractional_scale_v1_listener, wl); + RARCH_LOG("[Wayland]: fractional_scale_v1 enabled\n"); + } wl_surface_add_listener(wl->surface, &wl_surface_listener, wl); @@ -809,9 +829,12 @@ bool gfx_ctx_wl_set_video_mode_common_size(gfx_ctx_wayland_data_t *wl, if (!fullscreen) { - wl->buffer_scale = wl->pending_buffer_scale; - wl->buffer_width *= wl->buffer_scale; - wl->buffer_height *= wl->buffer_scale; + wl->buffer_scale = wl->pending_buffer_scale; + wl->fractional_scale_num = wl->pending_fractional_scale_num; + wl->buffer_width = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(wl->buffer_width, wl->fractional_scale_num) : wl->buffer_width * wl->buffer_scale; + wl->buffer_height = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(wl->buffer_height, wl->fractional_scale_num) : wl->buffer_height * wl->buffer_scale; } if (wl->viewport) /* Update viewport */ wp_viewport_set_destination(wl->viewport, wl->width, wl->height); @@ -944,13 +967,15 @@ void gfx_ctx_wl_check_window_common(gfx_ctx_wayland_data_t *wl, get_video_size(wl, &new_width, &new_height); if ( wl->pending_buffer_scale != wl->buffer_scale + || wl->pending_fractional_scale_num != wl->fractional_scale_num || new_width != *width || new_height != *height) { - wl->buffer_scale = wl->pending_buffer_scale; - *width = new_width; - *height = new_height; - *resize = true; + wl->buffer_scale = wl->pending_buffer_scale; + wl->fractional_scale_num = wl->pending_fractional_scale_num; + *width = new_width; + *height = new_height; + *resize = true; } *quit = (bool)frontend_driver_get_signal_handler_state(); diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 4c883f093f..d1832c2182 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -107,10 +107,11 @@ static void gfx_ctx_wl_check_window(void *data, bool *quit, static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height) { - gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - - wl->last_buffer_scale = wl->buffer_scale; - wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale); + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + wl->last_buffer_scale = wl->buffer_scale; + wl->last_fractional_scale_num = wl->fractional_scale_num; + if (!wl->fractional_scale) + wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale); #ifdef HAVE_EGL wl_egl_window_resize(wl->win, width, height, 0, 0); diff --git a/gfx/drivers_context/wayland_vk_ctx.c b/gfx/drivers_context/wayland_vk_ctx.c index 5161b6ef85..2b726a8fa8 100644 --- a/gfx/drivers_context/wayland_vk_ctx.c +++ b/gfx/drivers_context/wayland_vk_ctx.c @@ -86,7 +86,9 @@ static bool gfx_ctx_wl_set_resize(void *data, unsigned width, unsigned height) gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; wl->last_buffer_scale = wl->buffer_scale; - wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale); + wl->last_fractional_scale_num = wl->fractional_scale_num; + if (!wl->fractional_scale) + wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale); if (vulkan_create_swapchain(&wl->vk, width, height, wl->swap_interval)) { diff --git a/input/common/wayland_common.c b/input/common/wayland_common.c index de428f8c36..8084699bea 100644 --- a/input/common/wayland_common.c +++ b/input/common/wayland_common.c @@ -189,10 +189,12 @@ static void wl_pointer_handle_enter(void *data, gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; wl->input.mouse.surface = surface; - wl->input.mouse.last_x = wl_fixed_to_int( - sx * (wl_fixed_t)wl->buffer_scale); - wl->input.mouse.last_y = wl_fixed_to_int( - sy * (wl_fixed_t)wl->buffer_scale); + wl->input.mouse.last_x = wl->fractional_scale ? + (int) FRACTIONAL_SCALE_MULT(wl_fixed_to_int(sx), wl->fractional_scale_num) : + wl_fixed_to_int(sx * (wl_fixed_t)wl->buffer_scale); + wl->input.mouse.last_y = wl->fractional_scale ? + (int) FRACTIONAL_SCALE_MULT(wl_fixed_to_int(sy), wl->fractional_scale_num) : + wl_fixed_to_int(sy * (wl_fixed_t)wl->buffer_scale); wl->input.mouse.x = wl->input.mouse.last_x; wl->input.mouse.y = wl->input.mouse.last_y; wl->input.mouse.focus = true; @@ -223,10 +225,12 @@ static void wl_pointer_handle_motion(void *data, wl_fixed_t sy) { gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; - wl->input.mouse.x = wl_fixed_to_int( - (wl_fixed_t)wl->buffer_scale * sx); - wl->input.mouse.y = wl_fixed_to_int( - (wl_fixed_t)wl->buffer_scale * sy); + wl->input.mouse.x = wl->fractional_scale ? + (int) FRACTIONAL_SCALE_MULT(wl_fixed_to_int(sx), wl->fractional_scale_num) : + wl_fixed_to_int((wl_fixed_t)wl->buffer_scale * sx); + wl->input.mouse.y = wl->fractional_scale ? + (int) FRACTIONAL_SCALE_MULT(wl_fixed_to_int(sy), wl->fractional_scale_num) : + wl_fixed_to_int((wl_fixed_t)wl->buffer_scale * sy); } static void wl_pointer_handle_button(void *data, @@ -331,10 +335,12 @@ static void wl_touch_handle_down(void *data, { wl->active_touch_positions[wl->num_active_touches].active = true; wl->active_touch_positions[wl->num_active_touches].id = id; - wl->active_touch_positions[wl->num_active_touches].x = (unsigned) - wl_fixed_to_int(x * (wl_fixed_t)wl->buffer_scale); - wl->active_touch_positions[wl->num_active_touches].y = (unsigned) - wl_fixed_to_int(y * (wl_fixed_t)wl->buffer_scale); + wl->active_touch_positions[wl->num_active_touches].x = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(wl_fixed_to_int(x), wl->fractional_scale_num) : + (unsigned) wl_fixed_to_int(x * (wl_fixed_t)wl->buffer_scale); + wl->active_touch_positions[wl->num_active_touches].y = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(wl_fixed_to_int(y), wl->fractional_scale_num) : + (unsigned) wl_fixed_to_int(y * (wl_fixed_t)wl->buffer_scale); wl->num_active_touches++; break; } @@ -415,10 +421,12 @@ static void wl_touch_handle_motion(void *data, if ( wl->active_touch_positions[i].active && wl->active_touch_positions[i].id == id) { - wl->active_touch_positions[i].x = (unsigned) wl_fixed_to_int( - x * (wl_fixed_t)wl->buffer_scale); - wl->active_touch_positions[i].y = (unsigned) wl_fixed_to_int( - y * (wl_fixed_t)wl->buffer_scale); + wl->active_touch_positions[i].x = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(wl_fixed_to_int(x), wl->fractional_scale_num) : + (unsigned) wl_fixed_to_int(x * (wl_fixed_t)wl->buffer_scale); + wl->active_touch_positions[i].y = wl->fractional_scale ? + FRACTIONAL_SCALE_MULT(wl_fixed_to_int(y), wl->fractional_scale_num) : + (unsigned) wl_fixed_to_int(y * (wl_fixed_t)wl->buffer_scale); } } } @@ -592,6 +600,13 @@ static bool wl_current_outputs_remove(gfx_ctx_wayland_data_t *wl, return false; } +static void wp_fractional_scale_v1_preferred_scale(void *data, struct wp_fractional_scale_v1 *fractional_scale, + uint32_t scale) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + wl->pending_fractional_scale_num = scale; +} + static void wl_surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *output) { @@ -697,6 +712,9 @@ static void wl_registry_handle_global(void *data, struct wl_registry *reg, else if (string_is_equal(interface, wp_viewporter_interface.name)) wl->viewporter = (struct wp_viewporter*)wl_registry_bind(reg, id, &wp_viewporter_interface, MIN(version, 1)); + else if (string_is_equal(interface, wp_fractional_scale_manager_v1_interface.name)) + wl->fractional_scale_manager = (struct wp_fractional_scale_manager_v1*) + wl_registry_bind(reg, id, &wp_fractional_scale_manager_v1_interface, MIN(version, 1)); else if (string_is_equal(interface, wl_output_interface.name)) { display_output_t *od = (display_output_t*) @@ -1031,6 +1049,10 @@ const struct xdg_surface_listener xdg_surface_listener = { xdg_surface_handle_configure, }; +const struct wp_fractional_scale_v1_listener wp_fractional_scale_v1_listener = { + wp_fractional_scale_v1_preferred_scale, +}; + const struct wl_surface_listener wl_surface_listener = { wl_surface_enter, wl_surface_leave, diff --git a/input/common/wayland_common.h b/input/common/wayland_common.h index bb597da742..47c4ff8dc7 100644 --- a/input/common/wayland_common.h +++ b/input/common/wayland_common.h @@ -34,6 +34,7 @@ #endif /* Generated from wayland protocol files by generate_wayland_protos.sh */ +#include "../../gfx/common/wayland/fractional-scale-v1.h" #include "../../gfx/common/wayland/viewporter.h" #include "../../gfx/common/wayland/idle-inhibit-unstable-v1.h" #include "../../gfx/common/wayland/xdg-shell.h" @@ -41,7 +42,11 @@ #include "../../gfx/common/wayland/pointer-constraints-unstable-v1.h" #include "../../gfx/common/wayland/relative-pointer-unstable-v1.h" -#define UDEV_KEY_MAX 0x2ff +#define FRACTIONAL_SCALE_V1_DEN 120 +#define FRACTIONAL_SCALE_MULT(v, scale_num) \ + (((v) * (scale_num) + FRACTIONAL_SCALE_V1_DEN / 2) / FRACTIONAL_SCALE_V1_DEN) + +#define UDEV_KEY_MAX 0x2ff #define UDEV_MAX_KEYS (UDEV_KEY_MAX + 7) / 8 #define MAX_TOUCHES 16 @@ -144,9 +149,11 @@ typedef struct gfx_ctx_wayland_data struct wl_registry *registry; struct wl_compositor *compositor; struct wp_viewporter *viewporter; + struct wp_fractional_scale_manager_v1 *fractional_scale_manager; struct wl_surface *surface; struct xdg_surface *xdg_surface; struct wp_viewport *viewport; + struct wp_fractional_scale_v1 *fractional_scale; struct xdg_wm_base *xdg_shell; struct xdg_toplevel *xdg_toplevel; struct wl_keyboard *wl_keyboard; @@ -203,6 +210,9 @@ typedef struct gfx_ctx_wayland_data unsigned last_buffer_scale; unsigned pending_buffer_scale; unsigned buffer_scale; + unsigned last_fractional_scale_num; + unsigned pending_fractional_scale_num; + unsigned fractional_scale_num; bool core_hw_context_enable; bool fullscreen; @@ -239,6 +249,8 @@ extern const struct wl_touch_listener touch_listener; extern const struct wl_seat_listener seat_listener; +extern const struct wp_fractional_scale_v1_listener wp_fractional_scale_v1_listener; + extern const struct wl_surface_listener wl_surface_listener; extern const struct xdg_wm_base_listener xdg_shell_listener;