clients/simple-egl: Implement fractional-scale protocol support

Fractional scale is increasingly common in the Wayland ecosystem. Thus,
given simple-egl's role as egl example client, implement support for
the new protocol - even though Weston itself does not support it yet.

Together with buffer_scale and buffer_transform this ensures
simple-egl provides optimally sized and oriented buffers.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
This commit is contained in:
Robert Mader 2023-02-25 19:37:41 +01:00 committed by Robert Mader
parent 1d2feda5aa
commit 9337d42741
3 changed files with 100 additions and 15 deletions

View File

@ -128,8 +128,12 @@ simple_clients = [
'name': 'egl',
'sources': [
'simple-egl.c',
fractional_scale_v1_client_protocol_h,
fractional_scale_v1_protocol_c,
tearing_control_v1_client_protocol_h,
tearing_control_v1_protocol_c,
viewporter_client_protocol_h,
viewporter_protocol_c,
xdg_shell_client_protocol_h,
xdg_shell_protocol_c,
ivi_application_client_protocol_h,

View File

@ -42,6 +42,8 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "fractional-scale-v1-client-protocol.h"
#include "viewporter-client-protocol.h"
#include "xdg-shell-client-protocol.h"
#include "tearing-control-v1-client-protocol.h"
@ -71,6 +73,8 @@ struct display {
struct wl_cursor *default_cursor;
struct wl_surface *cursor_surface;
struct wp_tearing_control_manager_v1 *tearing_manager;
struct wp_viewporter *viewporter;
struct wp_fractional_scale_manager_v1 *fractional_scale_manager;
struct {
EGLDisplay dpy;
EGLContext ctx;
@ -93,6 +97,7 @@ struct window {
struct geometry logical_size;
struct geometry buffer_size;
int32_t buffer_scale;
double fractional_buffer_scale;
enum wl_output_transform buffer_transform;
bool needs_buffer_geometry_update;
@ -112,6 +117,8 @@ struct window {
EGLSurface egl_surface;
int fullscreen, maximized, opaque, buffer_bpp, frame_sync, delay;
struct wp_tearing_control_v1 *tear_control;
struct wp_viewport *viewport;
struct wp_fractional_scale_v1 *fractional_scale_obj;
bool tearing, toggled_tearing, tear_enabled;
bool vertical_bar;
bool fullscreen_ratio;
@ -326,8 +333,8 @@ static void
update_buffer_geometry(struct window *window)
{
enum wl_output_transform new_buffer_transform;
int32_t new_buffer_scale;
struct geometry new_buffer_size;
struct geometry new_viewport_dest_size;
new_buffer_transform = compute_buffer_transform(window);
if (window->buffer_transform != new_buffer_transform) {
@ -336,13 +343,6 @@ update_buffer_geometry(struct window *window)
window->buffer_transform);
}
new_buffer_scale = compute_buffer_scale(window);
if (window->buffer_scale != new_buffer_scale) {
window->buffer_scale = new_buffer_scale;
wl_surface_set_buffer_scale(window->surface,
window->buffer_scale);
}
switch (window->buffer_transform) {
case WL_OUTPUT_TRANSFORM_NORMAL:
case WL_OUTPUT_TRANSFORM_180:
@ -360,14 +360,47 @@ update_buffer_geometry(struct window *window)
break;
}
new_buffer_size.width *= window->buffer_scale;
new_buffer_size.height *= window->buffer_scale;
if (window->fractional_buffer_scale > 0.0) {
if (window->buffer_scale > 1) {
window->buffer_scale = 1;
wl_surface_set_buffer_scale(window->surface,
window->buffer_scale);
}
new_buffer_size.width = ceil(new_buffer_size.width *
window->fractional_buffer_scale);
new_buffer_size.height = ceil(new_buffer_size.height *
window->fractional_buffer_scale);
} else {
int32_t new_buffer_scale;
new_buffer_scale = compute_buffer_scale(window);
if (window->buffer_scale != new_buffer_scale) {
window->buffer_scale = new_buffer_scale;
wl_surface_set_buffer_scale(window->surface,
window->buffer_scale);
}
new_buffer_size.width *= window->buffer_scale;
new_buffer_size.height *= window->buffer_scale;
}
if (window->fullscreen && window->fullscreen_ratio) {
int new_buffer_size_min = MIN(new_buffer_size.width,
new_buffer_size.height);
int new_buffer_size_min;
int new_viewport_dest_size_min;
new_buffer_size_min = MIN(new_buffer_size.width,
new_buffer_size.height);
new_buffer_size.width = new_buffer_size_min;
new_buffer_size.height = new_buffer_size_min;
new_viewport_dest_size_min = MIN(window->logical_size.width,
window->logical_size.height);
new_viewport_dest_size.width = new_viewport_dest_size_min;
new_viewport_dest_size.height = new_viewport_dest_size_min;
} else {
new_viewport_dest_size.width = window->logical_size.width;
new_viewport_dest_size.height = window->logical_size.height;
}
if (window->buffer_size.width != new_buffer_size.width ||
@ -379,10 +412,14 @@ update_buffer_geometry(struct window *window)
window->buffer_size.height, 0, 0);
}
if (window->fractional_buffer_scale > 0.0)
wp_viewport_set_destination(window->viewport,
new_viewport_dest_size.width,
new_viewport_dest_size.height);
window->needs_buffer_geometry_update = false;
}
static void
init_gl(struct window *window)
{
@ -686,6 +723,19 @@ static const struct wl_surface_listener surface_listener = {
surface_leave
};
static void fractional_scale_handle_preferred_scale(void *data,
struct wp_fractional_scale_v1 *info,
uint32_t wire_scale) {
struct window *window = data;
window->fractional_buffer_scale = wire_scale / 120.0;
window->needs_buffer_geometry_update = true;
}
static const struct wp_fractional_scale_v1_listener fractional_scale_listener = {
.preferred_scale = fractional_scale_handle_preferred_scale,
};
static void
create_surface(struct window *window)
{
@ -720,6 +770,17 @@ create_surface(struct window *window)
else if (window->maximized)
xdg_toplevel_set_maximized(window->xdg_toplevel);
if (display->viewporter && display->fractional_scale_manager) {
window->viewport = wp_viewporter_get_viewport(display->viewporter,
window->surface);
window->fractional_scale_obj =
wp_fractional_scale_manager_v1_get_fractional_scale(display->fractional_scale_manager,
window->surface);
wp_fractional_scale_v1_add_listener(window->fractional_scale_obj,
&fractional_scale_listener,
window);
}
window->wait_for_configure = true;
wl_surface_commit(window->surface);
}
@ -740,6 +801,10 @@ destroy_surface(struct window *window)
xdg_toplevel_destroy(window->xdg_toplevel);
if (window->xdg_surface)
xdg_surface_destroy(window->xdg_surface);
if (window->viewport)
wp_viewport_destroy(window->viewport);
if (window->fractional_scale_obj)
wp_fractional_scale_v1_destroy(window->fractional_scale_obj);
wl_surface_destroy(window->surface);
}
@ -1178,6 +1243,15 @@ registry_handle_global(void *data, struct wl_registry *registry,
d->tearing_manager = wl_registry_bind(registry, name,
&wp_tearing_control_manager_v1_interface,
1);
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
d->viewporter = wl_registry_bind(registry, name,
&wp_viewporter_interface,
1);
} else if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0) {
d->fractional_scale_manager =
wl_registry_bind(registry, name,
&wp_fractional_scale_manager_v1_interface,
1);
}
}
@ -1352,6 +1426,12 @@ out_no_xdg_shell:
if (display.compositor)
wl_compositor_destroy(display.compositor);
if (display.viewporter)
wp_viewporter_destroy(display.viewporter);
if (display.fractional_scale_manager)
wp_fractional_scale_manager_v1_destroy(display.fractional_scale_manager);
wl_registry_destroy(display.registry);
wl_display_flush(display.display);
wl_display_disconnect(display.display);

View File

@ -1,7 +1,7 @@
dep_scanner = dependency('wayland-scanner', native: true)
prog_scanner = find_program(dep_scanner.get_variable(pkgconfig: 'wayland_scanner'))
dep_wp = dependency('wayland-protocols', version: '>= 1.30',
dep_wp = dependency('wayland-protocols', version: '>= 1.31',
fallback: ['wayland-protocols', 'wayland_protocols'])
dir_wp_base = dep_wp.get_variable(pkgconfig: 'pkgdatadir', internal: 'pkgdatadir')
@ -16,11 +16,12 @@ install_data(
)
generated_protocols = [
[ 'fullscreen-shell', 'unstable', 'v1' ],
[ 'fractional-scale', 'staging', 'v1' ],
[ 'input-method', 'unstable', 'v1' ],
[ 'input-timestamps', 'unstable', 'v1' ],
[ 'ivi-application', 'internal' ],
[ 'ivi-hmi-controller', 'internal' ],
[ 'fullscreen-shell', 'unstable', 'v1' ],
[ 'linux-dmabuf', 'unstable', 'v1' ],
[ 'linux-explicit-synchronization', 'unstable', 'v1' ],
[ 'presentation-time', 'stable' ],