diff --git a/app/src/main/java/app/gamenative/display/GamescopeState.kt b/app/src/main/java/app/gamenative/display/GamescopeState.kt index eee3108af7..2726a9f7a9 100644 --- a/app/src/main/java/app/gamenative/display/GamescopeState.kt +++ b/app/src/main/java/app/gamenative/display/GamescopeState.kt @@ -40,9 +40,6 @@ object GamescopeSettings { const val SHARPNESS_STEPS = 5 const val SHARPNESS_DEFAULT = SHARPNESS_STEPS - /** The vblank grid a gamescope session is launched with (`-r`), in Hz. */ - const val SESSION_GRID_HZ = 1200 - /** gamescope's raw `scaling_sharpness` (0 = maximum sharpening) for a stored UI value. */ fun sharpnessRawValue(ui: Int): Int = (SHARPNESS_STEPS - ui.coerceIn(0, SHARPNESS_STEPS)) * 4 @@ -55,14 +52,6 @@ object GamescopeSettings { return if (mode == GamescopeScalingMode.DEFAULT) "" else " --scaler ${mode.id}" } - /** - * The `-r ` argument for a session's launch command, holding the grid at - * [SESSION_GRID_HZ] so `g_nNestedRefresh` wins over the panel rate the daemon advertises as - * the mode (see [SESSION_GRID_HZ]). - */ - @JvmStatic - fun gridArg(): String = " -r $SESSION_GRID_HZ" - /** * The output resolution a session presents at ("WxH"). [OUTPUT_RESOLUTION_OFF] resolves to the * container's screen size and [OUTPUT_RESOLUTION_DEVICE] to the panel's real pixel size; "" only diff --git a/app/src/main/java/app/gamenative/display/PanelRefresh.kt b/app/src/main/java/app/gamenative/display/PanelRefresh.kt new file mode 100644 index 0000000000..9bed66d4fd --- /dev/null +++ b/app/src/main/java/app/gamenative/display/PanelRefresh.kt @@ -0,0 +1,33 @@ +package app.gamenative.display + +import android.content.Context +import android.hardware.display.DisplayManager +import android.view.Display +import android.view.View +import androidx.core.content.ContextCompat +import kotlin.math.roundToInt + +/** The panel's active refresh rate, read one way for every consumer. */ +object PanelRefresh { + /** The rate reported when the display can't be read. */ + const val FALLBACK_HZ = 60 + + /** + * The panel's refresh rate in Hz: the mode the display is in now, not the fastest it supports, + * rounded to an integer. The daemon's advertised mode and latch-grid period + * ([GameNativeDrm.nativeSetPanelRefreshHz], which gamescope takes its refresh from) and the FPS + * limiter's ceiling both come from here, so they agree; a panel a user holds at 60 Hz counts as + * 60 even when it can do 120. + */ + @JvmStatic + fun activeHz(context: Context, attachedView: View? = null): Int { + val display = attachedView?.display + ?: runCatching { context.display }.getOrNull() + ?: ContextCompat.getSystemService(context, DisplayManager::class.java)?.getDisplay(Display.DEFAULT_DISPLAY) + return display?.refreshRate + ?.takeIf { it.isFinite() && it > 0f } + ?.roundToInt() + ?.coerceAtLeast(5) + ?: FALLBACK_HZ + } +} diff --git a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt index b384369ec7..9fafedb4c3 100644 --- a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt +++ b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt @@ -103,6 +103,7 @@ import app.gamenative.data.LibraryItem import app.gamenative.data.ShooterModeConfig import app.gamenative.data.SteamApp import app.gamenative.display.GameNativeDrm +import app.gamenative.display.PanelRefresh import app.gamenative.display.GamescopeCommandQueue import app.gamenative.display.GamescopeServerComponent import app.gamenative.display.GamescopeSettings @@ -272,7 +273,6 @@ import java.util.concurrent.atomic.AtomicBoolean import kotlin.concurrent.thread import java.util.concurrent.atomic.AtomicInteger import kotlin.io.path.name -import kotlin.math.roundToInt import kotlin.text.lowercase import com.winlator.PrefManager as WinlatorPrefManager @@ -291,7 +291,6 @@ private const val EXIT_PROCESS_TIMEOUT_MS = 30_000L private const val EXIT_PROCESS_POLL_INTERVAL_MS = 1_000L private const val EXIT_PROCESS_RESPONSE_TIMEOUT_MS = 2_000L private const val QUICK_MENU_PROCESS_POLL_INTERVAL_MS = 2_000L -private const val DEFAULT_FPS_LIMITER_MAX_HZ = 60 private const val DEFAULT_FPS_LIMITER_TARGET_HZ = 60 private const val FPS_LIMITER_MAX_MULTIPLIER = 2 private const val FPS_LIMITER_ENABLED_EXTRA = "fpsLimiterEnabled" @@ -314,16 +313,8 @@ private fun initialFpsLimiterTarget(container: Container): Int = * even when it can do 120; a mode change mid-session is reported again by the display * listener below. */ -internal fun detectRefreshRateHz(context: Context, attachedView: View?): Int { - val display = attachedView?.display - ?: context.display - ?: ContextCompat.getSystemService(context, DisplayManager::class.java)?.getDisplay(Display.DEFAULT_DISPLAY) - return display?.refreshRate - ?.takeIf { it.isFinite() && it > 0f } - ?.roundToInt() - ?.coerceAtLeast(5) - ?: DEFAULT_FPS_LIMITER_MAX_HZ -} +internal fun detectRefreshRateHz(context: Context, attachedView: View?): Int = + PanelRefresh.activeHz(context, attachedView) /** Re-reports the panel's active refresh rate to the daemon while a session runs. */ diff --git a/app/src/main/java/com/winlator/xenvironment/components/BionicProgramLauncherComponent.java b/app/src/main/java/com/winlator/xenvironment/components/BionicProgramLauncherComponent.java index 49a1d5fb93..83a910522b 100644 --- a/app/src/main/java/com/winlator/xenvironment/components/BionicProgramLauncherComponent.java +++ b/app/src/main/java/com/winlator/xenvironment/components/BionicProgramLauncherComponent.java @@ -658,7 +658,6 @@ private String wrapWithGamescope(String command) { + (hdr ? " --hdr-enabled" : "") + (reshade.isEmpty() ? "" : " --reshade-effect " + reshade) + GamescopeSettings.scalerArg(container) - + GamescopeSettings.gridArg() + gamescopeModeGeometry() + " -- " + command; } diff --git a/app/src/main/jniLibs/arm64-v8a/libgamenative_drm.so b/app/src/main/jniLibs/arm64-v8a/libgamenative_drm.so index 40225e6048..efd68c2b4b 100755 Binary files a/app/src/main/jniLibs/arm64-v8a/libgamenative_drm.so and b/app/src/main/jniLibs/arm64-v8a/libgamenative_drm.so differ