From c0540d5c28651dd2f76cb96ff36219ac31ec1ed2 Mon Sep 17 00:00:00 2001
From: Antheas Kapenekakis <5252246+antheas@users.noreply.github.com>
Date: Wed, 30 Oct 2024 05:00:17 +0100
Subject: [PATCH] fix(gamescope): improve frame pacing when refresh halving is
 enabled + add param (#1811)

---
 spec_files/gamescope/handheld.patch | 151 ++++++++++++++++++++--------
 1 file changed, 109 insertions(+), 42 deletions(-)

diff --git a/spec_files/gamescope/handheld.patch b/spec_files/gamescope/handheld.patch
index 9a3ef369..f11087ea 100644
--- a/spec_files/gamescope/handheld.patch
+++ b/spec_files/gamescope/handheld.patch
@@ -767,37 +767,78 @@ index 3dd64f8..7dacfe7 100644
 2.47.0
 
 
-From 61ea8edafedd5c8cce320bf6415e6151555ce594 Mon Sep 17 00:00:00 2001
+From c90aff28dae5c92170f47b2dc29c01770ff0dd42 Mon Sep 17 00:00:00 2001
 From: Antheas Kapenekakis <git@antheas.dev>
-Date: Wed, 23 Oct 2024 23:33:53 +0200
+Date: Wed, 30 Oct 2024 00:39:03 +0100
 Subject: [PATCH v2 12/12] fix(battery): run at half hz while at steamUI and
- disable VRR
+ disable VRR V2 + param
 
 ---
- src/steamcompmgr.cpp | 34 +++++++++++++++++++++++++---------
- 1 file changed, 25 insertions(+), 9 deletions(-)
+ src/main.cpp         |  2 ++
+ src/steamcompmgr.cpp | 45 +++++++++++++++++++++++++++++++++-----------
+ 2 files changed, 36 insertions(+), 11 deletions(-)
 
+diff --git a/src/main.cpp b/src/main.cpp
+index 056e1c1..e6a634b 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 },
++	{ "disable-steamui-framelimit", 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 },
+@@ -195,6 +196,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"
++	"  --disable-steamui-framelimit   By default, for displays above 100Hz, framerate is halved in SteamUI. Disable that.\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"
 diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp
-index 7dacfe7..f4446f0 100644
+index 7dacfe7..70698ac 100644
 --- a/src/steamcompmgr.cpp
 +++ b/src/steamcompmgr.cpp
-@@ -149,6 +149,7 @@ extern int g_nDynamicRefreshHz;
- bool g_bForceHDRSupportDebug = false;
- bool g_bHackyEnabled = false;
- bool g_bVRRModesetting = false;
-+bool g_refreshHalve = false;
- extern float g_flInternalDisplayBrightnessNits;
- extern float g_flHDRItmSdrNits;
- extern float g_flHDRItmTargetNits;
-@@ -166,6 +167,7 @@ uint32_t g_reshade_technique_idx = 0;
+@@ -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 = true;
  
  static std::vector< steamcompmgr_win_t* > GetGlobalPossibleFocusWindows();
  static bool
-@@ -838,15 +840,15 @@ static void _update_app_target_refresh_cycle()
+@@ -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
@@ -816,37 +857,46 @@ index 7dacfe7..f4446f0 100644
  			}
  		}
  
-@@ -5105,19 +5107,24 @@ static bool steamcompmgr_should_vblank_window( bool bShouldLimitFPS, uint64_t vb
- 	if ( GetBackend()->IsVRRActive() )
- 		return true;
+@@ -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
  
--	bool bSendCallback = true;
--
  	int nRefreshHz = gamescope::ConvertmHzToHz( g_nNestedRefresh ? g_nNestedRefresh : g_nOutputRefresh );
  	int nTargetFPS = g_nSteamCompMgrTargetFPS;
 -	if ( g_nSteamCompMgrTargetFPS && bShouldLimitFPS && nRefreshHz > nTargetFPS )
-+
-+	if ( nRefreshHz > 90 && g_refreshHalve )
-+	{
-+		// Refresh halve above 90Hz if steamui is active
-+		if ( vblank_idx % 2 != 0 )
-+			return false;
-+	}
-+	else if ( g_nSteamCompMgrTargetFPS && bShouldLimitFPS && nRefreshHz > nTargetFPS )
++	if ( g_nSteamCompMgrTargetFPS && (bShouldLimitFPS || b_bForceFrameLimit) && nRefreshHz > nTargetFPS )
  	{
  		int nVblankDivisor = nRefreshHz / nTargetFPS;
  
- 		if ( vblank_idx % nVblankDivisor != 0 )
--			bSendCallback = false;
-+			return false;
+@@ -5485,7 +5489,7 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev)
  	}
- 
--	return bSendCallback;
-+	return true;
- }
- 
- static bool steamcompmgr_should_vblank_window( steamcompmgr_win_t *w, uint64_t vblank_idx )
-@@ -5549,7 +5556,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
@@ -855,17 +905,34 @@ index 7dacfe7..f4446f0 100644
  	}
  	if ( ev->atom == ctx->atoms.gamescopeDisplayForceInternal )
  	{
-@@ -7628,6 +7635,15 @@ steamcompmgr_main(int argc, char **argv)
+@@ -7507,6 +7511,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, "disable-steamui-framelimit") == 0) {
++					g_bRefreshHalveEnable = false;
+ 				} else if (strcmp(opt_name, "enable-vrr-modesetting") == 0) {
+ 					g_bVRRModesetting = true;
+ 				} else if (strcmp(opt_name, "enable-hacky-texture") == 0) {
+@@ -7628,6 +7634,23 @@ steamcompmgr_main(int argc, char **argv)
  		// as a question.
  		const bool bIsVBlankFromTimer = vblank;
  
 +		if ( window_is_steam( global_focus.focusWindow ) ) {
 +			// Halve refresh rate and disable vrr on SteamUI
 +			cv_adaptive_sync = false;
-+			g_refreshHalve = true;
++			int nRealRefreshHz = gamescope::ConvertmHzToHz( g_nNestedRefresh ? g_nNestedRefresh : g_nOutputRefresh );
++			if (g_bRefreshHalveEnable && 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_refreshHalve = false;
++			g_nSteamCompMgrTargetFPS = g_nSteamCompMgrTargetFPSreq;
++			b_bForceFrameLimit = false;
 +		}
 +
  		// We can always vblank if VRR.