Skip to content

Commit

Permalink
video: wayland: Display non-native fullscreen aspect ratios centered …
Browse files Browse the repository at this point in the history
…with a black border

Employ subsurfaces and viewports to maintain a proper aspect ratio for fullscreen modes that don't match the display's native aspect ratio, and display the content centered, with a black border.  The mask surface uses a 1x1 SHM buffer, which is scaled to the display output dimensions using a viewport.  The draw surface becomes a subsurface of the parent mask surface and runs in desynced mode.
  • Loading branch information
Kontrabant committed Apr 13, 2022
1 parent c36bd78 commit 10e644e
Show file tree
Hide file tree
Showing 7 changed files with 417 additions and 66 deletions.
16 changes: 16 additions & 0 deletions CMakeLists.txt
Expand Up @@ -905,6 +905,22 @@ if(SDL_LIBC)
check_symbol_exists(getauxval "sys/auxv.h" HAVE_GETAUXVAL)
check_symbol_exists(elf_aux_info "sys/auxv.h" HAVE_ELF_AUX_INFO)
check_symbol_exists(poll "poll.h" HAVE_POLL)
check_symbol_exists(posix_fallocate "fcntl.h" HAVE_POSIX_FALLOCATE)

# memfd_create() and mkostemp() require _GNU_SOURCE to be defined on Linux
if(LINUX)
list(FIND CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE" GNU_SOURCE_DEFINED)
else()
set(GNU_SOURCE_DEFINED 0)
endif()
if(GNU_SOURCE_DEFINED EQUAL -1)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
endif()
check_symbol_exists(memfd_create "sys/mman.h" HAVE_MEMFD_CREATE)
check_symbol_exists(mkostemp "stdlib.h" HAVE_MKOSTEMP)
if(GNU_SOURCE_DEFINED EQUAL -1)
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
endif()

check_library_exists(m pow "" HAVE_LIBM)
if(HAVE_LIBM)
Expand Down
3 changes: 3 additions & 0 deletions include/SDL_config.h.cmake
Expand Up @@ -202,6 +202,9 @@
#cmakedefine HAVE_GETAUXVAL 1
#cmakedefine HAVE_ELF_AUX_INFO 1
#cmakedefine HAVE_POLL 1
#cmakedefine HAVE_POSIX_FALLOCATE 1
#cmakedefine HAVE_MEMFD_CREATE 1
#cmakedefine HAVE_MKOSTEMP 1
#cmakedefine HAVE__EXIT 1

#elif defined(__WIN32__)
Expand Down
33 changes: 20 additions & 13 deletions src/video/wayland/SDL_waylandevents.c
Expand Up @@ -391,8 +391,8 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
if (input->pointer_focus) {
const float sx_f = (float)wl_fixed_to_double(sx_w);
const float sy_f = (float)wl_fixed_to_double(sy_w);
const int sx = (int)SDL_lroundf(sx_f * window->pointer_scale_x);
const int sy = (int)SDL_lroundf(sy_f * window->pointer_scale_y);
const int sx = (int)SDL_lroundf((sx_f - window->pointer_offset_x) * window->pointer_scale_x);
const int sy = (int)SDL_lroundf((sy_f - window->pointer_offset_y) * window->pointer_scale_y);
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
}
}
Expand Down Expand Up @@ -719,10 +719,10 @@ touch_handler_down(void *data, struct wl_touch *touch, unsigned int serial,
int id, wl_fixed_t fx, wl_fixed_t fy)
{
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(surface);
const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
const float x = dblx / window_data->sdlwindow->w;
const float y = dbly / window_data->sdlwindow->h;
const double dblx = (wl_fixed_to_double(fx) - window_data->pointer_offset_x) * window_data->pointer_scale_x;
const double dbly = (wl_fixed_to_double(fy) - window_data->pointer_offset_y) * window_data->pointer_scale_y;
const float x = dblx / (float)window_data->sdlwindow->w;
const float y = dbly / (float)window_data->sdlwindow->h;

touch_add(id, x, y, surface);

Expand Down Expand Up @@ -752,8 +752,8 @@ touch_handler_motion(void *data, struct wl_touch *touch, unsigned int timestamp,
int id, wl_fixed_t fx, wl_fixed_t fy)
{
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(touch_surface(id));
const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
const double dblx = (wl_fixed_to_double(fx) - window_data->pointer_offset_x) * window_data->pointer_scale_x;
const double dbly = (wl_fixed_to_double(fy) - window_data->pointer_offset_y) * window_data->pointer_scale_y;
const float x = dblx / window_data->sdlwindow->w;
const float y = dbly / window_data->sdlwindow->h;

Expand Down Expand Up @@ -1824,8 +1824,8 @@ tablet_tool_handle_motion(void* data, struct zwp_tablet_tool_v2* tool, wl_fixed_
input->sx_w = sx_w;
input->sy_w = sy_w;
if (input->tool_focus) {
const float sx_f = (float)wl_fixed_to_double(sx_w);
const float sy_f = (float)wl_fixed_to_double(sy_w);
const float sx_f = (float)wl_fixed_to_double(sx_w) - window->pointer_offset_x;
const float sy_f = (float)wl_fixed_to_double(sy_w) - window->pointer_offset_y;
const int sx = (int)SDL_lroundf(sx_f * window->pointer_scale_x);
const int sy = (int)SDL_lroundf(sy_f * window->pointer_scale_y);
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
Expand Down Expand Up @@ -2197,6 +2197,13 @@ static const struct zwp_relative_pointer_v1_listener relative_pointer_listener =
relative_pointer_handle_relative_motion,
};

SDL_FORCE_INLINE struct wl_surface *
get_input_lock_surface(SDL_Window *window)
{
SDL_WindowData *data = window->driverdata;
return data->parent_surface ? data->parent_surface : data->surface;
}

static void
locked_pointer_locked(void *data,
struct zwp_locked_pointer_v1 *locked_pointer)
Expand Down Expand Up @@ -2227,7 +2234,7 @@ lock_pointer_to_window(SDL_Window *window,

locked_pointer =
zwp_pointer_constraints_v1_lock_pointer(d->pointer_constraints,
w->surface,
get_input_lock_surface(window),
input->pointer,
NULL,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
Expand Down Expand Up @@ -2371,7 +2378,7 @@ int Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *wi

confined_pointer =
zwp_pointer_constraints_v1_confine_pointer(d->pointer_constraints,
w->surface,
get_input_lock_surface(window),
input->pointer,
confine_rect,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
Expand Down Expand Up @@ -2406,7 +2413,7 @@ int Wayland_input_grab_keyboard(SDL_Window *window, struct SDL_WaylandInput *inp

w->key_inhibitor =
zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(d->key_inhibitor_manager,
w->surface,
get_input_lock_surface(window),
input->seat);

return 0;
Expand Down
6 changes: 6 additions & 0 deletions src/video/wayland/SDL_waylandvideo.c
Expand Up @@ -850,6 +850,8 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
Wayland_init_xdg_output(d);
} else if (SDL_strcmp(interface, "wp_viewporter") == 0) {
d->viewporter = wl_registry_bind(d->registry, id, &wp_viewporter_interface, 1);
} else if (SDL_strcmp(interface, "wl_subcompositor") == 0) {
d->subcompositor = wl_registry_bind(d->registry, id, &wl_subcompositor_interface, 1);

#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (SDL_strcmp(interface, "qt_touch_extension") == 0) {
Expand Down Expand Up @@ -1066,6 +1068,10 @@ Wayland_VideoQuit(_THIS)
wp_viewporter_destroy(data->viewporter);
}

if (data->subcompositor) {
wl_subcompositor_destroy(data->subcompositor);
}

if (data->compositor)
wl_compositor_destroy(data->compositor);

Expand Down
1 change: 1 addition & 0 deletions src/video/wayland/SDL_waylandvideo.h
Expand Up @@ -75,6 +75,7 @@ typedef struct {
struct zwp_text_input_manager_v3 *text_input_manager;
struct zxdg_output_manager_v1 *xdg_output_manager;
struct wp_viewporter *viewporter;
struct wl_subcompositor *subcompositor;

EGLDisplay edpy;
EGLContext context;
Expand Down

0 comments on commit 10e644e

Please sign in to comment.