Skip to content

Commit c1adfb4

Browse files
committed
wayland: Always create a viewport for the window if available
Viewports decouple the buffer from the window size and avoids the window geometry hacks used to prevent problems if a buffer with an old size in the pipeline ends up being committed. Fixes an invalid geometry warning and incorrect overview size for fullscreen windows on GNOME, and avoids flicker when entering/exiting fullscreen or moving the window between scaled and non-scaled displays. (cherry picked from commit 849c905)
1 parent 217bc17 commit c1adfb4

File tree

1 file changed

+18
-77
lines changed

1 file changed

+18
-77
lines changed

src/video/wayland/SDL_waylandwindow.c

Lines changed: 18 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -118,47 +118,12 @@ static void GetFullScreenDimensions(SDL_Window *window, int *width, int *height,
118118
}
119119
}
120120

121-
SDL_FORCE_INLINE SDL_bool SurfaceScaleIsFractional(SDL_Window *window)
122-
{
123-
SDL_WindowData *data = window->driverdata;
124-
return !FloatEqual(SDL_roundf(data->scale_factor), data->scale_factor);
125-
}
126-
127121
SDL_FORCE_INLINE SDL_bool FullscreenModeEmulation(SDL_Window *window)
128122
{
129123
return (window->flags & SDL_WINDOW_FULLSCREEN) &&
130124
((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP);
131125
}
132126

133-
static SDL_bool NeedViewport(SDL_Window *window)
134-
{
135-
SDL_WindowData *wind = window->driverdata;
136-
SDL_VideoData *video = wind->waylandData;
137-
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
138-
SDL_WaylandOutputData *output = display ? ((SDL_WaylandOutputData *)display->driverdata) : NULL;
139-
const int output_width = wind->fs_output_width ? wind->fs_output_width : (output ? output->width : wind->window_width);
140-
const int output_height = wind->fs_output_height ? wind->fs_output_height : (output ? output->height : wind->window_height);
141-
int fs_width, fs_height;
142-
143-
/*
144-
* A viewport is only required when scaling is enabled and:
145-
* - A fullscreen mode is being emulated and the mode does not match the logical desktop dimensions.
146-
* - The desktop uses fractional scaling and the high-DPI flag is set.
147-
*/
148-
if (video->viewporter) {
149-
if (FullscreenModeEmulation(window)) {
150-
GetFullScreenDimensions(window, &fs_width, &fs_height, NULL, NULL);
151-
if (fs_width != output_width || fs_height != output_height) {
152-
return SDL_TRUE;
153-
}
154-
} else if (SurfaceScaleIsFractional(window) && (window->flags & SDL_WINDOW_ALLOW_HIGHDPI)) {
155-
return SDL_TRUE;
156-
}
157-
}
158-
159-
return SDL_FALSE;
160-
}
161-
162127
static void GetBufferSize(SDL_Window *window, int *width, int *height)
163128
{
164129
SDL_WindowData *data = window->driverdata;
@@ -167,15 +132,12 @@ static void GetBufferSize(SDL_Window *window, int *width, int *height)
167132

168133
if (FullscreenModeEmulation(window)) {
169134
GetFullScreenDimensions(window, NULL, NULL, &buf_width, &buf_height);
170-
} else if (NeedViewport(window)) {
135+
} else if (data->draw_viewport) {
171136
/* Round fractional backbuffer sizes halfway away from zero. */
172137
buf_width = (int)SDL_lroundf(window->w * data->scale_factor);
173138
buf_height = (int)SDL_lroundf(window->h * data->scale_factor);
174139
} else {
175-
/*
176-
* Integer scaled windowed or fullscreen with no viewport
177-
*
178-
* Round the scale factor up in the unlikely scenario of a compositor
140+
/* Round the scale factor up in the unlikely scenario of a compositor
179141
* that supports fractional scaling, but not viewports.
180142
*/
181143
int scale_factor = (int)SDL_ceilf(data->scale_factor);
@@ -192,31 +154,6 @@ static void GetBufferSize(SDL_Window *window, int *width, int *height)
192154
}
193155
}
194156

195-
static void SetDrawSurfaceViewport(SDL_Window *window, int src_width, int src_height, int dst_width, int dst_height)
196-
{
197-
SDL_WindowData *wind = window->driverdata;
198-
SDL_VideoData *video = wind->waylandData;
199-
200-
if (video->viewporter) {
201-
if (!wind->draw_viewport) {
202-
wind->draw_viewport = wp_viewporter_get_viewport(video->viewporter, wind->surface);
203-
}
204-
205-
wp_viewport_set_source(wind->draw_viewport, wl_fixed_from_int(-1), wl_fixed_from_int(-1), wl_fixed_from_int(-1), wl_fixed_from_int(-1));
206-
wp_viewport_set_destination(wind->draw_viewport, dst_width, dst_height);
207-
}
208-
}
209-
210-
static void UnsetDrawSurfaceViewport(SDL_Window *window)
211-
{
212-
SDL_WindowData *wind = window->driverdata;
213-
214-
if (wind->draw_viewport) {
215-
wp_viewport_destroy(wind->draw_viewport);
216-
wind->draw_viewport = NULL;
217-
}
218-
}
219-
220157
static void ConfigureWindowGeometry(SDL_Window *window)
221158
{
222159
SDL_WindowData *data = window->driverdata;
@@ -240,7 +177,7 @@ static void ConfigureWindowGeometry(SDL_Window *window)
240177
0, 0);
241178
}
242179

243-
if (FullscreenModeEmulation(window) && NeedViewport(window)) {
180+
if (FullscreenModeEmulation(window) && data->draw_viewport) {
244181
int fs_width, fs_height;
245182
const int output_width = data->fs_output_width ? data->fs_output_width : (output ? output->width : data->window_width);
246183
const int output_height = data->fs_output_height ? data->fs_output_height : (output ? output->height : data->window_height);
@@ -252,8 +189,7 @@ static void ConfigureWindowGeometry(SDL_Window *window)
252189

253190
/* Set the buffer scale to 1 since a viewport will be used. */
254191
wl_surface_set_buffer_scale(data->surface, 1);
255-
SetDrawSurfaceViewport(window, data->drawable_width, data->drawable_height,
256-
output_width, output_height);
192+
wp_viewport_set_destination(data->draw_viewport, output_width, output_height);
257193

258194
data->window_width = output_width;
259195
data->window_height = output_height;
@@ -265,12 +201,10 @@ static void ConfigureWindowGeometry(SDL_Window *window)
265201
window_size_changed = data->window_width != window->w || data->window_height != window->h;
266202

267203
if (window_size_changed || drawable_size_changed) {
268-
if (NeedViewport(window)) {
204+
if (data->draw_viewport) {
269205
wl_surface_set_buffer_scale(data->surface, 1);
270-
SetDrawSurfaceViewport(window, data->drawable_width, data->drawable_height, window->w, window->h);
206+
wp_viewport_set_destination(data->draw_viewport, window->w, window->h);
271207
} else {
272-
UnsetDrawSurfaceViewport(window);
273-
274208
if (!FullscreenModeEmulation(window)) {
275209
/* Round to the next integer in case of a fractional value. */
276210
wl_surface_set_buffer_scale(data->surface, (int32_t)SDL_ceilf(data->scale_factor));
@@ -293,8 +227,11 @@ static void ConfigureWindowGeometry(SDL_Window *window)
293227
* need to be recalculated if the output size has changed.
294228
*/
295229
if (window_size_changed) {
296-
/* libdecor does this internally on frame commits, so it's only needed for xdg surfaces. */
297-
if (data->shell_surface_type != WAYLAND_SURFACE_LIBDECOR &&
230+
/* XXX: This is a hack and only set on the xdg-toplevel path when viewports
231+
* aren't supported to avoid a potential protocol violation if a buffer
232+
* with an old size is committed.
233+
*/
234+
if (!data->draw_viewport && data->shell_surface_type == WAYLAND_SURFACE_XDG_TOPLEVEL &&
298235
viddata->shell.xdg && data->shell_surface.xdg.surface) {
299236
xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->window_width, data->window_height);
300237
}
@@ -1420,9 +1357,6 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
14201357
&decoration_listener,
14211358
window);
14221359
}
1423-
1424-
/* Set the geometry */
1425-
xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, data->window_width, data->window_height);
14261360
} else {
14271361
/* Nothing to see here, just commit. */
14281362
wl_surface_commit(data->surface);
@@ -2036,6 +1970,13 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
20361970

20371971
SDL_WAYLAND_register_surface(data->surface);
20381972

1973+
if (c->viewporter) {
1974+
data->draw_viewport = wp_viewporter_get_viewport(c->viewporter, data->surface);
1975+
wp_viewport_set_source(data->draw_viewport,
1976+
wl_fixed_from_int(-1), wl_fixed_from_int(-1),
1977+
wl_fixed_from_int(-1), wl_fixed_from_int(-1));
1978+
}
1979+
20391980
/* Must be called before EGL configuration to set the drawable backbuffer size. */
20401981
ConfigureWindowGeometry(window);
20411982

0 commit comments

Comments
 (0)