diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 4ab593966..c2db92e5b 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -298,7 +298,7 @@ static void xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xd { SDL_WaylandOutputData *driverdata = data; - if (driverdata->width != 0 && driverdata->height != 0) { + if (driverdata->screen_width != 0 && driverdata->screen_height != 0) { /* FIXME: GNOME has a bug where the logical size does not account for * scale, resulting in bogus viewport sizes. * @@ -307,7 +307,7 @@ static void xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xd * detected otherwise), then override if necessary. * -flibit */ - const float scale = (float)driverdata->width / (float)width; + const float scale = (float)driverdata->screen_width / (float)width; if ((scale == 1.0f) && (driverdata->scale_factor != 1.0f)) { SDL_LogWarn( SDL_LOG_CATEGORY_VIDEO, @@ -316,8 +316,8 @@ static void xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xd } } - driverdata->width = width; - driverdata->height = height; + driverdata->screen_width = width; + driverdata->screen_height = height; driverdata->has_logical_size = SDL_TRUE; } @@ -414,12 +414,15 @@ static void AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90) int i; SDL_DisplayMode mode; - const int native_width = dpy->display_modes->w; - const int native_height = dpy->display_modes->h; + const int native_width = dpy->display_modes->pixel_w; + const int native_height = dpy->display_modes->pixel_h; for (i = 0; i < SDL_arraysize(mode_list); ++i) { - mode = *dpy->display_modes; + SDL_zero(mode); + mode.format = dpy->display_modes->format; mode.display_scale = 1.0f; + mode.refresh_rate = dpy->display_modes->refresh_rate; + mode.driverdata = dpy->display_modes->driverdata; if (rot_90) { mode.pixel_w = mode_list[i].h; @@ -521,16 +524,16 @@ static void display_handle_mode(void *data, SDL_WaylandOutputData *driverdata = data; if (flags & WL_OUTPUT_MODE_CURRENT) { - driverdata->native_width = width; - driverdata->native_height = height; + driverdata->pixel_width = width; + driverdata->pixel_height = height; /* * Don't rotate this yet, wl-output coordinates are transformed in * handle_done and xdg-output coordinates are pre-transformed. */ if (!driverdata->has_logical_size) { - driverdata->width = width; - driverdata->height = height; + driverdata->screen_width = width; + driverdata->screen_height = height; } driverdata->refresh = refresh; @@ -565,11 +568,11 @@ static void display_handle_done(void *data, native_mode.format = SDL_PIXELFORMAT_RGB888; if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) { - native_mode.pixel_w = driverdata->native_height; - native_mode.pixel_h = driverdata->native_width; + native_mode.pixel_w = driverdata->pixel_height; + native_mode.pixel_h = driverdata->pixel_width; } else { - native_mode.pixel_w = driverdata->native_width; - native_mode.pixel_h = driverdata->native_height; + native_mode.pixel_w = driverdata->pixel_width; + native_mode.pixel_h = driverdata->pixel_height; } native_mode.display_scale = 1.0f; native_mode.refresh_rate = ((100 * driverdata->refresh) / 1000) / 100.0f; /* mHz to Hz */ @@ -581,20 +584,20 @@ static void display_handle_done(void *data, if (driverdata->has_logical_size) { /* If xdg-output is present, calculate the true scale of the desktop */ if (video->viewporter) { - driverdata->scale_factor = (float)native_mode.w / (float)driverdata->width; + driverdata->scale_factor = (float)native_mode.pixel_w / (float)driverdata->screen_width; } } else { /* Scale the desktop coordinates, if xdg-output isn't present */ - driverdata->width /= driverdata->scale_factor; - driverdata->height /= driverdata->scale_factor; + driverdata->screen_width /= driverdata->scale_factor; + driverdata->screen_height /= driverdata->scale_factor; } /* xdg-output dimensions are already transformed, so no need to rotate. */ if (driverdata->has_logical_size || !(driverdata->transform & WL_OUTPUT_TRANSFORM_90)) { - desktop_mode.pixel_w = driverdata->width; - desktop_mode.pixel_h = driverdata->height; + desktop_mode.pixel_w = driverdata->pixel_width; + desktop_mode.pixel_h = driverdata->pixel_height; } else { - desktop_mode.pixel_w = driverdata->height; - desktop_mode.pixel_h = driverdata->width; + desktop_mode.pixel_w = driverdata->pixel_height; + desktop_mode.pixel_h = driverdata->pixel_width; } desktop_mode.display_scale = driverdata->scale_factor; desktop_mode.refresh_rate = ((100 * driverdata->refresh) / 1000) / 100.0f; /* mHz to Hz */ @@ -617,10 +620,15 @@ static void display_handle_done(void *data, if (video->viewporter != NULL) { SDL_AddDisplayMode(dpy, &native_mode); } else { - /* ...if not, expose the integer scale desktop modes down to 1.0. */ + /* ...if not, expose some smaller, integer scaled resolutions. */ int i; - for (i = (int)driverdata->scale_factor - 1; i > 0; --i) { + const int base_pixel_w = desktop_mode.pixel_w / (int)desktop_mode.display_scale; + const int base_pixel_h = desktop_mode.pixel_h / (int)desktop_mode.display_scale; + for (i = 1; i < (int)desktop_mode.display_scale; ++i) { + desktop_mode.pixel_w = base_pixel_w * i; + desktop_mode.pixel_h = base_pixel_h * i; desktop_mode.display_scale = (float)i; + SDL_AddDisplayMode(dpy, &desktop_mode); } } @@ -629,23 +637,23 @@ static void display_handle_done(void *data, /* Add emulated modes if wp_viewporter is supported and mode emulation is enabled. */ if (video->viewporter && mode_emulation_enabled) { const SDL_bool rot_90 = ((driverdata->transform & WL_OUTPUT_TRANSFORM_90) != 0) || - (driverdata->width < driverdata->height); + (driverdata->screen_width < driverdata->screen_height); AddEmulatedModes(dpy, rot_90); } /* Calculate the display DPI */ if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) { - driverdata->hdpi = driverdata->physical_height ? (((float)driverdata->height) * 25.4f / driverdata->physical_height) : 0.0f; - driverdata->vdpi = driverdata->physical_width ? (((float)driverdata->width) * 25.4f / driverdata->physical_width) : 0.0f; - driverdata->ddpi = SDL_ComputeDiagonalDPI(driverdata->height, - driverdata->width, + driverdata->hdpi = driverdata->physical_height ? (((float)driverdata->pixel_height) * 25.4f / driverdata->physical_height) : 0.0f; + driverdata->vdpi = driverdata->physical_width ? (((float)driverdata->pixel_width) * 25.4f / driverdata->physical_width) : 0.0f; + driverdata->ddpi = SDL_ComputeDiagonalDPI(driverdata->pixel_height, + driverdata->pixel_width, ((float)driverdata->physical_height) / 25.4f, ((float)driverdata->physical_width) / 25.4f); } else { - driverdata->hdpi = driverdata->physical_width ? (((float)driverdata->width) * 25.4f / driverdata->physical_width) : 0.0f; - driverdata->vdpi = driverdata->physical_height ? (((float)driverdata->height) * 25.4f / driverdata->physical_height) : 0.0f; - driverdata->ddpi = SDL_ComputeDiagonalDPI(driverdata->width, - driverdata->height, + driverdata->hdpi = driverdata->physical_width ? (((float)driverdata->pixel_width) * 25.4f / driverdata->physical_width) : 0.0f; + driverdata->vdpi = driverdata->physical_height ? (((float)driverdata->pixel_height) * 25.4f / driverdata->physical_height) : 0.0f; + driverdata->ddpi = SDL_ComputeDiagonalDPI(driverdata->pixel_width, + driverdata->pixel_height, ((float)driverdata->physical_width) / 25.4f, ((float)driverdata->physical_height) / 25.4f); } diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h index 0054490b3..62f1f6a1f 100644 --- a/src/video/wayland/SDL_waylandvideo.h +++ b/src/video/wayland/SDL_waylandvideo.h @@ -109,8 +109,8 @@ struct SDL_WaylandOutputData struct zxdg_output_v1 *xdg_output; uint32_t registry_id; float scale_factor; - int native_width, native_height; - int x, y, width, height, refresh, transform; + int pixel_width, pixel_height; + int x, y, screen_width, screen_height, refresh, transform; SDL_DisplayOrientation orientation; int physical_width, physical_height; float ddpi, hdpi, vdpi; diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index b9afc46dd..78fe3829f 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -62,8 +62,8 @@ static void GetFullScreenDimensions(SDL_Window *window, int *width, int *height, int fs_width, fs_height; int buf_width, buf_height; - const int output_width = wind->fs_output_width ? wind->fs_output_width : output->width; - const int output_height = wind->fs_output_height ? wind->fs_output_height : output->height; + const int output_width = wind->fs_output_width ? wind->fs_output_width : output->screen_width; + const int output_height = wind->fs_output_height ? wind->fs_output_height : output->screen_height; /* * Fullscreen desktop mandates a desktop sized window, so that's what applications will get. @@ -76,24 +76,24 @@ static void GetFullScreenDimensions(SDL_Window *window, int *width, int *height, /* If the application is DPI aware, we can expose the true backbuffer size */ if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) { - buf_width = output->native_width; - buf_height = output->native_height; + buf_width = output->pixel_width; + buf_height = output->pixel_height; } else { buf_width = fs_width; buf_height = fs_height; } } else { /* If a mode was set, use it, otherwise use the native resolution. */ - if (window->fullscreen_mode.w != 0 && window->fullscreen_mode.h != 0) { - fs_width = window->fullscreen_mode.w; - fs_height = window->fullscreen_mode.h; - buf_width = (int)SDL_lroundf((float)fs_width * window->fullscreen_mode.display_scale); - buf_height = (int)SDL_lroundf((float)fs_height * window->fullscreen_mode.display_scale); + if (window->fullscreen_mode.pixel_w != 0 && window->fullscreen_mode.pixel_h != 0) { + fs_width = window->fullscreen_mode.screen_w; + fs_height = window->fullscreen_mode.screen_h; + buf_width = window->fullscreen_mode.pixel_w; + buf_height = window->fullscreen_mode.pixel_h; } else { - fs_width = disp->display_modes[0].w; - fs_height = disp->display_modes[0].h; - buf_width = (int)SDL_lroundf((float)fs_width * disp->display_modes[0].display_scale); - buf_height = (int)SDL_lroundf((float)fs_width * disp->display_modes[0].display_scale); + fs_width = disp->display_modes[0].screen_w; + fs_height = disp->display_modes[0].screen_h; + buf_width = disp->display_modes[0].pixel_w; + buf_height = disp->display_modes[0].pixel_h; } } @@ -129,21 +129,23 @@ static SDL_bool WindowNeedsViewport(SDL_Window *window) SDL_WindowData *wind = window->driverdata; SDL_VideoData *video = wind->waylandData; SDL_WaylandOutputData *output = ((SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata); + const int output_width = wind->fs_output_width ? wind->fs_output_width : output->screen_width; + const int output_height = wind->fs_output_height ? wind->fs_output_height : output->screen_height; int fs_width, fs_height; /* * A viewport is only required when scaling is enabled and: + * - The surface scale is fractional. * - A fullscreen mode is being emulated and the mode does not match the logical desktop dimensions. - * - The desktop uses fractional scaling and the high-DPI flag is set. */ if (video->viewporter != NULL) { - if (FullscreenModeEmulation(window)) { + if (SurfaceScaleIsFractional(window)) { + return SDL_TRUE; + } else if (FullscreenModeEmulation(window)) { GetFullScreenDimensions(window, &fs_width, &fs_height, NULL, NULL); - if (fs_width != output->width || fs_height != output->height) { + if (fs_width != output_width || fs_height != output_height) { return SDL_TRUE; } - } else if (SurfaceScaleIsFractional(window) && (window->flags & SDL_WINDOW_ALLOW_HIGHDPI)) { - return SDL_TRUE; } } @@ -225,8 +227,8 @@ static void ConfigureWindowGeometry(SDL_Window *window) if (FullscreenModeEmulation(window)) { int fs_width, fs_height; - const int output_width = data->fs_output_width ? data->fs_output_width : output->width; - const int output_height = data->fs_output_height ? data->fs_output_height : output->height; + const int output_width = data->fs_output_width ? data->fs_output_width : output->screen_width; + const int output_height = data->fs_output_height ? data->fs_output_height : output->screen_height; window_size_changed = data->window_width != output_width || data->window_height != output_height; @@ -238,14 +240,21 @@ static void ConfigureWindowGeometry(SDL_Window *window) wl_surface_set_buffer_scale(data->surface, 1); SetDrawSurfaceViewport(window, data->drawable_width, data->drawable_height, output_width, output_height); + + data->window_width = output_width; + data->window_height = output_height; + + data->pointer_scale_x = (float)fs_width / (float)output_width; + data->pointer_scale_y = (float)fs_height / (float)output_height; } else { wl_surface_set_buffer_scale(data->surface, (int32_t)window->fullscreen_mode.display_scale); - } - data->window_width = output_width; - data->window_height = output_height; - data->pointer_scale_x = (float)fs_width / (float)output_width; - data->pointer_scale_y = (float)fs_height / (float)output_height; + data->window_width = fs_width; + data->window_height = fs_height; + + data->pointer_scale_x = 1.0f; + data->pointer_scale_y = 1.0f; + } } } else { window_size_changed = data->window_width != window->w || data->window_height != window->h; @@ -444,13 +453,13 @@ static void UpdateWindowFullscreen(SDL_Window *window, SDL_bool fullscreen) * otherwise, fall back to SDL_WINDOW_FULLSCREEN_DESKTOP. */ if (!wind->fullscreen_flags) { - if (window->fullscreen_mode.w && window->fullscreen_mode.h) { + if (window->fullscreen_mode.pixel_w && window->fullscreen_mode.pixel_h) { wind->fullscreen_flags = SDL_WINDOW_FULLSCREEN; } else { wind->fullscreen_flags = SDL_WINDOW_FULLSCREEN_DESKTOP; } } else if (wind->fullscreen_flags != SDL_WINDOW_FULLSCREEN_DESKTOP && - (!window->fullscreen_mode.w || !window->fullscreen_mode.h)) { + (!window->fullscreen_mode.pixel_w || !window->fullscreen_mode.pixel_h)) { wind->fullscreen_flags = SDL_WINDOW_FULLSCREEN_DESKTOP; }