From ccf3eb4e042d97396552c9fd18478ebc5680996a Mon Sep 17 00:00:00 2001 From: The412Banner Date: Mon, 12 Oct 2026 20:28:51 -0400 Subject: [PATCH] Auto fetches the open drivers itself; Xclipse named as such; sound and frame-gen in the logs - Auto looks online again when its saved release list predates this device's open drivers, so a Samsung or Mali phone gets its pair without pressing refresh first. - A Samsung Xclipse is labelled "Samsung Xclipse" (not PowerVR), with its own support line. - Per-game logs add audio-streams.txt: PulseAudio's sink inputs 20 s and 60 s into the launch, so a silent game shows whether its stream reached Pulse. - graphics-report.txt states the frame-generation setting and keeps the LSFG gate, FrameGen and audio lines from app.log. --- app/src/main/java/com/droiddeck/launcher/DriverMenus.kt | 6 ++++-- .../main/java/com/droiddeck/launcher/core/DeviceReport.kt | 2 +- .../main/java/com/droiddeck/launcher/gpu/DeviceInfo.kt | 2 +- app/src/main/java/com/droiddeck/launcher/gpu/GpuInfo.kt | 6 +++++- .../java/com/droiddeck/launcher/session/GraphicsReport.kt | 5 ++++- tools/linuxfs/overlay/usr/local/bin/droiddeck-game-env | 8 ++++++++ 6 files changed, 23 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/droiddeck/launcher/DriverMenus.kt b/app/src/main/java/com/droiddeck/launcher/DriverMenus.kt index b36041421..2c270b7b6 100644 --- a/app/src/main/java/com/droiddeck/launcher/DriverMenus.kt +++ b/app/src/main/java/com/droiddeck/launcher/DriverMenus.kt @@ -61,7 +61,7 @@ internal class DriverMenus(private val activity: Activity, private val ui: Handl private var autoCheckedThisProcess = false fun state() = GpuDriversState( - gpuName = gpu.displayName(activity), gpuFamily = gpu.family.label(activity), soc = gpu.soc, supportText = gpu.supportText(activity), + gpuName = gpu.displayName(activity), gpuFamily = if (gpu.name.contains("Xclipse", ignoreCase = true)) gpu.family.label(gpu.name) else gpu.family.label(activity), soc = gpu.soc, supportText = gpu.supportText(activity), supported = gpu.support == GpuInfo.Support.TESTED, unsupported = gpu.support == GpuInfo.Support.UNSUPPORTED, auto = mode == SessionPrefs.GPU_DRIVERS_AUTO, pairs = pairRows, busy = pairBusy, percent = pairPercent, autoStatus = autoStatus, releaseStatus = releaseStatus.ifEmpty { activity.getString(R.string.drivers_not_checked) }, checking = releaseChecking, @@ -198,7 +198,9 @@ internal class DriverMenus(private val activity: Activity, private val ui: Handl Thread({ val cached = TurnipReleases.cached(activity) val stale = cached == null || System.currentTimeMillis() - cached.checkedAt > 24 * 3_600_000L || - cached.assets.none { it.pair.isNotEmpty() } + cached.assets.none { it.pair.isNotEmpty() } || + // A list checked before this device's open drivers were offered has none of them. + (!DeviceSupport.adreno() && cached.assets.none { DriverPairs.isNonAdreno(it.pair) }) val problem = if (force || stale) runCatching { TurnipReleases.refresh(activity) }.exceptionOrNull()?.message else null ui.post { releaseChecking = false diff --git a/app/src/main/java/com/droiddeck/launcher/core/DeviceReport.kt b/app/src/main/java/com/droiddeck/launcher/core/DeviceReport.kt index 6cd2295df..69dffcd4c 100644 --- a/app/src/main/java/com/droiddeck/launcher/core/DeviceReport.kt +++ b/app/src/main/java/com/droiddeck/launcher/core/DeviceReport.kt @@ -124,7 +124,7 @@ object DeviceReport { h("Drivers") val gpu = com.droiddeck.launcher.gpu.GpuInfo.detect() - k("GPU", "${gpu.name} · ${gpu.family.label} · ${gpu.supportText}" + if (gpu.oneUi8Gen2) " · One UI 8 Gen 2" else "") + k("GPU", "${gpu.name} · ${gpu.family.label(gpu.name)} · ${gpu.supportText}" + if (gpu.oneUi8Gen2) " · One UI 8 Gen 2" else "") k("Driver mode", SessionPrefs.gpuDriverMode(context) + (com.droiddeck.launcher.gpu.DriverPairs.recommendedKey(gpu, com.droiddeck.launcher.gpu.DriverPairs.from( com.droiddeck.launcher.gpu.TurnipReleases.cached(context)))?.let { " (recommended pair: $it)" } ?: "")) diff --git a/app/src/main/java/com/droiddeck/launcher/gpu/DeviceInfo.kt b/app/src/main/java/com/droiddeck/launcher/gpu/DeviceInfo.kt index 5cafa3932..d135bb466 100644 --- a/app/src/main/java/com/droiddeck/launcher/gpu/DeviceInfo.kt +++ b/app/src/main/java/com/droiddeck/launcher/gpu/DeviceInfo.kt @@ -61,7 +61,7 @@ object DeviceInfo { private fun gpu(gpu: GpuInfo) = Section("GPU", buildList> { add("GPU", gpu.name) - add("Family", gpu.family.label) + add("Family", gpu.family.label(gpu.name)) add("Model found from", when (gpu.modelSource) { "kernel" -> "the kernel's GPU name" "vulkan" -> "the Vulkan driver (the kernel's name has no model)" diff --git a/app/src/main/java/com/droiddeck/launcher/gpu/GpuInfo.kt b/app/src/main/java/com/droiddeck/launcher/gpu/GpuInfo.kt index a2a950b15..4b03b8823 100644 --- a/app/src/main/java/com/droiddeck/launcher/gpu/GpuInfo.kt +++ b/app/src/main/java/com/droiddeck/launcher/gpu/GpuInfo.kt @@ -49,6 +49,9 @@ data class GpuInfo( val mali: Boolean get() = name.startsWith("MALI_") + /** [label] for this GPU: the system-driver family is a Samsung Xclipse or a PowerVR. */ + fun label(gpuName: String): String = if (this == POWERVR && gpuName.contains("Xclipse", ignoreCase = true)) "Samsung Xclipse" else label + /** [label] in the app's language: the Adreno families are names, the rest is words. */ fun label(context: Context): String = if (this == NOT_ADRENO) context.getString(R.string.gpuinfo_not_adreno) else label } @@ -69,7 +72,8 @@ data class GpuInfo( get() = when (support) { Support.TESTED -> "Supported" Support.UNTESTED -> when (family) { - Family.POWERVR -> "System PowerVR driver: compatibility varies by device" + Family.POWERVR -> if (name.contains("Xclipse", ignoreCase = true)) "Experimental: RADV or the system Xclipse driver" + else "System PowerVR driver: compatibility varies by device" Family.MALI_OTHER -> "Experimental: Mali through the Vulkan bridge" Family.MALI_JM, Family.MALI_G610_G710, Family.MALI_G615, Family.MALI_G720, Family.MALI_LATEST -> "Experimental: open Mali driver (test builds)" Family.A7XX_LOW -> "Experimental: its drivers are test builds" diff --git a/app/src/main/java/com/droiddeck/launcher/session/GraphicsReport.kt b/app/src/main/java/com/droiddeck/launcher/session/GraphicsReport.kt index 2abdf3861..9cc92271a 100644 --- a/app/src/main/java/com/droiddeck/launcher/session/GraphicsReport.kt +++ b/app/src/main/java/com/droiddeck/launcher/session/GraphicsReport.kt @@ -65,6 +65,8 @@ object GraphicsReport { val pairs = DriverPairs.from(TurnipReleases.cached(context)) appendLine("auto would pick: " + (DriverPairs.recommendedKey(gpu, pairs) ?: "(no pair: system driver or bridge)")) } + appendLine("frame generation: " + runCatching { com.droiddeck.launcher.gpu.FrameGen.mode(context).toString() }.getOrDefault("?") + + " (engine=off means it is switched off in Play settings; a driver that fails LSFG's gates logs \"device gates\" below)") appendLine("mali bridge setting: " + SessionPrefs.vkBridge(context) + ", in use: " + DeviceSupport.vkBridge(context)) val standIn = runCatching { com.droiddeck.launcher.runtime.LinuxRuntime.gpuStandIn(context) }.getOrNull() appendLine("render node for the guest: " + (standIn?.let { node -> @@ -134,7 +136,8 @@ object GraphicsReport { /** The compositor's driver lines from the app's own log. */ private val COMPOSITOR = Regex( """vk_present|waylandcomp|vk_loader|compositor|vkCreateDevice|extension|adrenotools|TurnipDriver|""" + - """graphics driver|SystemVulkan|vkbridge|VkBridge|mali_gralloc|panvk|PanVK|radv|MESA|native buffer|first frame|present""", + """graphics driver|SystemVulkan|vkbridge|VkBridge|mali_gralloc|panvk|PanVK|radv|MESA|native buffer|first frame|present|""" + + """lsfg|FrameGen|device gates|AAudio|directaudio|pulse""", RegexOption.IGNORE_CASE, ) diff --git a/tools/linuxfs/overlay/usr/local/bin/droiddeck-game-env b/tools/linuxfs/overlay/usr/local/bin/droiddeck-game-env index 8068c67d8..9deeae337 100755 --- a/tools/linuxfs/overlay/usr/local/bin/droiddeck-game-env +++ b/tools/linuxfs/overlay/usr/local/bin/droiddeck-game-env @@ -392,6 +392,14 @@ def game_logs(command, env, app_id, now=None): if key.startswith(("VK_", "BL_VK", "BL_DRM", "MESA_", "PANVK", "DXVK_", "VKD3D", "ZINK", "TU_"))]) + "\n") except OSError: pass + # Whether the game's sound reaches PulseAudio: the streams 20 s and 60 s in, without waiting. + try: + subprocess.Popen(["sh", "-c", 'for t in 20 40; do sleep $t; { echo "== $(date +%T)"; ' + 'pactl list sink-inputs 2>&1 | head -80; } >> "$1/audio-streams.txt"; done', "audio", str(folder)], + stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + start_new_session=True) + except OSError: + pass return result