From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Fri, 22 Nov 2024 01:37:48 +0100 Subject: [NA] add dev script --- subprojects/edid-decode | 1 + sync.sh | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 160000 subprojects/edid-decode create mode 100755 sync.sh diff --git a/subprojects/edid-decode b/subprojects/edid-decode new file mode 160000 index 0000000..c6b859d --- /dev/null +++ b/subprojects/edid-decode @@ -0,0 +1 @@ +Subproject commit c6b859d7f0251e2433fb81bd3f67bd2011c2036c diff --git a/sync.sh b/sync.sh new file mode 100755 index 0000000..878bf6c --- /dev/null +++ b/sync.sh @@ -0,0 +1,21 @@ +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +HOST=$1 +RSYNC="rsync -rv --exclude .git --exclude venv --exclude __pycache__'" +USER=${USER:-bazzite} + +set -e + +meson build/ -Dforce_fallback_for=stb,libdisplay-info,libliftoff,wlroots,vkroots +ninja -C build/ +scp build/src/gamescope ${HOST}:gamescope + +ssh $HOST /bin/bash << EOF + sudo rpm-ostree usroverlay --hotfix + sudo mv ~/gamescope /usr/bin/gamescope + bazzite-session-select gamescope + # sudo reboot +EOF -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Matthew Anderson Date: Fri, 17 May 2024 21:56:55 -0500 Subject: feat: add --custom-refresh-rates option (+ fixes) Commit originally by Matthew, external fixes by Kyle, and new system check move by Antheas. Co-authored-by: Kyle Gospodnetich Co-authored-by: Antheas Kapenekakis --- src/Backends/DRMBackend.cpp | 5 +++++ src/main.cpp | 31 +++++++++++++++++++++++++++++++ src/main.hpp | 2 ++ 3 files changed, 38 insertions(+) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index 0b121e8..75c3258 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -2243,6 +2243,11 @@ namespace gamescope bHasKnownHDRInfo = true; } } + else if ( g_customRefreshRates.size() > 0 && GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL ) { + // Only apply custom refresh rates as a fallback, allowing a graceful transition to the new system. + m_Mutable.ValidDynamicRefreshRates = g_customRefreshRates; + return; + } } if ( !bHasKnownColorimetry ) diff --git a/src/main.cpp b/src/main.cpp index 9dff5c4..8381889 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -129,6 +129,7 @@ const struct option *gamescope_options = (struct option[]){ { "fade-out-duration", required_argument, nullptr, 0 }, { "force-orientation", required_argument, nullptr, 0 }, { "force-windows-fullscreen", no_argument, nullptr, 0 }, + { "custom-refresh-rates", required_argument, nullptr, 0 }, { "disable-color-management", no_argument, nullptr, 0 }, { "sdr-gamut-wideness", required_argument, nullptr, 0 }, @@ -202,6 +203,7 @@ const char usage[] = " --hdr-itm-target-nits set the target luminace of the inverse tone mapping process.\n" " Default: 1000 nits, Max: 10000 nits\n" " --framerate-limit Set a simple framerate limit. Used as a divisor of the refresh rate, rounds down eg 60 / 59 -> 60fps, 60 / 25 -> 30fps. Default: 0, disabled.\n" + " --custom-refresh-rates Set custom refresh rates for the output. eg: 60,90,110-120\n" " --mangoapp Launch with the mangoapp (mangohud) performance overlay enabled. You should use this instead of using mangohud on the game or gamescope.\n" "\n" "Nested mode options:\n" @@ -425,6 +427,33 @@ static enum gamescope::GamescopeBackend parse_backend_name(const char *str) } } +std::vector g_customRefreshRates; +// eg: 60,60,90,110-120 +static std::vector parse_custom_refresh_rates( const char *str ) +{ + std::vector rates; + char *token = strtok( strdup(str), ","); + while (token) + { + char *dash = strchr(token, '-'); + if (dash) + { + uint32_t start = atoi(token); + uint32_t end = atoi(dash + 1); + for (uint32_t i = start; i <= end; i++) + { + rates.push_back(i); + } + } + else + { + rates.push_back(atoi(token)); + } + token = strtok(nullptr, ","); + } + return rates; +} + struct sigaction handle_signal_action = {}; void ShutdownGamescope() @@ -746,6 +775,8 @@ int main(int argc, char **argv) g_eGamescopeModeGeneration = parse_gamescope_mode_generation( optarg ); } else if (strcmp(opt_name, "force-orientation") == 0) { g_DesiredInternalOrientation = force_orientation( optarg ); + } else if (strcmp(opt_name, "custom-refresh-rates") == 0) { + g_customRefreshRates = parse_custom_refresh_rates( optarg ); } else if (strcmp(opt_name, "sharpness") == 0 || strcmp(opt_name, "fsr-sharpness") == 0) { g_upscaleFilterSharpness = atoi( optarg ); diff --git a/src/main.hpp b/src/main.hpp index 2e6fb83..390c04a 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -3,6 +3,7 @@ #include #include +#include extern const char *gamescope_optstring; extern const struct option *gamescope_options; @@ -28,6 +29,7 @@ extern bool g_bGrabbed; extern float g_mouseSensitivity; extern const char *g_sOutputName; +extern std::vector g_customRefreshRates; enum class GamescopeUpscaleFilter : uint32_t { -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alesh Slovak Date: Thu, 26 Sep 2024 07:13:24 -0400 Subject: fix(vrr): Revert "steamcompmgr: Move outdatedInteractiveFocus to window" This reverts commit 299bc3410dcfd46da5e3c988354b60ed3a356900. --- src/steamcompmgr.cpp | 39 +++++++++++++++++++++++-------------- src/steamcompmgr_shared.hpp | 1 - 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 11a7cad..df7616d 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -3299,7 +3299,7 @@ found:; if ( window_has_commits( focus ) ) out->focusWindow = focus; else - focus->outdatedInteractiveFocus = true; + out->outdatedInteractiveFocus = true; // Always update X's idea of focus, but still dirty // the it being outdated so we can resolve that globally later. @@ -6044,28 +6044,37 @@ bool handle_done_commit( steamcompmgr_win_t *w, xwayland_ctx_t *ctx, uint64_t co // Window just got a new available commit, determine if that's worth a repaint // If this is an overlay that we're presenting, repaint - if ( w == global_focus.overlayWindow && w->opacity != TRANSLUCENT ) + if ( gameFocused ) { - hasRepaintNonBasePlane = true; - } + if ( w == global_focus.overlayWindow && w->opacity != TRANSLUCENT ) + { + hasRepaintNonBasePlane = true; + } - if ( w == global_focus.notificationWindow && w->opacity != TRANSLUCENT ) - { - hasRepaintNonBasePlane = true; + if ( w == global_focus.notificationWindow && w->opacity != TRANSLUCENT ) + { + hasRepaintNonBasePlane = true; + } } - - // If this is an external overlay, repaint - if ( w == global_focus.externalOverlayWindow && w->opacity != TRANSLUCENT ) + if ( ctx ) { - hasRepaintNonBasePlane = true; + if ( ctx->focus.outdatedInteractiveFocus ) + { + MakeFocusDirty(); + ctx->focus.outdatedInteractiveFocus = false; + } } - - if ( w->outdatedInteractiveFocus ) + if ( global_focus.outdatedInteractiveFocus ) { MakeFocusDirty(); - w->outdatedInteractiveFocus = false; - } + global_focus.outdatedInteractiveFocus = false; + // If this is an external overlay, repaint + if ( w == global_focus.externalOverlayWindow && w->opacity != TRANSLUCENT ) + { + hasRepaintNonBasePlane = true; + } + } // If this is the main plane, repaint if ( w == global_focus.focusWindow && !w->isSteamStreamingClient ) { diff --git a/src/steamcompmgr_shared.hpp b/src/steamcompmgr_shared.hpp index 095694e..e41fad9 100644 --- a/src/steamcompmgr_shared.hpp +++ b/src/steamcompmgr_shared.hpp @@ -125,7 +125,6 @@ struct steamcompmgr_win_t { unsigned int requestedHeight = 0; bool is_dialog = false; bool maybe_a_dropdown = false; - bool outdatedInteractiveFocus = false; bool hasHwndStyle = false; uint32_t hwndStyle = 0; -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Renn <8340896+AkazaRenn@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:48:26 +0200 Subject: fix(deck): Use super + 1/2 for Overlay/QAM Replaces the patch for CTRL + 1/2 for Overlay/QAM with Super + 1/2 and allows for CTRL for a smooth transition. Suggested-by: Antheas Kapenekakis --- src/wlserver.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 78a86ee..99df8aa 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -290,6 +290,9 @@ static void wlserver_handle_modifiers(struct wl_listener *listener, void *data) bump_input_counter(); } +// false if GS_ENABLE_CTRL_12 exists and is 0, true otherwise +bool env_gs_enable_ctrl_12 = getenv("GS_ENABLE_CTRL_12") ? (getenv("GS_ENABLE_CTRL_12")[0] != '0') : true; + static void wlserver_handle_key(struct wl_listener *listener, void *data) { struct wlserver_keyboard *keyboard = wl_container_of( listener, keyboard, key ); @@ -310,7 +313,14 @@ static void wlserver_handle_key(struct wl_listener *listener, void *data) keysym == XKB_KEY_XF86AudioLowerVolume || keysym == XKB_KEY_XF86AudioRaiseVolume || keysym == XKB_KEY_XF86PowerOff; - if ( ( event->state == WL_KEYBOARD_KEY_STATE_PRESSED || event->state == WL_KEYBOARD_KEY_STATE_RELEASED ) && forbidden_key ) + + // Check for steam overlay key (ctrl/super + 1/2) + bool is_steamshortcut = + ((env_gs_enable_ctrl_12 && (keyboard->wlr->modifiers.depressed & WLR_MODIFIER_CTRL)) || + (keyboard->wlr->modifiers.depressed & WLR_MODIFIER_LOGO)) && + (keysym == XKB_KEY_1 || keysym == XKB_KEY_2); + + if ( ( event->state == WL_KEYBOARD_KEY_STATE_PRESSED || event->state == WL_KEYBOARD_KEY_STATE_RELEASED ) && (forbidden_key || is_steamshortcut) ) { // Always send volume+/- to root server only, to avoid it reaching the game. struct wlr_surface *old_kb_surf = wlserver.kb_focus_surface; @@ -319,6 +329,13 @@ static void wlserver_handle_key(struct wl_listener *listener, void *data) { wlserver_keyboardfocus( new_kb_surf, false ); wlr_seat_set_keyboard( wlserver.wlr.seat, keyboard->wlr ); + if (is_steamshortcut) + { + // send ctrl down modifier to trigger the overlay + wlr_keyboard_modifiers ctrl_down_modifier; + ctrl_down_modifier.depressed = WLR_MODIFIER_CTRL; + wlr_seat_keyboard_notify_modifiers(wlserver.wlr.seat, &ctrl_down_modifier); + } wlr_seat_keyboard_notify_key( wlserver.wlr.seat, event->time_msec, event->keycode, event->state ); wlserver_keyboardfocus( old_kb_surf, false ); return; -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Fri, 11 Oct 2024 17:52:48 +0200 Subject: fix: allow for disabling touch atom click Causes issues in certain devices (or not anymore?). Parameter option by Kyle. Co-authored-by: Kyle Gospodnetich --- src/main.cpp | 2 ++ src/steamcompmgr.cpp | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 8381889..a76b51b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -128,6 +128,7 @@ const struct option *gamescope_options = (struct option[]){ { "disable-xres", no_argument, nullptr, 'x' }, { "fade-out-duration", required_argument, nullptr, 0 }, { "force-orientation", required_argument, nullptr, 0 }, + { "disable-touch-click", no_argument, nullptr, 0 }, { "force-windows-fullscreen", no_argument, nullptr, 0 }, { "custom-refresh-rates", required_argument, nullptr, 0 }, @@ -188,6 +189,7 @@ const char usage[] = " -T, --stats-path write statistics to path\n" " -C, --hide-cursor-delay hide cursor image after delay\n" " -e, --steam enable Steam integration\n" + " --disable-touch-click disable touchscreen tap acting as a click\n" " --xwayland-count create N xwayland servers\n" " --prefer-vk-device prefer Vulkan device for compositing (ex: 1002:7300)\n" " --force-orientation rotate the internal display (left, right, normal, upsidedown)\n" diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index df7616d..4a17499 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -197,6 +197,7 @@ update_runtime_info(); gamescope::ConVar cv_adaptive_sync( "adaptive_sync", false, "Whether or not adaptive sync is enabled if available." ); gamescope::ConVar cv_adaptive_sync_ignore_overlay( "adaptive_sync_ignore_overlay", false, "Whether or not to ignore overlay planes for pushing commits with adaptive sync." ); gamescope::ConVar cv_adaptive_sync_overlay_cycles( "adaptive_sync_overlay_cycles", 1, "Number of vblank cycles to ignore overlay repaints before forcing a commit with adaptive sync." ); +gamescope::ConVar cv_disable_touch_click{ "disable_touch_click", false, "Prevents touchscreen taps acting as clicks" }; uint64_t g_SteamCompMgrLimitedAppRefreshCycle = 16'666'666; uint64_t g_SteamCompMgrAppRefreshCycle = 16'666'666; @@ -5185,7 +5186,7 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) MakeFocusDirty(); } } - if (ev->atom == ctx->atoms.steamTouchClickModeAtom ) + if (ev->atom == ctx->atoms.steamTouchClickModeAtom && !cv_disable_touch_click ) { gamescope::cv_touch_click_mode = (gamescope::TouchClickMode) get_prop(ctx, ctx->root, ctx->atoms.steamTouchClickModeAtom, 0u ); } @@ -7476,6 +7477,8 @@ steamcompmgr_main(int argc, char **argv) g_reshade_technique_idx = atoi(optarg); } else if (strcmp(opt_name, "mura-map") == 0) { set_mura_overlay(optarg); + } else if (strcmp(opt_name, "disable-touch-click") == 0) { + cv_disable_touch_click = true; } break; case '?': -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Fri, 11 Oct 2024 21:56:54 +0200 Subject: fix(intel-gpu): allow for (enabling) hacky texture Disabling hacky texture will use more hardware planes, causing some devices to composite yielding lower fps. Required for intel to work --- src/main.cpp | 2 ++ src/steamcompmgr.cpp | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index a76b51b..84e05a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -128,6 +128,7 @@ const struct option *gamescope_options = (struct option[]){ { "disable-xres", no_argument, nullptr, 'x' }, { "fade-out-duration", required_argument, nullptr, 0 }, { "force-orientation", required_argument, nullptr, 0 }, + { "enable-hacky-texture", no_argument, nullptr, 0 }, { "disable-touch-click", no_argument, nullptr, 0 }, { "force-windows-fullscreen", no_argument, nullptr, 0 }, { "custom-refresh-rates", required_argument, nullptr, 0 }, @@ -189,6 +190,7 @@ const char usage[] = " -T, --stats-path write statistics to path\n" " -C, --hide-cursor-delay hide cursor image after delay\n" " -e, --steam enable Steam integration\n" + " --enable-hacky-texture enable hacky texture on hw that support it\n" " --disable-touch-click disable touchscreen tap acting as a click\n" " --xwayland-count create N xwayland servers\n" " --prefer-vk-device prefer Vulkan device for compositing (ex: 1002:7300)\n" diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 4a17499..da3115f 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -147,6 +147,7 @@ static lut3d_t g_tmpLut3d; extern int g_nDynamicRefreshHz; bool g_bForceHDRSupportDebug = false; +bool g_bHackyEnabled = false; extern float g_flInternalDisplayBrightnessNits; extern float g_flHDRItmSdrNits; extern float g_flHDRItmTargetNits; @@ -2412,7 +2413,7 @@ paint_all(bool async) if ( overlay == global_focus.inputFocusWindow ) update_touch_scaling( &frameInfo ); } - else if ( !GetBackend()->UsesVulkanSwapchain() && GetBackend()->IsSessionBased() ) + else if ( g_bHackyEnabled && !GetBackend()->UsesVulkanSwapchain() && GetBackend()->IsSessionBased() ) { auto tex = vulkan_get_hacky_blank_texture(); if ( tex != nullptr ) @@ -7479,6 +7480,8 @@ steamcompmgr_main(int argc, char **argv) set_mura_overlay(optarg); } else if (strcmp(opt_name, "disable-touch-click") == 0) { cv_disable_touch_click = true; + } else if (strcmp(opt_name, "enable-hacky-texture") == 0) { + g_bHackyEnabled = true; } break; case '?': -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Fri, 11 Oct 2024 23:01:13 +0200 Subject: fix: re-add external orientation options to not break current sessions (incl. applying ext. orientation) --- src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 84e05a9..2398535 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -129,6 +129,8 @@ const struct option *gamescope_options = (struct option[]){ { "fade-out-duration", required_argument, nullptr, 0 }, { "force-orientation", required_argument, nullptr, 0 }, { "enable-hacky-texture", no_argument, nullptr, 0 }, + { "force-panel-type", required_argument, nullptr, 0 }, + { "force-external-orientation", required_argument, nullptr, 0 }, { "disable-touch-click", no_argument, nullptr, 0 }, { "force-windows-fullscreen", no_argument, nullptr, 0 }, { "custom-refresh-rates", required_argument, nullptr, 0 }, @@ -777,7 +779,7 @@ int main(int argc, char **argv) gamescope::cv_touch_click_mode = (gamescope::TouchClickMode) atoi( optarg ); } else if (strcmp(opt_name, "generate-drm-mode") == 0) { g_eGamescopeModeGeneration = parse_gamescope_mode_generation( optarg ); - } else if (strcmp(opt_name, "force-orientation") == 0) { + } else if (strcmp(opt_name, "force-orientation") == 0 || strcmp(opt_name, "force-external-orientation") == 0) { g_DesiredInternalOrientation = force_orientation( optarg ); } else if (strcmp(opt_name, "custom-refresh-rates") == 0) { g_customRefreshRates = parse_custom_refresh_rates( optarg ); -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: honjow Date: Wed, 16 Oct 2024 00:23:58 +0800 Subject: fix(external): fix crash when using external touchscreens --- src/wlserver.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 99df8aa..5e8f516 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -2492,8 +2492,12 @@ static void apply_touchscreen_orientation(double *x, double *y ) double tx = 0; double ty = 0; - // Use internal screen always for orientation purposes. - switch ( GetBackend()->GetConnector( gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL )->GetCurrentOrientation() ) + auto orientation = GAMESCOPE_PANEL_ORIENTATION_AUTO; + if ( GetBackend() && GetBackend()->GetCurrentConnector( ) ) + { + orientation = GetBackend()->GetCurrentConnector()->GetCurrentOrientation(); + } + switch ( orientation ) { default: case GAMESCOPE_PANEL_ORIENTATION_AUTO: -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Fri, 11 Oct 2024 23:47:59 +0200 Subject: feat(vrr): allow for setting refresh rate if the internal display allows For the Ally, we have a set of VFP that work to set the refresh rate. They can also be used for VRR but gamescope does not currently allow for it. Therefore, bypass some checks to allow it to work just for this usecase. --- src/main.cpp | 2 ++ src/steamcompmgr.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2398535..0621c65 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -132,6 +132,7 @@ const struct option *gamescope_options = (struct option[]){ { "force-panel-type", required_argument, nullptr, 0 }, { "force-external-orientation", required_argument, nullptr, 0 }, { "disable-touch-click", no_argument, nullptr, 0 }, + { "enable-vrr-modesetting", no_argument, nullptr, 0 }, { "force-windows-fullscreen", no_argument, nullptr, 0 }, { "custom-refresh-rates", required_argument, nullptr, 0 }, @@ -194,6 +195,7 @@ const char usage[] = " -e, --steam enable Steam integration\n" " --enable-hacky-texture enable hacky texture on hw that support it\n" " --disable-touch-click disable touchscreen tap acting as a click\n" + " --enable-vrr-modesetting enable setting framerate while VRR is on in the internal display\n" " --xwayland-count create N xwayland servers\n" " --prefer-vk-device prefer Vulkan device for compositing (ex: 1002:7300)\n" " --force-orientation rotate the internal display (left, right, normal, upsidedown)\n" diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index da3115f..69fd348 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -148,6 +148,7 @@ extern int g_nDynamicRefreshHz; bool g_bForceHDRSupportDebug = false; bool g_bHackyEnabled = false; +bool g_bVRRModesetting = false; extern float g_flInternalDisplayBrightnessNits; extern float g_flHDRItmSdrNits; extern float g_flHDRItmTargetNits; @@ -899,7 +900,7 @@ bool g_bChangeDynamicRefreshBasedOnGameOpenRatherThanActive = false; bool steamcompmgr_window_should_limit_fps( steamcompmgr_win_t *w ) { // VRR + FPS Limit needs another approach. - if ( GetBackend()->IsVRRActive() ) + if ( GetBackend()->IsVRRActive() && !(g_bVRRModesetting && GetBackend()->GetScreenType() == gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL) ) return false; return w && !window_is_steam( w ) && !w->isOverlay && !w->isExternalOverlay; @@ -923,7 +924,7 @@ steamcompmgr_user_has_any_game_open() bool steamcompmgr_window_should_refresh_switch( steamcompmgr_win_t *w ) { - if ( GetBackend()->IsVRRActive() ) + if ( GetBackend()->IsVRRActive() && !(g_bVRRModesetting && GetBackend()->GetScreenType() == gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL)) return false; if ( g_bChangeDynamicRefreshBasedOnGameOpenRatherThanActive ) @@ -7480,6 +7481,8 @@ steamcompmgr_main(int argc, char **argv) set_mura_overlay(optarg); } else if (strcmp(opt_name, "disable-touch-click") == 0) { cv_disable_touch_click = true; + } else if (strcmp(opt_name, "enable-vrr-modesetting") == 0) { + g_bVRRModesetting = true; } else if (strcmp(opt_name, "enable-hacky-texture") == 0) { g_bHackyEnabled = true; } -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Fri, 11 Oct 2024 19:09:05 +0200 Subject: feat: add external option that now only lies to steam Previously, there was a force-panel option that allowed for VRR. However, this is no longer the case and VRR works fine. This option still allows for scaling the display though. So, create a variant of the patch that only does that. --- src/main.cpp | 16 ++++++++++++++++ src/steamcompmgr.cpp | 2 +- src/steamcompmgr.hpp | 1 + src/wlserver.cpp | 2 +- src/wlserver.hpp | 1 + 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0621c65..056e1c1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -199,6 +199,7 @@ const char usage[] = " --xwayland-count create N xwayland servers\n" " --prefer-vk-device prefer Vulkan device for compositing (ex: 1002:7300)\n" " --force-orientation rotate the internal display (left, right, normal, upsidedown)\n" + " --force-panel-type lie to steam that the screen is external\n" " --force-windows-fullscreen force windows inside of gamescope to be the size of the nested display (fullscreen)\n" " --cursor-scale-height if specified, sets a base output height to linearly scale the cursor against.\n" " --hdr-enabled enable HDR output (needs Gamescope WSI layer enabled for support from clients)\n" @@ -373,6 +374,19 @@ static GamescopePanelOrientation force_orientation(const char *str) } } +bool g_FakeExternal = false; +static bool force_panel_type_external(const char *str) +{ + if (strcmp(str, "internal") == 0) { + return false; + } else if (strcmp(str, "external") == 0) { + return true; + } else { + fprintf( stderr, "gamescope: invalid value for --force-panel-type\n" ); + exit(1); + } +} + static enum GamescopeUpscaleScaler parse_upscaler_scaler(const char *str) { if (strcmp(str, "auto") == 0) { @@ -783,6 +797,8 @@ int main(int argc, char **argv) g_eGamescopeModeGeneration = parse_gamescope_mode_generation( optarg ); } else if (strcmp(opt_name, "force-orientation") == 0 || strcmp(opt_name, "force-external-orientation") == 0) { g_DesiredInternalOrientation = force_orientation( optarg ); + } else if (strcmp(opt_name, "force-panel-type") == 0) { + g_FakeExternal = force_panel_type_external( optarg ); } else if (strcmp(opt_name, "custom-refresh-rates") == 0) { g_customRefreshRates = parse_custom_refresh_rates( optarg ); } else if (strcmp(opt_name, "sharpness") == 0 || diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 69fd348..3dd64f8 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -7192,7 +7192,7 @@ void update_mode_atoms(xwayland_ctx_t *root_ctx, bool* needs_flush = nullptr) if (needs_flush) *needs_flush = true; - if ( GetBackend()->GetCurrentConnector() && GetBackend()->GetCurrentConnector()->GetScreenType() == gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL ) + if ( !g_FakeExternal && GetBackend()->GetCurrentConnector() && GetBackend()->GetCurrentConnector()->GetScreenType() == gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL ) { XDeleteProperty(root_ctx->dpy, root_ctx->root, root_ctx->atoms.gamescopeDisplayModeListExternal); diff --git a/src/steamcompmgr.hpp b/src/steamcompmgr.hpp index 9f384c4..30e48e8 100644 --- a/src/steamcompmgr.hpp +++ b/src/steamcompmgr.hpp @@ -127,6 +127,7 @@ extern float focusedWindowScaleY; extern float focusedWindowOffsetX; extern float focusedWindowOffsetY; +extern bool g_FakeExternal; extern bool g_bFSRActive; extern uint32_t inputCounter; diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 5e8f516..1eeaa25 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -1078,7 +1078,7 @@ static uint32_t get_conn_display_info_flags() return 0; uint32_t flags = 0; - if ( pConn->GetScreenType() == gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL ) + if ( pConn->GetScreenType() == gamescope::GAMESCOPE_SCREEN_TYPE_INTERNAL && !g_FakeExternal ) flags |= GAMESCOPE_CONTROL_DISPLAY_FLAG_INTERNAL_DISPLAY; if ( pConn->SupportsVRR() ) flags |= GAMESCOPE_CONTROL_DISPLAY_FLAG_SUPPORTS_VRR; diff --git a/src/wlserver.hpp b/src/wlserver.hpp index 0569472..104f7a2 100644 --- a/src/wlserver.hpp +++ b/src/wlserver.hpp @@ -190,6 +190,7 @@ struct wlserver_t { }; extern struct wlserver_t wlserver; +extern bool g_FakeExternal; std::vector wlserver_xdg_commit_queue(); -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Mon, 14 Oct 2024 22:42:20 +0200 Subject: fix(display-config): always fill in mutable refresh rates Assume the user is not lying to us when they fill in dynamic_refresh_rates and that gamescope will work with e.g., CVT, so accept it even if no custom modeline generation has been provided. --- src/Backends/DRMBackend.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index 75c3258..f014be9 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -2161,7 +2161,9 @@ namespace gamescope sol::optional otDynamicRefreshRates = tTable["dynamic_refresh_rates"]; sol::optional ofnDynamicModegen = tTable["dynamic_modegen"]; - if ( otDynamicRefreshRates && ofnDynamicModegen ) + if ( otDynamicRefreshRates && !ofnDynamicModegen ) + m_Mutable.ValidDynamicRefreshRates = TableToVector( *otDynamicRefreshRates ); + else if ( otDynamicRefreshRates && ofnDynamicModegen ) { m_Mutable.ValidDynamicRefreshRates = TableToVector( *otDynamicRefreshRates ); -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Fri, 25 Oct 2024 21:22:10 +0200 Subject: fix(vrr): allow frame limiter to work with VRR enabled Down to 48hz, modeset the correct framerate. Below 48hz, disable VRR and use the classic frame limiter. --- src/steamcompmgr.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 3dd64f8..7dacfe7 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -165,6 +165,7 @@ uint32_t g_reshade_technique_idx = 0; bool g_bSteamIsActiveWindow = false; bool g_bForceInternal = false; +bool g_bVRRRequested = false; static std::vector< steamcompmgr_win_t* > GetGlobalPossibleFocusWindows(); static bool @@ -827,6 +828,28 @@ static void _update_app_target_refresh_cycle() { auto rates = GetBackend()->GetCurrentConnector()->GetValidDynamicRefreshRates(); + if (g_bVRRModesetting) { + if (g_bVRRRequested) { + // If modeset VRR, go upwards to match the refresh rate 1-1. Refresh + // doubling would hurt us here by breaking the frame limiter. + for ( auto rate = rates.begin(); rate != rates.end(); rate++ ) + { + if ((int)*rate == target_fps) + { + g_nDynamicRefreshRate[ type ] = *rate; + // Enable VRR as we have the correct refresh rate + cv_adaptive_sync = true; + return; + } + } + // Otherwise, disable VRR as we can't match the refresh rate 1-1 + // (e.g., below 48hz). + cv_adaptive_sync = false; + } else { + cv_adaptive_sync = false; + } + } + // Find highest mode to do refresh doubling with. for ( auto rate = rates.rbegin(); rate != rates.rend(); rate++ ) { @@ -5522,8 +5545,11 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) } if ( ev->atom == ctx->atoms.gamescopeVRREnabled ) { - bool enabled = !!get_prop( ctx, ctx->root, ctx->atoms.gamescopeVRREnabled, 0 ); - cv_adaptive_sync = enabled; + g_bVRRRequested = !!get_prop( ctx, ctx->root, ctx->atoms.gamescopeVRREnabled, 0 ); + // Try to match refresh rate and have that set the cv_adaptive_sync only if it can + if (g_bVRRModesetting) update_app_target_refresh_cycle(); + // otherwise, fall back to original behavior + else cv_adaptive_sync = g_bVRRRequested; } if ( ev->atom == ctx->atoms.gamescopeDisplayForceInternal ) { -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Wed, 30 Oct 2024 00:39:03 +0100 Subject: fix(battery): run at half hz while at steamUI and disable VRR V2 + param --- src/steamcompmgr.cpp | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 7dacfe7..4098c44 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -166,6 +166,9 @@ uint32_t g_reshade_technique_idx = 0; bool g_bSteamIsActiveWindow = false; bool g_bForceInternal = false; bool g_bVRRRequested = false; +bool g_bVRRCanEnable = false; +bool b_bForceFrameLimit = false; +bool g_bRefreshHalveEnable = false; static std::vector< steamcompmgr_win_t* > GetGlobalPossibleFocusWindows(); static bool @@ -793,6 +796,7 @@ uint64_t g_uCurrentBasePlaneCommitID = 0; bool g_bCurrentBasePlaneIsFifo = false; static int g_nSteamCompMgrTargetFPS = 0; +static int g_nSteamCompMgrTargetFPSreq = 0; static uint64_t g_uDynamicRefreshEqualityTime = 0; static int g_nDynamicRefreshRate[gamescope::GAMESCOPE_SCREEN_TYPE_COUNT] = { 0, 0 }; // Delay to stop modes flickering back and forth. @@ -812,7 +816,7 @@ static void _update_app_target_refresh_cycle() int target_fps = g_nCombinedAppRefreshCycleOverride[type]; g_nDynamicRefreshRate[ type ] = 0; - g_nSteamCompMgrTargetFPS = 0; + g_nSteamCompMgrTargetFPSreq = 0; if ( !target_fps ) { @@ -821,7 +825,7 @@ static void _update_app_target_refresh_cycle() if ( g_nCombinedAppRefreshCycleChangeFPS[ type ] ) { - g_nSteamCompMgrTargetFPS = target_fps; + g_nSteamCompMgrTargetFPSreq = target_fps; } if ( g_nCombinedAppRefreshCycleChangeRefresh[ type ] ) @@ -838,15 +842,15 @@ static void _update_app_target_refresh_cycle() { g_nDynamicRefreshRate[ type ] = *rate; // Enable VRR as we have the correct refresh rate - cv_adaptive_sync = true; + g_bVRRCanEnable = true; return; } } // Otherwise, disable VRR as we can't match the refresh rate 1-1 // (e.g., below 48hz). - cv_adaptive_sync = false; + g_bVRRCanEnable = false; } else { - cv_adaptive_sync = false; + g_bVRRCanEnable = false; } } @@ -864,9 +868,9 @@ static void _update_app_target_refresh_cycle() static void update_app_target_refresh_cycle() { - int nPrevFPSLimit = g_nSteamCompMgrTargetFPS; + int nPrevFPSLimit = g_nSteamCompMgrTargetFPSreq; _update_app_target_refresh_cycle(); - if ( !!g_nSteamCompMgrTargetFPS != !!nPrevFPSLimit ) + if ( !!g_nSteamCompMgrTargetFPSreq != !!nPrevFPSLimit ) update_runtime_info(); } @@ -5052,7 +5056,7 @@ update_runtime_info() if ( g_nRuntimeInfoFd < 0 ) return; - uint32_t limiter_enabled = g_nSteamCompMgrTargetFPS != 0 ? 1 : 0; + uint32_t limiter_enabled = g_nSteamCompMgrTargetFPSreq != 0 ? 1 : 0; pwrite( g_nRuntimeInfoFd, &limiter_enabled, sizeof( limiter_enabled ), 0 ); } @@ -5109,7 +5113,7 @@ static bool steamcompmgr_should_vblank_window( bool bShouldLimitFPS, uint64_t vb int nRefreshHz = gamescope::ConvertmHzToHz( g_nNestedRefresh ? g_nNestedRefresh : g_nOutputRefresh ); int nTargetFPS = g_nSteamCompMgrTargetFPS; - if ( g_nSteamCompMgrTargetFPS && bShouldLimitFPS && nRefreshHz > nTargetFPS ) + if ( g_nSteamCompMgrTargetFPS && (bShouldLimitFPS || b_bForceFrameLimit) && nRefreshHz > nTargetFPS ) { int nVblankDivisor = nRefreshHz / nTargetFPS; @@ -5485,7 +5489,7 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) } if ( ev->atom == ctx->atoms.gamescopeFPSLimit ) { - g_nSteamCompMgrTargetFPS = get_prop( ctx, ctx->root, ctx->atoms.gamescopeFPSLimit, 0 ); + g_nSteamCompMgrTargetFPSreq = get_prop( ctx, ctx->root, ctx->atoms.gamescopeFPSLimit, 0 ); update_runtime_info(); } for (int i = 0; i < gamescope::GAMESCOPE_SCREEN_TYPE_COUNT; i++) @@ -5549,7 +5553,7 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) // Try to match refresh rate and have that set the cv_adaptive_sync only if it can if (g_bVRRModesetting) update_app_target_refresh_cycle(); // otherwise, fall back to original behavior - else cv_adaptive_sync = g_bVRRRequested; + else g_bVRRCanEnable = g_bVRRRequested; } if ( ev->atom == ctx->atoms.gamescopeDisplayForceInternal ) { @@ -7628,6 +7632,23 @@ steamcompmgr_main(int argc, char **argv) // as a question. const bool bIsVBlankFromTimer = vblank; + if ( g_bRefreshHalveEnable && window_is_steam( global_focus.focusWindow ) ) { + // Halve refresh rate and disable vrr on SteamUI + cv_adaptive_sync = false; + int nRealRefreshHz = gamescope::ConvertmHzToHz( g_nNestedRefresh ? g_nNestedRefresh : g_nOutputRefresh ); + if (nRealRefreshHz > 100 && g_nSteamCompMgrTargetFPSreq > 34) { + g_nSteamCompMgrTargetFPS = nRealRefreshHz / 2; + b_bForceFrameLimit = true; + } else { + g_nSteamCompMgrTargetFPS = g_nSteamCompMgrTargetFPSreq; + b_bForceFrameLimit = false; + } + } else { + cv_adaptive_sync = g_bVRRCanEnable; + g_nSteamCompMgrTargetFPS = g_nSteamCompMgrTargetFPSreq; + b_bForceFrameLimit = false; + } + // We can always vblank if VRR. const bool bVRR = GetBackend()->IsVRRActive(); if ( bVRR ) -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Fri, 1 Nov 2024 17:27:54 +0100 Subject: feat(battery): add atom for controlling frame halving --- src/steamcompmgr.cpp | 6 ++++++ src/xwayland_ctx.hpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 4098c44..6c8ce74 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -5919,6 +5919,10 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) MakeFocusDirty(); } } + if ( ev->atom == ctx->atoms.gamescopeFrameHalveAtom ) + { + g_bRefreshHalveEnable = !!get_prop( ctx, ctx->root, ctx->atoms.gamescopeFrameHalveAtom, 0 ); + } } static int @@ -7089,6 +7093,8 @@ void init_xwayland_ctx(uint32_t serverId, gamescope_xwayland_server_t *xwayland_ ctx->atoms.primarySelection = XInternAtom(ctx->dpy, "PRIMARY", false); ctx->atoms.targets = XInternAtom(ctx->dpy, "TARGETS", false); + ctx->atoms.gamescopeFrameHalveAtom = XInternAtom( ctx->dpy, "GAMESCOPE_STEAMUI_HALFHZ", false );; + ctx->root_width = DisplayWidth(ctx->dpy, ctx->scr); ctx->root_height = DisplayHeight(ctx->dpy, ctx->scr); diff --git a/src/xwayland_ctx.hpp b/src/xwayland_ctx.hpp index df2af70..e4eec9f 100644 --- a/src/xwayland_ctx.hpp +++ b/src/xwayland_ctx.hpp @@ -246,6 +246,8 @@ struct xwayland_ctx_t final : public gamescope::IWaitable Atom clipboard; Atom primarySelection; Atom targets; + + Atom gamescopeFrameHalveAtom; } atoms; bool HasQueuedEvents(); -- 2.47.0 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Antheas Kapenekakis Date: Wed, 13 Nov 2024 17:22:05 +0100 Subject: feat: add DPMS support through an Atom --- src/Backends/DRMBackend.cpp | 16 +++++++++++++--- src/rendervulkan.hpp | 2 ++ src/steamcompmgr.cpp | 15 ++++++++++++--- src/xwayland_ctx.hpp | 1 + 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index f014be9..6bb0b88 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -2669,6 +2669,9 @@ int drm_prepare( struct drm_t *drm, bool async, const struct FrameInfo_t *frameI drm->needs_modeset = true; } + if (drm->pCRTC && drm->pCRTC->GetProperties().ACTIVE->GetCurrentValue() != !frameInfo->dpms) + drm->needs_modeset = true; + drm_colorspace uColorimetry = DRM_MODE_COLORIMETRY_DEFAULT; const bool bWantsHDR10 = g_bOutputHDREnabled && frameInfo->outputEncodingEOTF == EOTF_PQ; @@ -2724,7 +2727,7 @@ int drm_prepare( struct drm_t *drm, bool async, const struct FrameInfo_t *frameI uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK; // We do internal refcounting with these events - if ( drm->pCRTC != nullptr ) + if ( !frameInfo->dpms && drm->pCRTC != nullptr) flags |= DRM_MODE_PAGE_FLIP_EVENT; if ( async || g_bForceAsyncFlips ) @@ -2797,7 +2800,13 @@ int drm_prepare( struct drm_t *drm, bool async, const struct FrameInfo_t *frameI if ( drm->pCRTC ) { - drm->pCRTC->GetProperties().ACTIVE->SetPendingValue( drm->req, 1u, true ); + if ( frameInfo->dpms ) { + // We can't disable a CRTC if it's already disabled + if (drm->pCRTC->GetProperties().ACTIVE->GetCurrentValue() != 0) + drm->pCRTC->GetProperties().ACTIVE->SetPendingValue(drm->req, 0, true); + } + else + drm->pCRTC->GetProperties().ACTIVE->SetPendingValue( drm->req, 1u, true ); drm->pCRTC->GetProperties().MODE_ID->SetPendingValue( drm->req, drm->pending.mode_id ? drm->pending.mode_id->GetBlobValue() : 0lu, true ); if ( drm->pCRTC->GetProperties().VRR_ENABLED ) @@ -2828,7 +2837,7 @@ int drm_prepare( struct drm_t *drm, bool async, const struct FrameInfo_t *frameI drm->flags = flags; int ret; - if ( drm->pCRTC == nullptr ) { + if (frameInfo->dpms || drm->pCRTC == nullptr ) { ret = 0; } else if ( drm->bUseLiftoff ) { ret = drm_prepare_liftoff( drm, frameInfo, needs_modeset ); @@ -3391,6 +3400,7 @@ namespace gamescope FrameInfo_t presentCompFrameInfo = {}; presentCompFrameInfo.allowVRR = pFrameInfo->allowVRR; + presentCompFrameInfo.dpms = pFrameInfo->dpms; presentCompFrameInfo.outputEncodingEOTF = pFrameInfo->outputEncodingEOTF; if ( bNeedsFullComposite ) diff --git a/src/rendervulkan.hpp b/src/rendervulkan.hpp index b537170..ccabd88 100644 --- a/src/rendervulkan.hpp +++ b/src/rendervulkan.hpp @@ -281,6 +281,8 @@ struct FrameInfo_t bool applyOutputColorMgmt; // drm only EOTF outputEncodingEOTF; + bool dpms; + int layerCount; struct Layer_t { diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 6c8ce74..dfee904 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -169,6 +169,8 @@ bool g_bVRRRequested = false; bool g_bVRRCanEnable = false; bool b_bForceFrameLimit = false; bool g_bRefreshHalveEnable = false; +bool g_bDPMS = false; +bool g_bDPMS_set = false; static std::vector< steamcompmgr_win_t* > GetGlobalPossibleFocusWindows(); static bool @@ -2271,7 +2273,7 @@ bool ShouldDrawCursor() } static void -paint_all(bool async) +paint_all(bool async, bool dpms) { gamescope_xwayland_server_t *root_server = wlserver_get_xwayland_server(0); xwayland_ctx_t *root_ctx = root_server->ctx.get(); @@ -2322,6 +2324,7 @@ paint_all(bool async) frameInfo.outputEncodingEOTF = g_ColorMgmt.pending.outputEncodingEOTF; frameInfo.allowVRR = cv_adaptive_sync; frameInfo.bFadingOut = fadingOut; + frameInfo.dpms = dpms; // If the window we'd paint as the base layer is the streaming client, // find the video underlay and put it up first in the scenegraph @@ -5923,6 +5926,10 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) { g_bRefreshHalveEnable = !!get_prop( ctx, ctx->root, ctx->atoms.gamescopeFrameHalveAtom, 0 ); } + if (ev->atom == ctx->atoms.gamescopeDPMS) + { + g_bDPMS = !!get_prop(ctx, ctx->root, ctx->atoms.gamescopeDPMS, 0); + } } static int @@ -7094,6 +7101,7 @@ void init_xwayland_ctx(uint32_t serverId, gamescope_xwayland_server_t *xwayland_ ctx->atoms.targets = XInternAtom(ctx->dpy, "TARGETS", false); ctx->atoms.gamescopeFrameHalveAtom = XInternAtom( ctx->dpy, "GAMESCOPE_STEAMUI_HALFHZ", false );; + ctx->atoms.gamescopeDPMS = XInternAtom(ctx->dpy, "GAMESCOPE_DPMS", false); ctx->root_width = DisplayWidth(ctx->dpy, ctx->scr); ctx->root_height = DisplayHeight(ctx->dpy, ctx->scr); @@ -8061,9 +8069,10 @@ steamcompmgr_main(int argc, char **argv) bShouldPaint = false; } - if ( bShouldPaint ) + if (bShouldPaint || (g_bDPMS != g_bDPMS_set && vblank)) { - paint_all( eFlipType == FlipType::Async ); + g_bDPMS_set = g_bDPMS; + paint_all( eFlipType == FlipType::Async, g_bDPMS ); hasRepaint = false; hasRepaintNonBasePlane = false; diff --git a/src/xwayland_ctx.hpp b/src/xwayland_ctx.hpp index e4eec9f..2347cbb 100644 --- a/src/xwayland_ctx.hpp +++ b/src/xwayland_ctx.hpp @@ -248,6 +248,7 @@ struct xwayland_ctx_t final : public gamescope::IWaitable Atom targets; Atom gamescopeFrameHalveAtom; + Atom gamescopeDPMS; } atoms; bool HasQueuedEvents(); -- 2.47.0