Skip to content

LCD Blackout Investigation

jerrymares edited this page Jul 22, 2026 · 1 revision

Physical LCD blackout with live rendering

Status: persistent mitigation deployed and physically confirmed across a reboot, launcher-to-title transition, and nearly five hours of continuous rendering. Suspend/resume and dock/undock remain recommended regression exercises.

Symptom

On a Jupiter LCD Steam Deck, the internal panel intermittently became visually black during a foreground Vulkan workload. Audio continued and the backlight remained visibly on. The same behavior had occurred outside that workload, so an application-only explanation was insufficient.

The incident was an LCD-output failure, not an application crash:

  • the foreground process continued at roughly 38–40 FPS and continued receiving input;
  • Steam Game Recording contained a fully visible, advancing scene during the physical blackout;
  • Gamescope remained active and no Vulkan device-loss or guest-exit event appeared;
  • the kernel logged no correlated amdgpu reset, ring timeout, OOM kill, or thermal critical event.

Panel and DRM evidence during the failure

Check Observed state
Internal connector eDP-1 connected and enabled
EDID readable, 128 bytes
Backlight requested and actual brightness nonzero; bl_power=0
CRTC active at native 800x1280 panel timing, 60 Hz
Foreground surface 1280×800
External DP disconnected
Hardware scanout full-screen base plane plus full-screen alpha overlay plane
DRM ownership Gamescope owned the physical card; expected render clients only

This combination is recorded by DeckDoc as:

BLACKOUT_SIGNATURE: LIVE_RENDER_TO_PHYSICAL_SCANOUT_GAP

The recording proves the composed content existed upstream of physical scanout. The live eDP, backlight, and CRTC state proves the kernel still believed the panel pipeline was active. The failure boundary is therefore after frame production/capture and at or below the display-plane commit, kernel DCN/eDP scanout, panel timing/TCON, or physical panel-link layer.

That boundary is strong evidence, not proof that the panel hardware is healthy. A cable, panel/TCON, or kernel display-engine fault can all leave software state apparently valid.

Safe mitigation and result

The live session ran:

gamescopectl composite_force 1

Gamescope describes this convar as forcing composition and never using direct scanout. After the change, the overlay plane detached and DRM showed one active full-screen framebuffer plane. Gamescope, the foreground process, audio, and its control socket remained alive.

The same policy is persisted for future Game Mode sessions in:

~/.config/gamescope/scripts/99-deckdoc-display-stability.lua

with an initial assignment plus a documented Gamescope frame hook:

gamescope.convars.composite_force.value = true
gamescope.hook("OnPostPaint", function()
    if not gamescope.convars.composite_force.value then
        gamescope.convars.composite_force.value = true
    end
end)

This changes plane selection only. It does not change brightness, panel power, refresh rate, display resolution, TDP, clocks, charging, firmware, or GPU power state.

Launcher-to-game lifecycle finding

Live validation found one lifecycle gap in the first version of the policy. The Ryudeck library was single-plane after gamescopectl composite_force 1, but activating the title's Vulkan surface restored three full-screen scanout planes. Running the same convar command again immediately reduced DRM state to one plane while the title kept rendering at about 60 FPS. This rules out an ineffective convar and shows that a per-application transition can overwrite a one-time startup assignment.

The persistent policy therefore checks the convar from Gamescope's documented OnPostPaint hook and reasserts it only after another component clears it. The hook makes no panel, power, timing, or clock write.

The first persistence attempt also exposed a path-specific failure: SteamOS 3.8.14 logged that its user script root is ~/.config/gamescope/scripts/; a file directly under ~/.config/gamescope/ was silently skipped. DeckDoc now installs into the logged script root and tests that exact destination.

Reboot and title-transition verification (2026-07-21)

The corrected policy survived an orderly reboot and passed the lifecycle test that failed the first version:

  • Gamescope logged that it loaded /home/deck/.config/gamescope/scripts/99-deckdoc-display-stability.lua as script id 12, with no Lua error.
  • Gamescope later logged DeckDoc restored composite_force after an application transition., proving that the hook observed and repaired the transition-time convar reset.
  • The Steam library, Ryudeck library, and foreground Vulkan title each retained one active DRM plane: plane-3, crtc-0, and plane_mask=8 at the native 800x1280 panel timing.
  • Root KMS capture produced a native 1280x800 advancing title frame at approximately 53--60 FPS after the transition. The foreground process and MangoApp remained alive, and the boot had no coredump.

This verifies script discovery, hook execution, native resolution, and scanout-plane containment.

Physical and long-duration confirmation

The user subsequently confirmed that the built-in LCD was visibly showing the running title. At the same time, the title log had advanced for 4 hours 54 minutes and reported 60.0--60.5 FPS. Gamescope reported the internal screen visible and unpaused with presents fully draining; exactly one Ryudeck process and one MangoApp process remained, and the current boot still had zero coredumps. This closes the software-versus-emitted-pixels gap for the repaired session.

Post-mitigation diagnostic integrity

The first healthy-state DeckDoc report revealed several reporting errors that could obscure this result. They were corrected and covered by fixtures before the final snapshot:

  • 18 retained pre-fix MangoApp coredumps are now explicitly historical; the current boot reports zero MangoApp dumps, zero SIGABRT, zero SIGSEGV, and an active MangoApp service.
  • Steam's normal /tmp/dumps/settings.dat and bookkeeping directories are no longer counted as crash dumps. The current boot has zero actual minidump/core files.
  • Root reports route Gamescope, PipeWire, and Steam-path reads through the active Game Mode user rather than /root; the final report sees a responsive internal Gamescope backend, real audio sinks, and the actual Steam compatibility tree.
  • Thermal severity follows each sensor's exported hwmon threshold. A sensor without a published critical point can be recorded as above 90 C, but DeckDoc no longer calls 90 C a hardware trip.
  • Journal matching strips the steamdeck hostname before looking for Steam process failures, avoiding false matches against unrelated messages containing a later word such as tx_abort.

The corrected running-title sample held at about 83 C CPU, 75--76 C GPU, and 6,200 RPM for 30 seconds after brief 90--94 C load spikes. There was no thermal trip, GPU reset, process exit, or plane-policy loss. This temperature history is worth tracking, but it did not correlate with the original blackout, which occurred at lower measured temperatures.

Suspend/resume and thermal context

The affected boot contained three deep suspend cycles and all three completed (PM: suspend exit). The blackout occurred about 45 minutes after the last resume, not at the resume boundary. Repeated Failed to add display topology, DTM TA is not initialized messages appeared at boot/resume and are retained as external-display-topology evidence, but they do not prove the internal-LCD cause.

At the incident, measured temperatures were below critical shutdown territory (APU sensor about 82°C, GPU about 72°C, battery about 33°C, NVMe about 45°C). Earlier high-temperature warnings on the same boot describe workload stress history, not a correlated thermal trip.

Docked-resolution finding

The incident itself occurred at the correct 1280×800 Game Mode and XWayland resolution. Historical Steam configuration backups did contain a global 1920×1080 game resolution, while the current global setting is Default. That old global override can explain occasional small UI/icons or a retained 1080p virtual desktop after dock transitions, but it does not explain this blackout: the live CRTC, framebuffer, Gamescope command line, and application windows were all 800p.

DeckDoc should report this distinction and must not silently edit Steam's VDF files while Steam is running.

Ruled-out leading causes

  • Foreground application crash: rendering, recording, audio, and input continued.
  • Decky Loader/plugin injection: installed plugins did not own DRM, inject the foreground process, or log a correlated failure.
  • Rogue second renderer: DRM client ownership was expected.
  • GPU reset/hang: no correlated reset, ring timeout, device loss, or fence failure occurred.
  • Current global 1080p override: current Steam and display state were 1280×800.
  • Backlight-off event: actual brightness was nonzero and bl_power=0.

Decky-specific audit

Decky was not assumed absent: the system plugin_loader.service was active and its backend processes were inspected. The installed set was CSS Loader, SteamGridDB, Decky-Framegen, and Free Loader. Decky-Framegen was the only member with a plausible graphics association, but its backend contains no background Gamescope/display action: it only prepares or removes per-game Windows compatibility files after an explicit frontend request. Its current-boot log contained only Framegen plugin loaded.

The running native foreground process had no /home/deck/homebrew mapping and no Decky/framegen Vulkan layer or preload environment. Its only LD_PRELOAD entries were Steam's normal 32-bit and 64-bit game overlay renderers. CSS Loader's activity was confined to Steam browser CSS injection. None of the Decky processes owned the DRM card or emitted a current-boot crash correlated with the blackout.

This rules Decky out for the captured incident without globally disabling it. A future blackout should still record the current plugin inventory and logs because a later plugin update or a per-game mod could change that result.

Recommended regression exercises

  • Exercise multiple sleep/resume cycles and dock/undock transitions with forced composition active.
  • Track recurrence duration. If blackouts continue in a verified single-plane session, preserve the DRM state and escalate the kernel/panel-link/TCON branch rather than changing power controls.
  • Compare behavior after future SteamOS/gamescope updates; remove the policy only after a controlled recurrence test.

Primary references

Clone this wiki locally