From d3e8b8b523907080839b3cfb77c5b6f72f1cdf2d Mon Sep 17 00:00:00 2001 From: Arjun Srinivasan Date: Tue, 21 May 2024 18:23:45 +0000 Subject: [PATCH] vm_tools: sommelier: Add quirk to fix viewport destination. Fixes viewport destination to size of the screen for games using randr emulation. For some games (like Barotrauma), xwayland sends the wrong viewport destination, causing the game to render in a small box. This adds a quirk to set the destination to the whole screen. Not sure if the bug here is in xwayland or the game, but if it is xwayland it should probably be fixed there at some point. This also reproduces on other wayland compositors. BUG=b:336844348 TEST=run barotrauma Change-Id: Ie1e23c3b5c383a4c99dfbf10b2f4928b610a1253 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/5555696 Commit-Queue: Arjun Srinivasan Reviewed-by: Chloe Pelling Tested-by: Arjun Srinivasan --- quirks/quirks.proto | 1 + sommelier-window.cc | 54 ++++++++++++++++++++++++++++++++++++--------- sommelier-window.h | 4 ++++ 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/quirks/quirks.proto b/quirks/quirks.proto index 363c3c0..b1ff093 100644 --- a/quirks/quirks.proto +++ b/quirks/quirks.proto @@ -46,4 +46,5 @@ enum Feature { FEATURE_BLACK_SCREEN_FIX = 2; FEATURE_CONTAINERIZE_WINDOWS = 3; FEATURE_FORCE_X11_UNMAXIMIZE = 4; + FEATURE_RANDR_EMU_FIX = 5; } diff --git a/sommelier-window.cc b/sommelier-window.cc index 365cfb6..6149c2f 100644 --- a/sommelier-window.cc +++ b/sommelier-window.cc @@ -466,6 +466,8 @@ void sl_internal_toplevel_configure_size_containerized(struct sl_window* window, int safe_window_height = window->max_height ? window->max_height : window->min_height; if (window->use_emulated_rects) { + LOG(VERBOSE) << "using emulated rects " << window->emulated_width << "x" + << window->emulated_height; // If screen size emulation is set by XWayland, set the window size to the // emulated size and adjust the viewport size as Exo had requested it to be. safe_window_width = window->emulated_width; @@ -487,6 +489,17 @@ void sl_internal_toplevel_configure_size_containerized(struct sl_window* window, << safe_window_height; if (window->use_emulated_rects && window->compositor_fullscreen) { + // Some games using emulated rects have xwayland send the wrong viewport + // destination, causing the game to render in a small box. This overrides + // that via quirk to set the destination to the size of the screen. + if (sl_window_should_fix_randr_emu(window)) { + window->viewport_override = true; + window->viewport_width = host_width; + window->viewport_height = host_height; + window->viewport_pointer_scale = + static_cast(output->logical_width) / window->viewport_width; + return; + } // If we are using emulated rects and the window is fullscreen in // compositor, we only have to report the emulated size (done above). Aspect // ratio changes are moot (since compositor fullscreen). We don't have to @@ -594,16 +607,28 @@ void sl_internal_toplevel_configure_size(struct sl_window* window, int32_t width_in_pixels, int32_t height_in_pixels, int& mut_config_idx) { - // Workaround using viewport for when Exo sets sizes that are not - // within the bounds the client requested. - // TODO(b/316990641): Implement resizing via viewports if - // window->fullscreen==true but window->compositor_fullscreen==false. - // Only do this when --only-client-can-exit-fullscreen is set. - if (window->ctx->viewport_resize && - ((window->max_width != 0 && width_in_pixels > window->max_width) || - (window->min_width != 0 && width_in_pixels < window->min_width) || - (window->max_height != 0 && height_in_pixels > window->max_height) || - (window->min_height != 0 && height_in_pixels < window->min_height))) { + // For games with issues with incorrect viewport destination when using randr + // emulation, this will override the viewport destination with the screen size + // when in fullscreen mode. + if (window->use_emulated_rects && window->compositor_fullscreen && + sl_window_should_fix_randr_emu(window)) { + window->viewport_override = true; + window->viewport_width = host_width; + window->viewport_height = host_height; + window->viewport_pointer_scale = + static_cast(window->width) / window->viewport_width; + // Workaround using viewport for when Exo sets sizes that are not + // within the bounds the client requested. + // TODO(b/316990641): Implement resizing via viewports if + // window->fullscreen==true but window->compositor_fullscreen==false. + // Only do this when --only-client-can-exit-fullscreen is set. + } else if (window->ctx->viewport_resize && + ((window->max_width != 0 && width_in_pixels > window->max_width) || + (window->min_width != 0 && width_in_pixels < window->min_width) || + (window->max_height != 0 && + height_in_pixels > window->max_height) || + (window->min_height != 0 && + height_in_pixels < window->min_height))) { window->viewport_override = true; float width_ratio = static_cast(window->width) / width_in_pixels; float height_ratio = static_cast(window->height) / height_in_pixels; @@ -1329,6 +1354,15 @@ bool sl_window_is_client_positioned(struct sl_window* window) { return window->ctx->enable_x11_move_windows; } +bool sl_window_should_fix_randr_emu(struct sl_window* window) { +#ifdef QUIRKS_SUPPORT + if (window->ctx->quirks.IsEnabled(window, quirks::FEATURE_RANDR_EMU_FIX)) { + return true; + } +#endif + return false; +} + void sl_window_get_x_y(struct sl_window* window, uint32_t* x, uint32_t* y) { if (x != nullptr) { *x = window->x; diff --git a/sommelier-window.h b/sommelier-window.h index b16dc45..288a3fe 100644 --- a/sommelier-window.h +++ b/sommelier-window.h @@ -323,6 +323,10 @@ std::set sl_window_logged_quirks(struct sl_window* window); bool sl_window_is_client_positioned(struct sl_window* window); +// Set correct viewport destination from xwayland for incorrectly behaving +// games. +bool sl_window_should_fix_randr_emu(struct sl_window* window); + // Get position of the window. void sl_window_get_x_y(struct sl_window* window, uint32_t* x, uint32_t* y); // Get size of the window, taking account of emulated status.