mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-12 19:41:10 +00:00
fix: draw the gamescope cursor only when that option is on
The extra plane costs frames on a phone, so compositing stays off unless Performance asks for it.
This commit is contained in:
1 parent
b76f13f7ac
commit
7c51e6e904
8 files changed
+41
-10
No files matched your search
@@ -155,6 +155,7 @@ class FrontEndActivity : ComponentActivity() {
|
||||
private var gpuClockPin by mutableStateOf(false)
|
||||
private var prootNoSeccomp by mutableStateOf(false)
|
||||
private var prootFastPath by mutableStateOf(true)
|
||||
private var cursorComposite by mutableStateOf(false)
|
||||
private var guestHostname by mutableStateOf(SessionPrefs.DEFAULT_GUEST_HOSTNAME)
|
||||
private var phantomWarning by mutableStateOf<String?>(null)
|
||||
private var phantomProcessStatus by mutableStateOf(PhantomProcessStatus.NOT_APPLICABLE)
|
||||
@@ -1771,7 +1772,8 @@ class FrontEndActivity : ComponentActivity() {
|
||||
fsyncFirst = fsyncFirst,
|
||||
gamescopeRealtime = gamescopeRealtime,
|
||||
gpuClockPin = gpuClockPin,
|
||||
prootNoSeccomp = prootNoSeccomp, prootFastPath = prootFastPath, guestHostname = guestHostname, phantomWarning = phantomWarning,
|
||||
prootNoSeccomp = prootNoSeccomp, prootFastPath = prootFastPath, cursorComposite = cursorComposite,
|
||||
guestHostname = guestHostname, phantomWarning = phantomWarning,
|
||||
onClientOverride = { on -> SessionPrefs.setClientCpusOverride(this, on); clientOverride = on },
|
||||
onTuSysmem = { on -> SessionPrefs.setTuSysmem(this, on); tuSysmem = on },
|
||||
onZinkLazy = { on -> SessionPrefs.setZinkLazy(this, on); zinkLazy = on },
|
||||
@@ -1785,6 +1787,7 @@ class FrontEndActivity : ComponentActivity() {
|
||||
onGpuClockPin = { on -> SessionPrefs.setGpuClockPin(this, on); gpuClockPin = on },
|
||||
onProotNoSeccomp = { on -> SessionPrefs.setProotNoSeccomp(this, on); prootNoSeccomp = on },
|
||||
onProotFastPath = { on -> SessionPrefs.setProotFastPath(this, on); prootFastPath = on },
|
||||
onCursorComposite = { on -> SessionPrefs.setCursorComposite(this, on); cursorComposite = on },
|
||||
onGuestHostname = { name -> SessionPrefs.setGuestHostname(this, name) },
|
||||
onClientCore = { core, on ->
|
||||
clientCores = if (on) clientCores + core else clientCores - core
|
||||
@@ -1967,6 +1970,7 @@ class FrontEndActivity : ComponentActivity() {
|
||||
gpuClockPin = SessionPrefs.gpuClockPin(this)
|
||||
prootNoSeccomp = SessionPrefs.prootNoSeccomp(this)
|
||||
prootFastPath = SessionPrefs.prootFastPath(this)
|
||||
cursorComposite = SessionPrefs.cursorComposite(this)
|
||||
guestHostname = SessionPrefs.guestHostname(this)
|
||||
refreshPhantomStatus()
|
||||
}
|
||||
|
||||
@@ -472,6 +472,13 @@ object SessionPrefs {
|
||||
prefs(context).edit().putBoolean("prootFastPath", on).apply()
|
||||
}
|
||||
|
||||
/** gamescope draws the cursor itself. Off by default: on a phone that plane costs frames. */
|
||||
fun cursorComposite(context: Context): Boolean = prefs(context).getBoolean("cursorComposite", false)
|
||||
|
||||
fun setCursorComposite(context: Context, on: Boolean) {
|
||||
prefs(context).edit().putBoolean("cursorComposite", on).apply()
|
||||
}
|
||||
|
||||
const val DEFAULT_GUEST_HOSTNAME = "DroidDeck"
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -720,6 +720,7 @@ class SessionService : Service() {
|
||||
guest.add("BL_SYNC_FALLBACK=" + (if (SessionPrefs.syncFallback(this)) "1" else "0"))
|
||||
guest.add("BL_FSYNC_FIRST=" + (if (SessionPrefs.fsyncFirst(this)) "1" else "0"))
|
||||
guest.add("BL_GAMESCOPE_REALTIME=" + (if (SessionPrefs.gamescopeRealtime(this)) "1" else "0"))
|
||||
if (SessionPrefs.cursorComposite(this)) guest.add("BL_CURSOR_COMPOSITE=1")
|
||||
if (com.droiddeck.launcher.core.ZramSupport.supported()) guest.add("BL_ZRAM=1")
|
||||
guest.add("BANNER_AUDIO_DIRECT_DECAY=0")
|
||||
val extra = extraEnv() + com.droiddeck.launcher.agent.AgentEnv.beginSession(this)
|
||||
|
||||
@@ -20,7 +20,7 @@ object SettingsReset {
|
||||
"gpuDriverMode", "androidDriver", "linuxDriver", "linuxDriver.steam", "linuxDriver.desktop",
|
||||
"tuSysmem", "glThread", "noGlError", "zinkLazy", "mangoapp", "gpuClockPin", "gamescopeRealtime",
|
||||
"directAudio", "mic", "wifiDiscovery", "clientCpusOverride", "clientCpus", "gameCpus",
|
||||
"noXalia", "fastSync", "fsyncFirst", "syncFallback", "prootNoSeccomp", "prootFastPath",
|
||||
"noXalia", "fastSync", "fsyncFirst", "syncFallback", "prootNoSeccomp", "prootFastPath", "cursorComposite",
|
||||
"guestHostname", "fexPreset", "forceSsbs", "logs", "storageDiagnostics",
|
||||
"upscaler", "upscaleSharpness", "screenEffects", "textureAnisotropy", "textureLodBias",
|
||||
"steamDownloadsInBackground", "steam_offline", "bootMovie", "bootMovieSound", "bootMovieVolume", "bootMovieSeconds",
|
||||
|
||||
@@ -46,6 +46,7 @@ fun PerformancePage(
|
||||
gpuClockPin: Boolean,
|
||||
prootNoSeccomp: Boolean,
|
||||
prootFastPath: Boolean,
|
||||
cursorComposite: Boolean,
|
||||
guestHostname: String,
|
||||
phantomWarning: String?,
|
||||
onClientOverride: (Boolean) -> Unit,
|
||||
@@ -61,6 +62,7 @@ fun PerformancePage(
|
||||
onGpuClockPin: (Boolean) -> Unit,
|
||||
onProotNoSeccomp: (Boolean) -> Unit,
|
||||
onProotFastPath: (Boolean) -> Unit,
|
||||
onCursorComposite: (Boolean) -> Unit,
|
||||
onGuestHostname: (String) -> Unit,
|
||||
onClientCore: (Int, Boolean) -> Unit,
|
||||
onGameCore: (Int, Boolean) -> Unit,
|
||||
@@ -158,6 +160,11 @@ fun PerformancePage(
|
||||
else stringResource(R.string.perf_fastpath_hint),
|
||||
prootFastPath && !prootNoSeccomp, enabled = !prootNoSeccomp, onChange = onProotFastPath,
|
||||
)
|
||||
ToggleRow(
|
||||
host, "cursorcomposite", stringResource(R.string.perf_cursor_composite),
|
||||
stringResource(R.string.perf_cursor_composite_hint),
|
||||
cursorComposite, onChange = onCursorComposite,
|
||||
)
|
||||
}
|
||||
SettingsGroup(stringResource(R.string.perf_identity)) {
|
||||
var draft by remember(guestHostname) { mutableStateOf(guestHostname) }
|
||||
|
||||
@@ -568,6 +568,8 @@
|
||||
<string name="perf_fastpath">proot fast path</string>
|
||||
<string name="perf_fastpath_needs_seccomp">Needs proot\'s seccomp filter.</string>
|
||||
<string name="perf_fastpath_hint">Faster file lookups and less stutter. Turn off if a program can\'t find its files.</string>
|
||||
<string name="perf_cursor_composite">Draw the cursor inside gamescope</string>
|
||||
<string name="perf_cursor_composite_hint">Gamescope paints the pointer itself instead of handing it to Android. Turn on for a controller-driven cursor. Off is faster on a phone. Applies next session.</string>
|
||||
<string name="perf_identity">Session identity</string>
|
||||
<string name="perf_hostname">Host name</string>
|
||||
<string name="perf_hostname_hint">The name Steam sees for this device. Blank restores %1$s.</string>
|
||||
|
||||
@@ -227,7 +227,9 @@ if [ -z "${BL_INSIDE:-}" ]; then
|
||||
echo "== gamescope: games at ${nested}x${height} stretched to the ${width}x${height} output"
|
||||
fi
|
||||
fi
|
||||
if [ "$mode" = steam ]; then
|
||||
# Off unless Performance asks for it. Compositing the cursor here adds a second
|
||||
# plane on the phone's compositor; a controller-driven cursor is the reason to turn it on.
|
||||
if [ "$mode" = steam ] && [ "${BL_CURSOR_COMPOSITE:-0}" = 1 ]; then
|
||||
export gamescope_cursor_composite=2
|
||||
fi
|
||||
args=(--backend wayland --expose-wayland -f -W "$width" -H "$height" -w "$nested" -h "$height")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""The XTest cursor path is enabled only for Steam sessions."""
|
||||
"""Gamescope composites the cursor only when a Steam session asks for it."""
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
@@ -8,29 +8,37 @@ import unittest
|
||||
SESSION = Path(__file__).resolve().parents[1] / 'linuxfs/overlay/usr/local/bin/droiddeck-session'
|
||||
SOURCE = SESSION.read_text()
|
||||
MATCH = re.search(
|
||||
r'^ if \[ "\$mode" = steam \]; then\n.*?^ fi\n', SOURCE, re.M | re.S)
|
||||
r'^ if \[ "\$mode" = steam \] && \[ "\$\{BL_CURSOR_COMPOSITE:-0\}" = 1 \]; then\n.*?^ fi\n',
|
||||
SOURCE, re.M | re.S)
|
||||
assert MATCH is not None
|
||||
CURSOR_SETUP = MATCH.group(0)
|
||||
|
||||
|
||||
class SessionCursorRoutingTest(unittest.TestCase):
|
||||
def run_setup(self, mode, initial=None):
|
||||
def run_setup(self, mode, initial=None, composite=None):
|
||||
env = dict(os.environ, mode=mode)
|
||||
if initial is not None:
|
||||
env['gamescope_cursor_composite'] = initial
|
||||
else:
|
||||
env.pop('gamescope_cursor_composite', None)
|
||||
if composite is not None:
|
||||
env['BL_CURSOR_COMPOSITE'] = composite
|
||||
else:
|
||||
env.pop('BL_CURSOR_COMPOSITE', None)
|
||||
result = subprocess.run(
|
||||
['bash', '-c', CURSOR_SETUP + 'printf "%s\n" "${gamescope_cursor_composite-}"'],
|
||||
env=env, text=True, capture_output=True, check=True)
|
||||
return result.stdout.strip()
|
||||
|
||||
def test_steam_enables_manual_composition_for_the_nested_cursor(self):
|
||||
self.assertEqual('2', self.run_setup('steam'))
|
||||
def test_steam_leaves_the_cursor_with_the_host_unless_asked(self):
|
||||
self.assertEqual('', self.run_setup('steam'))
|
||||
|
||||
def test_steam_composites_the_cursor_when_the_setting_is_on(self):
|
||||
self.assertEqual('2', self.run_setup('steam', composite='1'))
|
||||
|
||||
def test_other_sessions_keep_their_existing_cursor_composition(self):
|
||||
self.assertEqual('', self.run_setup('desktop'))
|
||||
self.assertEqual('1', self.run_setup('run', '1'))
|
||||
self.assertEqual('', self.run_setup('desktop', composite='1'))
|
||||
self.assertEqual('1', self.run_setup('run', '1', composite='1'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in new issue
Block a user