* feat: the PowerVR runtime is a downloaded add-on pack, not bundled in the APK
* fix: a stopped session cancels the PowerVR pack download
* fix: a session stopped during runtime unpacking ends before staging
* fix: a failed PowerVR pack download ends the session with a message
* Retain compositor resources when GPU completion is unconfirmed
* Stop quarantined GPU callers before retries and mapped writes
* Support Android hardware-buffer presentation over Wayland
* Support PowerVR swapchains and linear image imports in Gamescope
* Bundle verified PowerVR graphics components through existing build preparation
* Detect and select the system Vulkan backend on PowerVR
* Apply PowerVR Steam and game compatibility during normal launches
* Show PowerVR support through existing driver and component controls
* Update existing hardware guidance for system Vulkan support
* Import the shared system Vulkan readiness check
* Discover and propagate the actual PowerVR render node
* Prune obsolete PowerVR runtimes after guest processes exit
* Retain external DMA-BUF ownership after GPU quarantine
* Name the PowerVR HAL selection explicitly
* Isolate component UI tests from application startup
* Cover the inherited FEX preset in PowerVR profile tests
* Log test worker failures for CI diagnosis
* Remove temporary test logging after diagnostic CI
* Prefer system dependencies for the Android Vulkan loader
* Capture raw stderr before test worker termination
* Remove the temporary test worker crash probe
* Import pinned DXVK recipe prerequisite from PowerVR PR570
Copy only the standalone build recipe, source pin, BC-format prerequisite
and presentation-sync patch/check from wallentx/DroidDeck at d0f7264ea8.
Source: https://github.com/Droid-Deck/DroidDeck/pull/570
Preserve that proposal attribution; no Android app, compositor, managed
pack, private data or fork development history is imported.
* Add opt-in low32 GPU mapping adapter and integrity probes
* Add opt-in D3D9 single-sample workaround and fix HUD texel format
* Document verified production game workaround and publication scope
* Restrict reset diagnostics and create private output atomically
* Target official runtime review and document PR570 prerequisite provenance
* Fix runtime tool output isolation, mmap64 chaining and DST ambiguity
* Normalize swapchain backbuffers for the opt-in D3D9 single-sample path
* Experimental Samsung Xclipse support on the system Vulkan path
Detect Samsung's Vulkan HAL (vulkan.samsung.so) and its sgpu render node
alongside PowerVR, and run Xclipse through the same libhybris bridge:
- VK_LAYER_DROIDDECK_xclipse (tools/linuxfs/xclipse-layer), built with the
glibc preloads and enabled only on Xclipse: sets bionic's environ for the
driver's shader compiler, avoids immutable YCbCr samplers in compute
layouts, forwards the KHR calibrated-timestamp entry points to the EXT
ones, and reports textureCompressionBC and BC4/BC5 filtering over the
compat layer's BC emulation.
- Upstream DXVK 2.6.2, pinned as a tar.gz component and selected on Xclipse:
the driver has 128 bytes of push constants, DXVK 3 needs 256.
- android_wlegl accepts a zero stride and passes it through unchanged:
Samsung's gralloc records none for GPU-only buffers.
Tested on a Galaxy A56 (Xclipse 540, driver 24.0.560): Steam Big Picture
and PICO PARK (D3D9).
* Xclipse layer: copy the device chain and track samplers per device
- Clear textureCompressionBC in a copy of the device-create chain (every
structure up to the VkPhysicalDeviceFeatures2 that enables it) instead of
writing the caller's structure; a chain led by a structure of unknown size
is passed on unchanged.
- Track YCbCr samplers per device in a growable list, drop them on
vkDestroySampler and device teardown, and fail sampler creation rather
than leave one untracked when the list cannot grow.
- Fail descriptor set layout creation with VK_ERROR_OUT_OF_HOST_MEMORY when
a replacement sampler array cannot be allocated, instead of passing the
original YCbCr samplers to the driver.
* Xclipse layer: copy any device-chain structure the headers define
The chain copy that clears the emulated textureCompressionBC only knew a
handful of structure sizes, so a valid chain such as
VkPhysicalDeviceTimelineSemaphoreFeatures -> VkPhysicalDeviceFeatures2 was
passed on unchanged and the compat layer refused the bit. Size every
structure that may extend VkDeviceCreateInfo from a table generated from the
Vulkan registry (gen_device_chain.py, Vulkan-Headers 1.3.275, the headers
the build compiles with), and copy onto the heap instead of a fixed buffer.
Only a structure newer than those headers still passes the chain unchanged.
Add a regression test that runs the layer between a simulated loader and a
mock driver: the timeline-semaphore chain, pEnabledFeatures, an unknown
structure, the caller's structures left untouched, per-device YCbCr sampler
tracking with handle reuse, and the KHR calibrated-timestamp forwarding. CI
installs libvulkan-dev for it.
* Mali bridge (#517, by ASEbrahim) on the non-Adreno test branch
Squash of Droid-Deck/DroidDeck#517 (ASEbrahim/DroidDeck mali-bridge @ 6b823341): the Vulkan
bridge (tools/vkbridge) that runs the guest's Vulkan on the phone's own driver, with BC1-BC7,
clip/cull distance, vertex-divisor and depth-clip emulation and dma-heap memory sharing for Mali.
All of the bridge is ASEbrahim's work; squashed only to carry it on this test branch.
Combined with #570 on this branch, a device draws through exactly one path:
- Adreno: Turnip, unchanged (checked first; the bridge setting is ignored there).
- PowerVR / Xclipse with the system HAL and a render node: the system-Vulkan path (#570).
- Anything else with the Setup toggle on (Mali): the bridge.
* Test branch: keep #570's DXVK build recipe so its pinned PowerVR components verify
#602 adds output checks to tools/dxvk/build.sh; tools/powervr/fetch.py pins the exact
recipe the published PowerVR DXVK was built from, so the branch carries #570's copy.
* Test branch: make #570, #602 and #560/#561 pass each other's tests
- tools/dxvk/build.sh: #602's copy (its output checks) and the PowerVR pin in
tools/powervr/release.json moved to that file's hash; the recipe's outputs are unchanged.
- droiddeck-session: the presentation block sets _bl_cef for #570's PowerVR path, and the UI
block keeps main's order, defaulting to -cef-use-angle=vulkan when the block has not run.
- Compositor test harnesses: AHardwareBuffer stubs for #570's AHB import, and a stub for
vkp_effects_forget_image (main #597) that #561's caller harness predates.
* Auto drivers for Mali and Xclipse on the non-Adreno test branch
Auto now picks an open driver pair for the GPU, the way it does for Adreno:
- Mali (no KGSL, /dev/mali0): the GPU's name ("Mali-G720-Immortalis MC12", from the vendor
Vulkan driver or kbase's gpuinfo) picks the PanVK build: G52-G78 (Job Manager), G610/G710,
G615 or G720. A Mali none of them covers (G925...), or one whose pair is not published yet,
draws through the Mali bridge, switched on by Auto.
- Xclipse keeps the system-driver path as Auto; the RADV pair is offered as a manual choice.
- The pairs come from The412Banner/droiddeck-nonadreno-drivers (one pre-release per driver,
each a DriverBundle zip). Only a device without an Adreno reads that repo.
- The importers accept PanVK and RADV libraries (libvulkan_panfrost / libvulkan_radeon).
- An open driver pair and the Mali bridge are alternatives: a selected pair turns the bridge off.
- TU_DEBUG is only set for Turnip, on an Adreno.
Every new branch is reached only when the device has no Adreno; an Adreno's detection, release
sources, Auto choice and session environment are unchanged.
* Auto: the one-binary PanVK kbase build for Mali v9-v13 on Android 15+
The412Banner/droiddeck-nonadreno-drivers adds panvk-mali-kbase: one PanVK build for
G57/G68/G77/G78, G610/G710, G615/G715, G720/G725 and G925, whose display half needs Android 15.
On Android 15+ Auto prefers it for every Mali it covers; below 15, and whenever its release is
not listed, Auto falls back to the GPU generation's own pair. G52/G76 keep the Job Manager
build; a G715/G725/G925 below Android 15, or any Mali no pair covers, draws through the bridge.
Every pair stays selectable by hand.
* Test: the G925 is in the kbase build's family now
* Offer faux123's device PanVK builds (RP4 Pro, Ace, RG556) as manual pairs for their Mali
* Detailed graphics logs for non-Adreno test reports
- graphics-report.txt in every session folder: the graphics path the session draws with and why
(Turnip, system Vulkan #570, Mali bridge #517, or an open driver pair with its release), the
driver mode and choices, what Auto would pick, the GPU (family, Vulkan device name, kbase
gpuinfo, Android, SoC, kernel), the GPU nodes the app can see (access, device numbers, SELinux
label; nothing is opened) and the guest's graphics environment. At the end it adds the
compositor's driver lines from app.log and the game launches that were logged.
- vulkan-summary.txt: the session's own vulkaninfo --summary with the driver as exported, in the
background with a 10 s timeout.
- Per-game logs under games/<time>-<appid>/: Proton's log, DXVK's and vkd3d-proton's, Mesa's and
PanVK's startup messages and the launch environment, from droiddeck-game-env. Each file is cut
to 20 MB and the folder to 120 MB at the session's end.
- The per-game logs and the Vulkan summary are on for a GPU that is not an Adreno, and on an
Adreno only with Setup's new "Detailed graphics logs" switch. Share logs already takes the
whole session folder, so all of it is in the zip, scrubbed as before.
* Mali pairs: a stand-in render node, the driver's real library name, and a Mali known by its chip
- Auto on Jim's Dimensity 9300+ chose the bridge: the GPU had no name (the app had not asked
Vulkan yet and kbase's gpuinfo is unreadable under SELinux), so a Mali-G720 counted as a Mali
no build covers. The name now falls back to the GPU the chip is known to carry (Dimensity,
Helio, Kompanio, Tensor); and when nothing names it, Auto asks the vendor Vulkan driver off the
main thread before it settles for the bridge. Auto logs what it decided and why.
- An open Mali driver pair gets /dev/mali0 as the guest's render node, as the bridge does
(bindGpuNode, BL_DRM_STANDIN): gamescope needs the node the driver reports. The session shim
only answers libdrm's PRIME and GEM-close calls on it, which PanVK on kbase never makes.
- A PanVK or RADV runtime half is installed as libvulkan_panfrost.so / libvulkan_radeon.so rather
than under Turnip's name; Turnip keeps libvulkan_freedreno.so.
- graphics-report.txt names the render node the guest got, adds the session script's driver lines
and flags a failed Mali-bridge self-test at the top.
* Auto takes the RADV pair on a Samsung Xclipse, with the system route as its fallback
A tester's Galaxy S24 FE (Xclipse 940) boots to Steam with the RADV-Xclipse pair, where the
system-driver route fails at Steam's OpenGL (glamor and GLX cannot load a driver). Auto now
downloads and selects RADV on an Xclipse like the Mali pairs, and falls back to the system route
only when RADV is not published. #570's reset of both drivers at each start no longer undoes an
open driver pair. PowerVR (vulkan.powervr.so) keeps the system driver as before.
* An Exynos with a Mali is a Mali, not an Xclipse
The system route took vulkan.samsung.so as Samsung's Xclipse, but an Exynos 1280/1380 (Galaxy Tab
S9 FE: Mali-G68) may name its HAL the same; with /dev/mali0 present that HAL is not the system
route's, and the device is detected as the Mali it is. The chip table adds the Exynos 1380 and
1280 (s5e8835, s5e8825: Mali-G68).
* 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.
* Client sound retries a briefly disconnected AAudio; kbase ioctl refusals explained in the report
A Galaxy S24 FE's session had no sound at all: the DirectAudio sink's AAudio stream opened with
AAUDIO_ERROR_DISCONNECTED while the output route was still changing at session start, and the
plain AAudio fallback failed the same moment. The sink guard now retries DirectAudio, then the
plain sink, five times over ten seconds and says which one it got. graphics-report.txt keeps the
client-sink and kbase lines, and explains a KBASE_IOCTL_MEM_EXEC_INIT EPERM as the kbase driver's
own answer rather than the session's sandbox.
* Mali pairs draw the display on the phone's own Mali driver; Xwayland falls back without glamor
- Testers' Mali pairs got the guest drawing (gamescope on the stand-in node, Zink on PanVK) but
the compositor's PanVK Android half failed on Mali gralloc: it probes AHB formats 0x38/0x3b that
mali_gralloc does not have, and "vkCreateImage w/ native buffer failed". Under Auto a Mali pair
now leaves the display on the phone's own Vulkan driver (dma-buf, modifiers and AHB all pass the
testers' checks) and runs the pair's PanVK in the guest; the Android half stays installed for a
manual pick. "Pair in use" now follows the runtime half.
- A session after one whose Xwayland crashed (segfault, then gamescope's X11 I/O error) starts
Xwayland with XWAYLAND_NO_GLAMOR=1 on a non-Adreno device, and says so in app.log.
- graphics-report.txt names the display driver the compositor used, and keeps gralloc, dma-buf,
modifier and import lines from app.log and Xwayland's own lines from the session log.
* Non-Adreno sound: the daemon falls back on its own; the build's commit in device.txt and the report
The S24 FE's session still had no sound: its AAudio refuses DirectAudio's low-latency stream with
AAUDIO_ERROR_DISCONNECTED, and the sink guard never got to retry because pactl did not reach the
daemon in time ("the daemon did not answer in 15 s"). On a GPU that is not an Adreno the daemon's
own start-up script now asks DirectAudio again without low latency and loads the plain AAudio sink
underneath it, so a default sink exists whatever pactl does. device.txt and graphics-report.txt
name the build label and source commit, so a log says which build it came from.
* Non-Adreno sound: no second DirectAudio load (it hung the daemon); the plain AAudio sink underneath
On the S24 FE the daemon stopped after DirectAudio's failed low-latency load: the second
DirectAudio load in the same daemon never returned, so nothing after it ran and pactl never
connected. The daemon now loads only the plain AAudio sink (no low latency) after DirectAudio,
inside .nofail, and sets whichever exists as the default.
* gamescope: explicit sync off where the kernel or the stand-in node cannot signal its timelines
Adds tools/gamescope/patches/0126 (GAMESCOPE_DISABLE_EXPLICIT_SYNC=1 for the nested backends) and
sets it on a GPU that is not an Adreno when the kernel is older than 6.6 (no
DRM_IOCTL_SYNCOBJ_EVENTFD) or the guest's render node is Mali's stand-in. The graphics report
lists it with the rest of the guest's graphics environment.
* Test branch: gamescope with the explicit-sync switch (0126), pinned by sha
Built by build-gamescope.yml run 38335744351 from 0136fb61 and published as a component release
of The412Banner/droiddeck-nonadreno-drivers; the apk build fetches it by tag and checks the sha.
* Sound: nothing that can block in the daemon's start-up; Steam's web compositing in software on open pairs
- The S24 FE (US) daemon hung loading the plain AAudio sink from default.pa (its AAudio open
blocks rather than fails), so it never finished starting. default.pa is back to DirectAudio
alone inside .nofail; the fallbacks are loaded from the app once the daemon answers, each pactl
bounded by its timeout (DirectAudio, then the plain sink with and without low latency). The
guard waits 30 s and logs, with timestamps, how long the daemon took, whether its socket and
pactl exist, and what it finally got.
- With an open driver pair on a GPU that is not an Adreno, Steam's CEF composites in software
(-cef-disable-gpu-compositing) with GPU raster kept: RADV on Xclipse showed stale, half-written
tiles, as #570 saw on PowerVR. The session log says so.
* Mali under Auto: the display always on Android's own Vulkan loader; a reboot hint for refused audio
Axel's Tab S9 FE still drew its display with the PanVK Android half, set by an earlier build, and
stalled at "Waiting for Steam's first frame" on Mali gralloc's format probes. Under Auto a Mali's
display now goes to Android's own loader whatever was set before (DriverMenus resets it, and the
compositor's driver choice ignores a pair's Android half), with no HAL path to find first. A pair
counts as in use when its runtime half is. A manual pick of the PanVK display is kept.
When audio.log shows AAUDIO_ERROR_DISCONNECTED, the report and the client-sink line say Android
refused the output and that rebooting the phone usually fixes it.
* Fix: call SessionPrefs.gpuDriverMode through its instance from Java
* Compositor: log each new dma-buf format/modifier/size it imports (for colour and swizzle reports)
Steam's software web compositing already covers every open driver pair, Mali included.
* Open driver pairs: vkd3d-proton reports the driver's caps; buffer attach/release tracing; Mesa log
- With a PanVK or RADV pair (BL_OPEN_DRIVER=1), droiddeck-game-env drops the app-wide
VKD3D_FEATURE_LEVEL=12_2 and VKD3D_SHADER_MODEL=6_9 so vkd3d-proton reports what the driver has
(an Unreal DX12 game crashed at start on PanVK with the overrides); a game's own setting still
wins, and launch.txt records DROIDDECK_VKD3D_CAPS=driver.
- The compositor traces, on a GPU that is not an Adreno, the first 400 dma-buf attaches and buffer
releases by wl_buffer id and sending line, and logs any release of a buffer already released
and not attached again (gamescope's "Compositor released us but we were not acquired" on G925).
- Per-game logs no longer set MESA_DEBUG=silent, which kept mesa.log empty.
* Tests: the dma-buf quarantine harness follows send_buffer_release's tracing macro
* Mali (Venus): David Cimo's Venus route sources and recipes
From DavidCimo/droiddeck-mali, branch mali-venus @ 4f838891 (prototype 13; his 12 commits on top
of DroidDeck 0.3.1, GPL-3.0), by David Cimo:
- tools/venus: Mesa Venus vtest patch (incl. the per-queue submit_mutex fix and the cached-memory
frame readback), virglrenderer Android patch, the Mali compatibility layer (the six features
DXVK needs: fill modes, multi-viewport, robustness2, clip/cull distance, BC1-BC7) and his tools.
- tools/linuxfs/preload/venus.c: keeps Zink's kopper under Venus.
- tools/gamescope/patches/0127 (his 0114): shm buffers uploaded on every commit.
- docs/development/mali-venus.md: his design notes.
- tools/venus/ci-build.sh and build-venus.yml: his build recipes as one CI job that packs the
component (vtest server, ICD, layer) as venus.tzst for the apk.
Co-authored-by: Dersim Abbas <derabb0620@gmail.com>
* Mali (Venus) as a selectable route, by David Cimo
Ports David Cimo's Venus route (DavidCimo/droiddeck-mali, mali-venus @ 4f838891) onto this branch
as "Mali (Venus)", one tap in Setup next to the Mali bridge:
- VenusComponent (his): stages the Venus ICD and runs virglrenderer's vtest server over the
phone's own Vulkan driver; the guest gets VK_ICD_FILENAMES, VN_DEBUG=vtest, VTEST_SOCKET_NAME and
MESA_VK_WSI_DEBUG=sw.
- Selection rule: Venus when Setup's "Mali (Venus)" is on, on a GPU that is neither an Adreno nor
a system-driver one (PowerVR, Xclipse), and the apk carries it. It then replaces the Mali bridge
and any open driver pair for the session, and the display stays on the phone's own driver.
Auto is unchanged (the PanVK pair). Adreno never takes any of it.
- The compositor enables only the dma-buf extensions the driver has, logs a vendor driver's
extension list, and gives a zero row pitch a packed row (his vk_present.c changes).
- The Mali compatibility layer is staged into the runtime on non-Adreno devices only.
- The component (vtest server, ICD, layer) comes from build-venus.yml as venus.tzst, published on
The412Banner/droiddeck-nonadreno-drivers and pinned by sha in tools/venus/release.env.
- gamescope 3.16.29-p15 adds his shm upload patch (0127) next to 0126; pinned by sha.
- device.txt and graphics-report.txt name the route.
Co-authored-by: Dersim Abbas <derabb0620@gmail.com>
* Mali: Venus gamescope without robustness2, the bridge switch honoured and kept, clean driver switches
- gamescope 0128: VK_EXT_robustness2 is optional. A Mali driver through Venus has none, and
gamescope stopped at "Missing required extension: VK_EXT_robustness2" (the wayland_surface error
after it was only the knock-on). Without it, unused descriptor slots point at a 1x1 texture
instead of VK_NULL_HANDLE. (David Cimo's Pixel 9 driver has robustness2, so his build never
needed this.) gamescope component rebuilt and pinned by sha.
- Open-files limit: on a GPU that is not an Adreno the session script raises the soft limit to the
hard limit for the whole session tree (a PanVK-kbase session froze on "Too many open files"
after ten minutes) and graphics-report.txt shows before and after. A stopgap; the driver leak is
fixed separately.
- The Mali bridge switch is honoured: when on and usable it wins over a PanVK pair for the
session (Venus still wins over it). Selecting a pair no longer switches the bridge off, which is
why the switch did not survive an app restart (Auto re-selected the pair at start). Setup says
when this phone cannot use the bridge at all.
- Driver switching: picking a Mali pair by hand keeps the display on the phone's own driver, as
Auto does (a PanVK Android display stalls on Mali gralloc at "Waiting for Steam's first frame",
and stayed set after switching back); installing a bundle again replaces it instead of adding a
"-2" copy beside the old one.
- graphics-report.txt names the runtime driver's folder and libraries, and the previous session's
drivers, flagged when they changed.
* gamescope p16 (0128 robustness2 optional), pinned by sha; graphics-report says who chose the display driver
* Bundle replace only for open non-Adreno pairs; Adreno bundles keep their numbered copies
* Rebuilt open drivers reach phones: re-downloaded when their digest changes, release list hourly on non-Adreno
The non-Adreno driver releases replace their assets in place (the PanVK kbase sync-file fd leak
fix). A download is now remembered with its GitHub sha256, and an asset whose digest changed
counts as not installed, so Auto fetches it again and the bundle replaces the old one; the release
list is re-read after an hour instead of a day on a GPU that is not an Adreno.
* Mali compatibility layer: multiDrawIndirect, depthClipEnable and robustness2 for DXVK on Venus
A Galaxy A15 (Mali-G57) on Venus got gamescope and Steam up, but DXVK refused the GPU:
"Device does not support required feature 'multiDrawIndirect'". DXVK 3.1 stops at the first
missing feature, so the rest of its required list (dxvk_device_info.cpp) was checked against what
the testers' Mali drivers cannot have, and covered in the same pass, on top of David Cimo's six:
- multiDrawIndirect: reported, taken off the device, and an indirect draw with drawCount > 1 is
recorded as single draws at offset + i * stride; maxDrawIndirectCount reported as 2^30.
(drawIndirectCount is optional for DXVK and stays as the driver says.)
- VK_EXT_depth_clip_enable (required): offered when the driver lacks it; depthClipEnable off in a
pipeline becomes depthClampEnable, and the extension's structures never reach the driver.
- VK_EXT_robustness2 missing entirely (gamescope saw the same on these phones): offered with
robustBufferAccess2 (as robustBufferAccess, as before) and nullDescriptor, emulated by small
stand-ins (a zeroed buffer, a 1x1 image) for VK_NULL_HANDLE buffers, image views and vertex
buffers in plain, template and push descriptor writes and vertex-buffer binds. A null
texel-buffer view stays null (its format is not known).
The layer logs every feature it emulates per device.
* Venus component 22694a38 (layer: multiDrawIndirect, depthClipEnable, robustness2), pinned by sha
* Non-Adreno round 3: bridge images, Venus GL, shared buffers, Steam GPU drawing
- vkbridge: the memory model skips lazily allocated types. Mali-G615 lists
DEVICE_LOCAL|LAZILY_ALLOCATED first; taken as the device-local type it left
images with no memory type (self-test "image clear/draw: setup" FAIL,
gamescope "No compatible image memory type").
- Session: a bridge self-test that fails images or draws falls back to the
runtime's driver pair for that session (BL_VKBRIDGE_FALLBACK_ICD); Setup
and the graphics report say so.
- Venus: the Mali compatibility layer runs in every process but gamescope
(DROIDDECK_MALI_COMPAT=1), so Zink in Steam and Xwayland gets
nullDescriptor; null texel-buffer views get stand-ins too. Without
nullDescriptor the session's GL goes to llvmpipe.
- gamescope 0129: a refused compute pipeline is named with its SPIR-V
capabilities.
- Compositor: a buffer on two surfaces at once (gamescope's planes while a
notification is up) is released only when the last one lets go.
- Open driver pairs: processes.txt timeline for the first three minutes;
Setup "Steam interface: GPU drawing" turns off software web compositing.
* Pin gamescope p17 (0129) and Venus 55b30fbf
* Non-Adreno round 4: Mali GPU-drawing block, gamescope YCbCr retry, GL probe, bridge draw sync
- Setup's "Steam interface: GPU drawing" is hidden on Mali and a saved "on" is
cleared: with PanVK it rebooted an Edge 60 (G615) as steamwebhelper started.
Kept for Xclipse.
- gamescope 0130: a composite pipeline refused at start-up is retried with a
layout without immutable YCbCr samplers (G615 through Venus refused every
composite shader; their SPIR-V has no Float16, so fp16 was not the cause).
- Venus: droiddeck-glprobe opens GL through GLX the way the Steam client does,
with the loader's reasons logged; when it fails the client's GL goes to
llvmpipe.
- vkbridge self-test: the draw check waits for the render pass's stores before
copying out (a tiler read zeros without the dependency).
* Pin gamescope p18 (0130)
* Non-Adreno round 5: gamescope memory fallback, Venus destroy guard, OpenAL depot
- gamescope 0131: DEVICE_LOCAL|HOST_VISIBLE requests fall back to host-visible
memory (the bridge's unified-memory model lists none with both), with the
request, type bits and memory types logged on failure; 0130's probe pipeline
is kept and skipped when forced.
- Venus: GAMESCOPE_NO_YCBCR_SAMPLERS=1 from the start; virglrenderer ignores
the destroy of a pipeline it never created instead of marking the context
fatal (vtest server exit 137 on a Mali-G615).
- Steam's OpenAL depot (229020) maps to oalinst_dll, so games that list it
(Hotline Miami) get OpenAL in their prefix.
* Pin gamescope p19 (0131) and Venus 6199a93f
* Non-Adreno round 6: PowerVR PRIME on old kernels, thermal, hang-up names, bridge flippable images, Venus Zink variants
- drm.c: PR #570's current PRIME ownership check (F_DUPFD_QUERY, then kcmp,
then the F_SETOWN_EX owner marker): on a kernel before 6.10 with kcmp
blocked, drmPrimeFDToHandle answered EOPNOTSUPP for every PowerVR import
(Pixel 10, Android 17: Zink "failed drmPrimeFDToHandle", Xwayland error 7,
gamescope X11 I/O error). The Mali stand-in node is kept.
- A /sys/class/thermal the kernel will not list gets an empty directory, so
mangoapp no longer aborts on it.
- gamescope 0132: a hung-up waitable is named before the abort; 0133: the
bridge's flippable images use supported-but-unexportable modifiers instead
of asserting.
- Venus: when Zink does not start, the loader's view is logged and Zink is
retried without ZINK_DEBUG=compact, with ZINK_DESCRIPTORS=auto and without
kopper before falling back to llvmpipe.
* Pin gamescope p20 (0132, 0133)
* Non-Adreno round 7: bridge command-buffer guard, Venus Zink trace, PowerVR mangoapp, Xclipse label
- vkbridge server: every command buffer a device hands out is tracked; Begin,
End (stream replay) and QueueSubmit refuse one it never allocated or has
freed (VK_ERROR_DEVICE_LOST, logged) instead of passing it to the driver,
where Mali's vkBeginCommandBuffer crashed the app (SIGSEGV 0x10, Steam's
Zink on an Edge 60 and a Tab S11).
- vkbridge server: a fault inside the driver while serving a request cuts
that client off (SIGSEGV/SIGBUS guard per request) and leaves its objects
alone; the app and the other clients carry on. Other faults go to the
previous handler.
- vkbridge server: the pipeline cache directory is copied; the JNI string it
pointed at was freed (garbage in the cache path).
- Venus: DROIDDECK_MALI_COMPAT_TRACE=1 makes the Mali compatibility layer log
what an application queries before vkCreateDevice; a failed glprobe adds a
traced run and vulkaninfo --summary under the same environment.
- PowerVR: mangoapp draws with llvmpipe (Zink could not make it a swapchain
and it crashed at every start).
- Setup: an Xclipse GPU reads "Experimental: RADV or the system Xclipse
driver", not the PowerVR line.
* Pin Venus e40cd361 (layer trace)
* Non-Adreno round 8: bridge sharing fallback and crash detail, Venus diagnostics and 1.2 gate, compositor disconnect reasons, RADV upstream
- Mali bridge: the self-test fails "memory sharing" when the server offers
no host-visible memory type (no sharing method passed, RP4 Pro G77); the
session then falls back to the PanVK pair like a failed draw, and Setup
says the bridge cannot share memory with that driver. Without a pair to
fall back on, the log says so.
- Mali bridge: a guarded driver crash now logs the sub-command it was in,
the fault address and pc (library + offset via dladdr), the command
buffer's level, begin flags, pool flags and state, and the last 32
replayed commands. Begin on an executable buffer from a pool without
RESET_COMMAND_BUFFER_BIT is logged once (implicit reset).
- Venus: vulkan-summary.txt gets the device extension list and key
features (full vulkaninfo in vulkan-full.txt); a failed GL probe runs
once with VN_DEBUG=init,result, ZINK_DEBUG=mem, MESA_LOG_LEVEL=debug and
the layer trace into glprobe-trace.txt. The Mali compatibility layer's
trace covers every pre-device query (devices, memory, queue families,
formats, image formats, external handles) and names the extensions.
- Venus: off when the phone's driver reports Vulkan below 1.2 (gamescope
skips such a device); Setup and the graphics report say why and the
session uses the PanVK pair.
- Compositor: libwayland's own disconnect reasons go to wayland.log, and a
client's buffer may grow to 1 MB before a slow reader is dropped. A
session that ended without teardown records Android's exit reasons.
- Drivers: RADV-Xclipse upstream (radv-xclipse-upstream) is a manual
choice for Xclipse; Auto keeps radv-xclipse.
* Tests: the terminal-callers harness stubs the Quest layer and Cardboard modules and Android's system properties
* Pin gamescope p21 (main's patches + 0120-0133) and Venus a4d47cf3 (layer trace)
* Display driver Auto: Quest's patched Turnip first; the system driver only for a Mali, other GPUs keep the generic fallback
* Open driver pairs: the installed build's version, its upload date, and an Update when the release is rebuilt in place
- The release check records each asset's GitHub id and updated_at; a
download records them (with the digest) for an open non-Adreno pair.
- Components > GPU drivers: an installed open pair shows its manifest
version ("android <tag> + linux <commit>"), one not yet installed shows
"built YYYY-MM-DD". A different digest, asset id or upload time on the
same tag marks the installed pair "Update available" with an Update
action: the pair is downloaded again and replaced in place, and stays
selected only if it was. Adreno and DD-Turnip pairs are unchanged.
- graphics-report.txt: the pair release line gives the installed and the
listed upload dates and flags a newer build; an exact bundle id match is
preferred (RADV-Xclipse-upstream is not RADV-Xclipse).
* Session preload: drop oom_score_adj raises so lmkd does not treat games as cached apps
steam-launch-wrapper starts every game with --oom-score-adjust 900; on
Android 900 is CACHED_APP_MIN_ADJ, so lmkd kills the running game first
when memory runs short (and on Linux 6.1 the raise becomes the process's
permanent minimum). A process in the app cannot go below the score it
inherits, so the writes that succeed from inside are raises: every
write-open of /proc/<pid|self|thread-self>[/task/<tid>]/oom_score_adj (or
oom_adj), through open/openat or fopen, goes to /dev/null, logged once.
Based on the oom_score_adj redirect in the preload's opens.c by jdmg28 (https://github.com/jdmg28/DroidDeck-Mali/commit/6be00e00)
* Display: why presenting failed on the session-ended screen, and the display driver that really loaded
- The compositor records why it cannot present (no Vulkan driver loaded,
vkCreateInstance/vkCreateDevice failed, no GPU or graphics queue, no
swapchain on the screen with the driver's reason, device lost, GPU work
unconfirmed). Each is a DD_PRESENT_FAULT line in wayland.log, read back
over JNI or from wayland.log; the session-ended screen shows it instead
of a black screen, and graphics-report.txt gets "!! DISPLAY FAILED". A
first frame or a working swapchain clears it.
- After the display device is created, the driver that answered is logged
from VkPhysicalDeviceDriverProperties (device, driverName, driverInfo,
driver id, Vulkan version) and reported in graphics-report.txt. When a
driver pair's display half was requested but a vendor driver answered
(adrenotools falls back to the system driver when the requested one does
not load), it says so.
Based on DD_PRESENT_FAULT in vk_present.c / waylandcomp_jni.c / SessionActivity by jdmg28 (https://github.com/jdmg28/DroidDeck-Mali/blob/arena/cd8ab18a-droiddeck-mali/app/src/main/cpp/waylandcomp/src/vk_present.c)
Based on the adrenotools silent-fallback finding by ryanistr (https://github.com/ryanistr/DroidDeck-Mali/blob/main/docs/development/panvk-mali-g77-bringup.md)
* tests: steam presentation test sets 0.5.0's steam_client
* Non-Adreno: find every driver pair, Venus before the bridge, fix the bridge's begin info
From the logs testers sent since c9ebb247:
- The app read the drivers repo's newest 15 releases only; the component releases (gamescope,
Venus) pushed every PanVK pair and RADV-Xclipse past them, so Auto found no pair on any Mali
and switched the Mali bridge on. The non-Adreno repo is now read in one page of 100.
- Auto's stand-in for a missing pair: Mali (Venus) where the apk carries it (Steam runs on it
from the G57 to the G1-Ultra), the bridge otherwise, nothing on a driver below Vulkan 1.2. It
no longer clears the Linux driver, does nothing when the list could not be read, records that
it chose the route, and turns it off again once a pair is installed. A bridge that earlier
builds left on under Auto is taken as Auto's.
- Mali bridge: vkBeginCommandBuffer sent its begin info without the count the server decodes, so
Mali got a zeroed begin info with stale flags and crashed at 0x10 (Pixel 8 Pro G715, Lenovo
G615, Xiaomi G925, Tab S11).
- Mali-G1 series (MT6993, arch v14) known by its chip; its label says Venus, not the bridge.
- A session Android killed for memory is said so on the next start (the S24 FE "crashes" were
low-memory kills, not driver faults).
- The in-app updater never installs an official (Adreno-only) build over this test build.
* Venus: destroy the device's object mutex after the objects that lock it
Bionic aborts on locking a destroyed mutex ("pthread_mutex_lock called on a destroyed mutex",
Tab S9 FE G68, Pixel 9a), so a client that exited holding objects took the render worker down.
From BattleTempest's DroidDeck-Pixel (kevinbryant551-ux/DroidDeck-Pixel, GPL-3.0).
* release check: a session helper may be extracted to another runtime path
droiddeck-steam-taskset (#570) goes to usr/local/libexec/droiddeck-steam/taskset, where PATH puts
it in front of Steam's own taskset for the client only; 0.5.0's check wanted every droiddeck-*
helper at its own path.
* Venus component 93038b7d (destroyed-mutex fix)
* Update MaliBridge to v0.5.1 (#1135)
* Mali Auto: never leave a session on the runtime's Turnip
Logs from a Retroid Pocket 4 Pro (G77), Galaxy S21 Ultra (G78), Tab S11 Ultra
(G925) and Xiaomi G610 showed Auto ending on the runtime's Turnip, where
gamescope finds no GPU ("failed to find physical device"): after a pair's
trial rolled back, when the pair is on the bad list, and when the driver
list could not be read. In each case Auto now switches on its stand-in
(Venus, or the bridge) when no open driver, Venus or bridge is set.
Under Auto the Mali display also leaves any imported driver, not only a
pair's PanVK half (a lone PanVK_G720 import gave a black screen).
* Mali bridge: MaliBridge 224b6e36 (v0.5.3 source, by ASEbrahim)
From c65062b6 (v0.5.1). v0.5.2/v0.5.3: Steam mode on older Mali drivers
(G77/G710/G610/G57) gets past "starting display and audio", OpenGL 4.6 on
most Malis through dynamic-rendering and vertex-format emulation, Dimensity
9500 texture fixes, async pipeline compile, RE2 flicker on G925, DirectX on
the Pixel 8 family. JNI entry and session env names are unchanged.
* gamescope 0134: linear when the backend offers no modifier; Venus on Mesa 26.2.5
0134: CVulkanTexture::BInit asserted !modifiers.empty() when the nested Wayland
backend offered no modifier for a flippable image's format (NieR Replicant on a
Pixel 9a under Venus, session exit 134). It now tries linear and logs it.
Venus ICD: mesa-26.2.5 (venus TLS teardown from an unloaded driver, virtio-gpu
devices without 3D skipped); virglrenderer stays on 1.3.0.
* gamescope p22-nonadreno (0134 + main's 0116 cursor fix; build run 40159674290)
* CI: build the non-Adreno additions before the preload check
* build.gradle: drop verifyHandModel (main moved the hand models into the tracking pack)
* Venus component venus-proto13-e24ed8ab (Mesa 26.2.5; build run 40161447324)
* CI: fetch the Mali (Venus) component again (lost when build.yml took main's jobs)
Build a7a1ebf1 (run 40161734101) had no assets/venus or libvirgl_test_server.so, so
VenusComponent.available() was false and Auto's stand-in would have been the bridge.
* Auto: the Mali bridge stands in on a Vulkan 1.1 Mali driver
Auto refused both Venus and the bridge when the phone's driver reports Vulkan
below 1.2, so on the G77, G78 and G610 (r32p1/r38, Vulkan 1.1) a rolled-back or
missing pair left the runtime's Turnip: "failed to find physical device"
(Retroid Pocket 4 Pro after the JM pair's trial, Xiaomi 13T). Only Venus needs
1.2; the bridge raises the driver for gamescope and runs on these phones. A
Venus switch that cannot start on such a driver no longer counts as a route.
* Tests: stub main's g_release_unpaced in the DMA-BUF quarantine probe
The probe copies release_buffer out of compositor.c; since the merge it reads
g_release_unpaced, which the harness did not declare (setUpClass failed to compile).
* Update MaliBridge to v0.5.4 (ASEbrahim)
48477fe6 (tag v0.5.4): Dimensity 9500 green squares and red-tinted textures,
Balatro and other OpenGL text, fewer crashes when memory runs low, one screen
update per game frame, picture kept after a long background pause (SIGHUP no
longer stops the server), wrong colours after changing graphics settings on
the G720, more in the session report. The app-side changes of his DroidDeck
Mali app (Steam menus setting, per-game setup, Send logs, updates) are not
part of the MaliBridge repository and are not in this build.
* gamescope 0135: linear when the driver rejects every offered modifier
An r32p1 Mali-G610 (Vulkan 1.1) behind the Mali bridge answered both of the
backend's modifiers for AR24 with VK_ERROR_FORMAT_NOT_SUPPORTED, so the first
flippable image failed and gamescope asserted in vulkan_create_flat_texture
(Xiaomi 13T). Linear, when offered, is tried anyway; the bridge makes such
images without the handle type and exports them through a dma-heap. If the
image cannot be made, BInit fails as before.
* gamescope: pin the non-Adreno p23 build (0135)
* Tests: the terminal-callers harness stubs take_shm's game-frame detection
Main's take_shm now reads surface damage, parent/role/mapped and the HUD state
to spot game frames; the harness declares them so the copied function compiles
(setUpClass failed in Build APK run 40505286127). No damage, so it stays off.
* gamescope: number the test branch's patches 0920-0935
Main now has its own 0121-0125 (window override walk, host-event wake, commit fences, done at
import, HUD frame times), which sorted in between this branch's 0120-0135. The branch's sixteen
patches move to 0920-0935 with the same last two digits, so they apply after main's set and stay
clear of its next numbers. Applying all 38 to gamescope 3.16.29 in the old order and the new one
gives the same tree (checked with patch -p1, as build-in-arch.sh does). PATCHES.md and the one
code comment that named 0130 follow the new numbers.
* check_session_assets: helpers count in usr/local/bin or the Steam taskset folder only
The merge kept this branch's pattern (any usr/ target), which main's new test rejects: a helper
extracted into a subfolder of usr/local/bin must not count. The pattern now takes usr/local/bin
under any name, as on main, plus usr/local/libexec/droiddeck-steam for droiddeck-steam-taskset.
Every helper in the overlay is still found extracted in SessionFiles.kt.
* gamescope: pin 3.16.29 p24 (non-Adreno)
Built from this branch @d13b9d88 (run 41119284267): main a5b035b2's patches plus this branch's,
now 0920-0935. All 38 applied, gamescope's tests 2/2. sha256 1d1088d4.
* Update MaliBridge to v0.5.4.2 (ASEbrahim)
95a1e600 (tag v0.5.4.2), was v0.5.4 (48477fe6). For the bridge: memory sharing without the handle
type where that is all the self-test passed (unflagged buffers, client/memory.c, server_memory.c),
the older-Mali (G52-G77) game-mode start fixes, the r38p1 beta geometry-shader erratum (gs_hide),
present timeouts and an API cap per process. Client, server and the in-app library all build from
the submodule with MaliBridge's own scripts, which did not change; the protocol only gained
fields an older server sends as 0.
* Session end: the compositor fault query no longer fails the hint when the native library is absent
presentationFault() (6778a224) called WaylandCompositor.compositorFault() directly. Main's new
SessionEndHintTest runs sessionEndHint() in Robolectric, where libdroiddeckwayland cannot load, so
all six cases ended in UnsatisfiedLinkError (Build APK run 41125749537). The call is now wrapped
like runtimeDamageHint()'s, and without an answer the hint reads wayland.log as before.
* test: stub the GPU busy reader in the caller harness
* fix: release build is not debuggable, Mali uses the system display driver, staging failure ends its own session
* fix: address non-Adreno review findings
* fix: preserve current gamescope and GPU warning behavior
* fix: retain graphics failure hints and launch diagnostics
* fix: identify non-Adreno GPUs in driver failure hints
* test: harnesses follow the external client barrier and effects upscaling changes
* fix: client sources return to foreign ownership after the overlay draws
---------
Co-authored-by: Leask Wong <i@leaskh.com>
Co-authored-by: wallentx <william.allentx@gmail.com>
Co-authored-by: Stefan Zijlstra <6730062+stefanz92@users.noreply.github.com>
Co-authored-by: William Allen <wallentx@users.noreply.github.com>
Co-authored-by: The412Banner <the412banner@users.noreply.github.com>
Co-authored-by: Dersim Abbas <derabb0620@gmail.com>
Co-authored-by: root <root@localhost.localdomain>
Co-authored-by: ASEbrahim <ahmadsmain@gmail.com>
Co-authored-by: The412Banner <the412banner@gmail.com>
Co-authored-by: The412Banner <205237651+The412Banner@users.noreply.github.com>
* Desktop: programs a Windows installer adds get a menu entry and desktop icon
Opening a Windows installer on the desktop runs it with Proton in a prefix
of its own (droiddeck-proton-run's "own" prefix). Proton's menu builder
turns the installer's Start Menu links into .desktop files, but keeps them
in the prefix's drive_c/proton_shortcuts with a Windows .lnk path as Exec,
and nothing outside the prefix pointed at the installed program: Nexon
Launcher installed fine on an AYANEO Pocket FIT Elite and could only be
found by browsing the hidden compatdata folder.
droiddeck-desktop-programs reads proton_shortcuts in every prefix that is
neither a Steam game's nor a current Steam shortcut's, resolves each link to
its program inside the prefix, and writes a menu entry that opens it with
droiddeck-open, so it runs in that same prefix, with the icon Proton
extracted. A program whose installer also put a link on the Windows desktop
gets a desktop icon once; one the user deletes is not put back. Entries go
away with their program; uninstallers get none. It runs when the desktop
starts and after droiddeck-open finishes a Windows program.
* Desktop programs: only programs that run in their prefix, Windows argument rules, one refresh at a time
A link resolved through Proton's Z: mapping could name a program outside
the scanned prefix, and droiddeck-open would then run it in another one.
A program is now listed only when droiddeck-proton-run's prefix_of puts it
in the prefix it was found in.
Shortcut arguments were split with shlex, so a Windows argument with an
apostrophe raised and stopped the whole refresh; they are now split by
the Windows command-line rules.
The desktop start and the end of a Windows program can refresh at the
same time and race on the same temporary files; refreshes now take turns
on a lock beside the placement record.
* Desktop programs: extract the script at session start
SessionFiles lists the overlay scripts the app copies into the runtime;
droiddeck-desktop-programs was missing, so a real build would never have
installed it and check_session_assets failed the build.
* Desktop programs: a compatdata folder it cannot read changes nothing
Any error listing steamapps/compatdata made the refresh see no prefixes,
so it removed every program entry and forgot which desktop icons it had
placed; the next good run then put back icons the user had deleted. Only a
missing compatdata now means there is nothing installed; any other read
error leaves the menu, the desktop and the placement record as they were.
* Desktop programs: an unreadable shortcut or desktop folder changes nothing
os.path.isdir and glob read an unreadable proton_shortcuts or Windows
desktop folder as empty, so the refresh dropped that prefix's entries and
placement records and a later run put back icons the user had deleted.
Those folders are now listed directly: a missing one is still empty, and
any other error leaves the menu, the desktop and the record as they were.
* Desktop programs: only a missing file reads as absent
read(), link_target() and host_path()'s letter-case lookup turned any
error into "absent", so an unreadable placement record read as empty and
brought back icons the user had deleted, and an unreadable shortcut or
link dropped its program's entry. A missing file, a wrong file type and a
malformed link still read as absent; any other error now reaches main(),
which leaves the menu, the desktop and the record as they were.
* Desktop programs: keep the placement record true when a run fails part way
The placement record was read after the menu was already rewritten, so an
unreadable record changed the menu although the run reported it had not.
It is now read first.
When writing desktop icons failed part way, the icons already written were
not recorded, and the next run recreated any of them the user had deleted.
The record is now written from the icons that exist after the attempt,
icons are written in a fixed order, and a failed write leaves no temporary
file on the desktop.
os.path.exists and isfile also read a program whose path cannot be reached
as missing; a stat that fails only because the file is absent now counts
as missing, and any other error leaves everything as it was.
* Desktop programs: leave the menu alone when Steam's shortcuts cannot be read
The list of Steam shortcuts comes from a reader that treats an unreadable
or damaged shortcuts.vdf as having no shortcuts, so a Steam shortcut's
prefix could get a menu entry and a desktop icon of its own. The file is
now checked first: a missing one still means no shortcuts, and any other
read or parse failure leaves the menu and the desktop as they were.
* Desktop programs: an unreadable Steam account or empty shortcuts file also stops the refresh
account_dir takes an unreadable loginusers.vdf or userdata folder as
missing, so the shortcuts check could be skipped and a Steam shortcut's
prefix still get its own entry. Both are now read first, and an access
error leaves the menu as it was.
An empty shortcuts.vdf is now parsed like any other, so it stops the
refresh too, the same way droiddeck-steam-shortcuts refuses to rewrite it.
---------
Co-authored-by: K11MCH1 <81425424+K11MCH1@users.noreply.github.com>
* perf: reclaim launcher memory under system pressure
* docs: record Caravan save-load OOM with spare swap
* fix: wait for completed reclaim before increasing backoff
* fix(preload): answer NETLINK_ROUTE queries inside a session
ip(8) could not run in a session: the app's SELinux domain has no
netlink_route_socket bind permission, so iproute2 failed at bind and never saw
the link that getifaddrs() and /proc/net already expose.
Serve NETLINK_ROUTE from the same etc/droiddeck-net snapshot: an AF_UNIX
socketpair backs the netlink fd, link/addr/route dumps and route get are
synthesised, writes return EPERM, and multicast subscriptions keep failing
with EACCES so consumers that wait for link events keep their fallback.
Replies carry the port id reported by getsockname() and recvmsg() rewrites
the source address to AF_NETLINK/pid 0. iproute2's dump loop requires both
before it accepts a message or NLMSG_DONE; when either is missing every
message is skipped silently and the process blocks in recvmsg().
* fix(preload): keep socket() and send() semantics for emulated netlink
* fix(preload): deliver netlink replies with the caller's blocking mode
* fix(preload): preserve NETLINK_ROUTE protocol and fd semantics
- Send ACKs for successful queries and honor NETLINK_CAP_ACK
- Reject unsupported subscriptions and apply socket timeouts
- Track socket identity and shared references across dup and close
- Support kernel connect and rewrite recvfrom source addresses
- Resolve local and connected routes before default gateways
- Add netlink and iproute2 regression tests
* fix(preload): handle netlink request limits and socket lifecycle
- Collect large sendmsg requests without falling back to UNIX sockets
- Reject oversized replies explicitly instead of returning partial results
- Allocate unique port IDs and reject duplicate bindings
- Honor socket flags and restore inherited sockets across exec
- Validate socket types and report netlink socket identity
- Replace the fixed socket table with a dynamic registry
- Add regression tests for batching, port conflicts and exec inheritance
* fix(preload): optimize netlink tracking and support link name queries
- Add lock-free fd tracking to bypass netlink locks on ordinary sockets
- Move descriptor restoration to initialization and explicit discovery paths
- Support RTM_GETLINK lookups via IFLA_IFNAME with correct error codes
- Add regression coverage for hot-path overhead and name-based queries
* fix(preload): accept unterminated netlink interface names
- Copy IFLA_IFNAME into a bounded, NUL-terminated buffer before lookup
- Match kernel string length validation and ERANGE errors
- Add regression coverage for unterminated names and boundary cases
* fix(preload): pin peers for netlink replies
* fix(preload): make autobind idempotent
* fix(preload): isolate forked netlink cleanup
* fix(preload): avoid interposed fd scans
* perf(preload): skip PID checks for untracked fds
* fix(preload): verify peer before replay
---------
Co-authored-by: uubooster-team <uu.booster@service.netease.com>
* fix(components): a native-only override falls back to builtin when the prefix has no native DLL
A component that asks for a DLL native-only (for example .NET 4.8's mscoree=n) left the DLL unloadable when its native copy never reached the prefix. On ARM64 prefixes the .NET installer leaves Wine's builtin mscoree in system32, so every program that needs .NET exited at launch with 'mscoree.dll not found'.
At launch, an override of n for a DLL whose system32 or syswow64 copy is missing or is Wine's own (a link into the Proton build, or a builtin or placeholder stub) becomes n,b, and the session log says so. A real native copy is still loaded first, and the saved component state is unchanged, so the override returns to n once the native DLL is there.
* Treat any prefix symlink as builtin when checking native overrides
* Treat an unreadable prefix DLL as missing for native overrides
Extend the VRAM setting to Vulkan memory-budget reports for DXVK and D3D12 while preserving real heap capacity and allocation results, removing the hard rejection that caused game crashes in FIT and Discord tests.
## Summary
- Keep raw diagnostic staging in private cache and give each exported
archive a unique request directory.
- Remove that request directory after the CLI pull, including failed
transfers.
- Replace files from the previous extracted snapshot while preserving
unrelated destination files.
- Document that the old rooted-device fallback is not scrubbed.
Follow-up to #2061. The refreshed export tests now cover independent
archive outputs and stale snapshot replacement.
## Validation
- `wsl python3 -m unittest tools.tests.test_droiddeckctl` — 49 passed.
- `:app:testDebugUnitTest -x buildVkBridgeServer --tests
com.droiddeck.launcher.session.SessionLogShareZipTest.anArchiveCanBeWrittenOutsideTheShareFolder`
— passed.
- `git diff --check` — passed.
A listed title whose automatic FEX mapping the player clears now records
the empty mapping as a native choice, as titles with NATIVE_CHOICE do,
instead of getting FEX again on the next run.
Steamworks has no arm64 launch-option architecture, so a title that ships
x64 and arm64 Linux builds side by side still reads as osarch 64 and gets
the Proton ARM64 default. List such titles in FEX_DEFAULT_APPS so they
default to Linux x86 (FEX), whose launch runs the bundled arm64 build. A
player's own pick is kept, and unlisted titles are unchanged.
Refs #1774
seed_install read the app's manifest from every library before checking
that it was the linked DroidDeck install, so a manifest in another library
that is not UTF-8 raised past the caller and stopped routing for later
games. It now returns before reading anything but the linked manifest.
An untouched manifest from an older version was migrated even while
steamapps/downloading/<appid> existed; that migration now waits until
Steam is not staging the app, like the rewrite of a queued import.
An added game the account owns is linked into Steam as DroidDeck-<appid>.
When the folder carries no Steam build, Steam marks it Update Required and
checks every file before updating. That check reads the whole game, and an
interrupted one starts over, so on an SD card it ran again in every session
and kept the card busy: Lords of the Fallen (33 GB) restarted 51 times in a
day on an AYANEO Pocket FIT Elite.
The manifest for such an import now asks Steam to update the game when it
is launched. Imports that Steam already rewrote, but whose update has not
started, switch from "always keep updated" to "update when launched"; a
priority of 2, an update in progress, or an import with a recorded build is
left alone.
Stream each archive entry to disk instead of reading it into memory,
refuse an archive from a session that started after the state call, and
delete the exported zip from shared storage once it has been pulled.
`logs latest` pulled the session folder under getFilesDir(), which adb
cannot read on an unrooted device, so it always failed with "Permission
denied" and droiddeck-scenario kept no logs for failed runs.
The agent bridge gets a `logs` method that writes the Share logs archive
to the app's external files folder (agent-logs/), and droiddeckctl pulls
that zip and unpacks it into the destination with the session's files at
the top, as before. Builds without the method still get the old pull.
Forward extraction and installation messages from the x64 bootstrap log and replace stale download percentages with the applying-update state. Add regression coverage for phase ordering and log forwarding.
Fixes#812
Provide compatible gateway metadata for IPv4 VPN links without changing
VPN routing, and keep text and JSON network snapshots consistent.
Add regression tests for gateway selection and network snapshots.
Zink's rebind_image() and zink_rebind_all_images() refreshed only a sampler
view's main image view after the resource got a new backing object. The
view's zs_view and cube_array surfaces stayed on the old object and were
freed with it, so the next descriptor update wrote a garbage VkImageView.
On PowerVR (needs_zs_shader_swizzle) every RGBX/BGRX view has a zs_view, and
Steam's web helper segfaulted in vkUpdateDescriptorSetWithTemplate within
seconds of fast Right presses on the Home shelf. The new Mesa patch rebuilds
all of the view's surfaces with init_sampler_view().
Avoid decoding every app when Start without Steam resolves one game launch. Use wanted-app selection in the single-game helpers while keeping the existing field decoder and full-reader default for bulk callers.
Track partial coverage separately from complete results, share one immutable byte snapshot for incremental queries, and keep timestamp invalidation and warm hits. Preserve the last valid duplicate record and release the raw snapshot after a full decode.
Add format/cache/structural-budget and launch-resolution regressions, reuse the existing binary fixture encoder, and document the host-only performance scope.
* fix: upscale game buffers before native-resolution composition
* fix: drop an added code comment from the effects source draw
* fix: effects source keeps pillarboxed games and near-full source rectangles
* fix: a larger opaque draw above keeps the full composition path
---------
Co-authored-by: maxjivi05 <maxjividen@gmail.com>
The Agent's install request pointed at http://cn.patch.battle.net:1119/<product>.
That host only 301-redirects to the country's version service today; Blizzard's
China client asks cn.patch.battlenet.com.cn:1119 directly.
The update check built <branch>.version.battle.net, so a China install (branch
cn) asked cn.version.battle.net, which does not answer; the China service is
cn.version.battlenet.com.cn.
Only region cn changes.
* fix(storage): Windows installs on a natively mounted card no longer ask for an administrator
Cards mounted directly as FAT, exFAT or NTFS were not treated as Android
storage, so wineserver reported an Anonymous owner and refused permission
changes. Its chmod on these volumes also no longer fails the request.
* fix(storage): keep NTFS owners and the chmod error
* fix(desktop): Steam's own header moves and resizes its windows
Steam never asks KWin to move or resize its windows, and its maximize
button can only maximize. Each normal Steam window now reports presses
on its header and edges, and KWin handles them natively. No extra title
bar is added and other apps are unchanged.
* fix(desktop): drag regions cover the elements inside them
* fix(desktop): find Steam's drag regions by position
The Friends window's drag region ignores pointer events, so a hit test
never finds it. The check now runs once a press moves, so plain clicks
cost nothing.
* fix(desktop): a game's window follows its own window mode
Desktop games ran in a titled gamescope window whatever mode they asked for. gamescope now fills the desktop for a fullscreen or borderless game and matches the window size of a windowed one.
* Use the p30 gamescope test build
* fix(desktop): a windowed game too big for the desktop is maximised
* fix(desktop): a decorated game window stays a window
* Use the published gamescope p21
* feat(gamescope): a three way switch for relative mouse motion
Games that confine the cursor and warp it back to read movement never
reach the nested hints rule, so their aim stays bounded by the screen.
The convar defaults to 0 and leaves that rule alone; 1 forces relative
motion for the focused game, 2 keeps the pointer absolute even when the
rule would apply.
(cherry picked from commit db3d7555e0)
* feat(input): the session carries a relative mouse mode per game
Reads the mode from the game's gesture config, hands it to gamescope as
gamescope_relative_mouse, and pushes a change to the running session
through gamescopectl.
(cherry picked from commit e350d88464)
* feat(drawer): the relative mouse switch is a three way choice
Auto leaves it to the game, on forces relative motion, off keeps the
pointer absolute. Named in all 32 locales so none of the three falls
back to English.
(cherry picked from commit e96a187e02)
* fix(input): follow the focused game's relative mouse mode
Switching to a game whose saved mode differs left the session on the
previous game's mode, since only the drawer state was refreshed. The
requests also ran on a thread per selection, so two quick picks could
reach gamescope out of order.
(cherry picked from commit 7ff8c5d568)
* fix(input): retry the relative mouse mode gamescope did not take
The drawer state moved before the request ran, so a failed request left
the two out of step and the next focus change skipped the resend.
(cherry picked from commit cf0f82d8cd)
* fix(input): the relative mouse mode tracks the latest choice
The guest agent answers ok when it handled the exec, so a failing
gamescopectl was recorded as applied. Reconcile the newest desired mode
on the worker thread after each request, and only mark applied when the
command really exited zero.
(cherry picked from commit 5f5e3bd52e)
* gamescope: a hidden cursor under any pointer constraint is relative
Games that hide the cursor and confine the pointer had no lock hint, so the
nested pointer stayed absolute and the camera froze.
* Treat a hardware mouse as a real mouse in sessions
A mouse now moves the guest pointer by relative motion for the whole session
through pointer capture, so it no longer stops at screen edges or reaches
system gestures. Its cursor stays visible in every touch mode, follows the
game showing or hiding it, and clicks no longer press on-screen controls.
* gamescope: use the mouse test release
* Direct touch turns the camera while a game holds the pointer
A swipe in direct touch now sends relative motion when a game has the pointer
locked, including when the lock starts during the swipe, as when a game
hides the cursor while a button is held.
* Address review findings on mouse and touch input
Keep touchpad taps on on-screen controls, cancel a pending long press during a
locked swipe, let the three-finger gesture cancel a locked swipe, refresh
capture when the output changes, and use the menu's key for the relative
mouse setting.
* Keep locked touches inside the game picture and free the mouse in touch editors
* End touch editor ownership when the editor goes away
* Bring the mouse cursor back when a touch editor closes
* Release a pointer lock at the game's pointer
* gamescope: use the pointer position test release
* Fit the X screen to a fullscreen window larger than it
* gamescope: use the X screen fit test release
* Return the X screen when no game window has focus
* gamescope: use the X screen return test release
* ci: avoid redundant gamescope builds
* fix: hardware mouse in Desktop and pointer warping games
KWin nested on the host only reads relative motion while its own pointer lock is on, so a program that locked the pointer in Desktop (Blender orbit and pan) stopped receiving motion. A captured hardware mouse now turns that lock on, and a real Right Ctrl no longer toggles it.
Gamescope follows a game's pointer warps instead of overriding them, and absolute motion also sends raw motion. Also retries relative mouse requests, tidies the unplug path, passes side buttons and fits a second oversized window correctly.
* chore: use the gamescope build with patch 0131
* fix: Desktop mouse lock keeps retrying after early attempts fail
* fix: hold the key that turns on the Desktop mouse lock
KWin ignores a press and release delivered together.
* fix: gamescope enters warp following sooner and keeps steady motion
* chore: use gamescope p26
* Capture system keys in a focused session and keep the first Desktop mouse motion in place
* Use the p27 gamescope build
* Update the system keys row test
* Recognise a captured mouse so the Desktop grab can start
* Keep touch warps out of relative motion
* Send Esc from keyboards that report it as Back
* Use the p28 gamescope build
* Release captured keys on pause, forward motion during a grab and wait for a pending screen fit
* Use the p29 gamescope build
* fix(input): keep held system keys consumed until they are released
Copy each captured key event, since the service owns the original only for the callback, and consume the physical release of a key already released to the guest.
Use the published gamescope p20.
* fix(input): capture a system key only from its first press
---------
Co-authored-by: kingokksa <kingokksa@qq.com>
Co-authored-by: maxjivi05 <6025299+maxjivi05@users.noreply.github.com>
fix(battlenet): keep games installed inside Battle.net's folder running
A game installed under C:\Program Files (x86)\Battle.net\ (for example
World of Warcraft: Forever in "Battle.net\World of Warcraft\_forever_")
was counted as part of Battle.net itself. Launched from DroidDeck, the
launch never saw a game, said "Battle.net closed before a game started",
stopped everything left in the prefix, game included, and exited 1.
Battle.net's own files are now only those directly in its folder, in its
Battle.net.<build> folders and under ProgramData\Battle.net.
Co-authored-by: Albert <alb.carreras@gmail.com>
* feat: desktop and scrolling wall live wallpapers selectable from Android settings
* fix: render the wall wallpaper off the main thread and give it its own thumbnail
* fix: serialize wall wallpaper visibility and wait out in-flight draws on surface destroy
* fix: restart the wall loop on surface recreation and keep queued visibility changes
* fix: keep the wall loop alive across a failed canvas lock and finish redraws before returning
* fix: post the wall redraw asynchronously on surface change
* fix: redraw the desktop wallpaper logo from the real mark and show game covers on the wall
* chore: mount the git dir in build containers and seed new worktrees from the main checkout
* fix: decode wall covers as RGB_565 and seed worktree assets only into empty dirs
* feat: drop the desktop wallpaper and add frame rate and speed settings to the wall
* feat: wall settings over the live wallpaper with a match-screen rate, and drop the center vignette
* perf: pace the wall on vsync and draw it on a hardware canvas
* fix: stage worktree seed copies and publish them only after they succeed
* fix: point the wall settings link at the activity class so the picker shows the gear
* fix: dedupe wall covers by app and space repeats like the in-app wall, keep the frame loop alive across surface gaps
* fix: show the picker preview behind wall settings and drop the display-rate lookup
* fix: stop wall frame callbacks when the surface goes and only replace an empty seed destination
* fix: skip a seed when the destination reappears before the staged copy is moved in
Nothing in droiddeckctl reported temperature, so a before/after
comparison could start one run hot and the next cold.
`thermal` reads the battery temperature from dumpsys battery, the
thermal status from dumpsys thermalservice, and each CPU policy's
scaling_max_freq against cpuinfo_max_freq (capped when lower), all
readable over plain adb. `wait cool --below <C>` polls it every 10 s
until the battery is under that temperature, or exits 5 at --timeout.