Skip to content

Commit

Permalink
video: wayland: Use wp-viewporter for fullscreen with non-native reso…
Browse files Browse the repository at this point in the history
…lutions

Wayland doesn't support mode switching, however Wayland compositors can support the wp_viewporter protocol, which allows for the mapping of arbitrarily sized buffer regions to output surfaces.  Use this functionality, when available, for fullscreen output when using non-native display modes and/or when dealing with scaled desktops, which can incur significant overdraw without this extension.

This also allows for the exposure of arbitrarily sized, emulated display modes, which can be useful for legacy compatability.
  • Loading branch information
Kontrabant authored and flibitijibibo committed Mar 28, 2022
1 parent aec86ba commit 4d76c9c
Show file tree
Hide file tree
Showing 10 changed files with 642 additions and 88 deletions.
1 change: 1 addition & 0 deletions src/video/SDL_sysvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ struct SDL_VideoDevice
Uint32 next_object_id;
char *clipboard_text;
SDL_bool setting_display_mode;
SDL_bool disable_display_mode_switching;

/* * * */
/* Data used by the GL drivers */
Expand Down
19 changes: 11 additions & 8 deletions src/video/SDL_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -1339,14 +1339,17 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
resized = SDL_FALSE;
}

/* only do the mode change if we want exclusive fullscreen */
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
return -1;
}
} else {
if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
return -1;
/* Don't try to change the display mode if the driver doesn't want it. */
if (_this->disable_display_mode_switching == SDL_FALSE) {
/* only do the mode change if we want exclusive fullscreen */
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
return -1;
}
} else {
if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
return -1;
}
}
}

Expand Down
35 changes: 23 additions & 12 deletions src/video/wayland/SDL_waylandevents.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,10 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
input->sx_w = sx_w;
input->sy_w = sy_w;
if (input->pointer_focus) {
const int sx = wl_fixed_to_int(sx_w);
const int sy = wl_fixed_to_int(sy_w);
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);
const int sy = (int)SDL_lroundf(sy_f * window->pointer_scale);
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
}
}
Expand Down Expand Up @@ -717,8 +719,8 @@ 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);
const double dbly = wl_fixed_to_double(fy);
const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale;
const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale;
const float x = dblx / window_data->sdlwindow->w;
const float y = dbly / window_data->sdlwindow->h;

Expand Down Expand Up @@ -750,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);
const double dbly = wl_fixed_to_double(fy);
const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale;
const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale;
const float x = dblx / window_data->sdlwindow->w;
const float y = dbly / window_data->sdlwindow->h;

Expand Down Expand Up @@ -1817,8 +1819,10 @@ 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 int sx = wl_fixed_to_int(sx_w);
const int sy = wl_fixed_to_int(sy_w);
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);
const int sy = (int)SDL_lroundf(sy_f * window->pointer_scale);
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
}
}
Expand Down Expand Up @@ -2345,12 +2349,19 @@ int Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *wi
if (SDL_RectEmpty(&window->mouse_rect)) {
confine_rect = NULL;
} else {
SDL_Rect scaled_mouse_rect;

scaled_mouse_rect.x = (int)SDL_floorf((float)window->mouse_rect.x / w->pointer_scale);
scaled_mouse_rect.y = (int)SDL_floorf((float)window->mouse_rect.y / w->pointer_scale);
scaled_mouse_rect.w = (int)SDL_ceilf((float)window->mouse_rect.w / w->pointer_scale);
scaled_mouse_rect.h = (int)SDL_ceilf((float)window->mouse_rect.h / w->pointer_scale);

confine_rect = wl_compositor_create_region(d->compositor);
wl_region_add(confine_rect,
window->mouse_rect.x,
window->mouse_rect.y,
window->mouse_rect.w,
window->mouse_rect.h);
scaled_mouse_rect.x,
scaled_mouse_rect.y,
scaled_mouse_rect.w,
scaled_mouse_rect.h);
}

confined_pointer =
Expand Down
4 changes: 2 additions & 2 deletions src/video/wayland/SDL_waylandopengles.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,11 @@ Wayland_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
data = (SDL_WindowData *) window->driverdata;

if (w) {
*w = window->w * data->scale_factor;
*w = data->drawable_width;
}

if (h) {
*h = window->h * data->scale_factor;
*h = data->drawable_height;
}
}
}
Expand Down
Loading

0 comments on commit 4d76c9c

Please sign in to comment.