forked from unom/punktfunk
fix(flatpak): export GAMESCOPE_WAYLAND_DISPLAY so the Deck actually gets HDR
The gamescope WSI layer decides whether to engage from one signal:
isRunningUnderGamescope() reads $GAMESCOPE_WAYLAND_DISPLAY and nothing
else. flatpak does not forward host env into the sandbox, so it arrived
unset and the layer's CreateInstance early-returned before creating a
GamescopeInstance — no gamescope surface, so the HDR10/ST.2084 formats
were never appended and the surface stayed SDR.
The layer still loads and still logs its generic bits in that state, so
it reads as working. It is not: the three settings already here (layer
search path, ENABLE_GAMESCOPE_WSI, the socket bind) all sit downstream
of this gate and buy nothing without it.
Measured on a Deck OLED (Galileo, SteamOS 3.8.16), client --browse,
reading "swapchain config":
unset -> no [Gamescope WSI] Surface state block, None
set, hdr_enabled=0 -> server hdr output enabled: false, None
set, hdr_enabled=1 -> hdr formats exposed to client: true,
Some(A2B10G10R10_UNORM_PACK32, HDR10_ST2084_EXT)
Matches the field report of "HDR->SDR" in the stats overlay on a
correct HDR host. DXVK_HDR was ruled out by measurement. The remaining
gate (gamescope's hdr_enabled convar = Steam's HDR display setting) is
a user-side step, not a packaging one.
This commit is contained in:
@@ -93,20 +93,38 @@ finish-args:
|
||||
# /usr/lib/extensions/vulkan/gamescope once installed (a one-time, per-Deck step; keep it in the
|
||||
# Decky plugin's setup / docs):
|
||||
# flatpak install --user -y flathub org.freedesktop.Platform.VulkanLayer.gamescope//25.08
|
||||
# THREE things are needed, not two (verified live on a Deck OLED — the env vars alone left
|
||||
# hdr10_format=None). (1) VK_ADD_IMPLICIT_LAYER_PATH puts the layer's implicit-layer JSON on the
|
||||
# Vulkan loader's search path (the runtime point mounts the files but not onto the path). (2)
|
||||
# ENABLE_GAMESCOPE_WSI flips the layer's own `enable_environment` gate. (3) The layer, once
|
||||
# loaded, must open a *Wayland* connection to gamescope's private socket ($GAMESCOPE_WAYLAND_DISPLAY
|
||||
# = gamescope-0) to negotiate the HDR10 colorspace via the gamescope_swapchain protocol — but the
|
||||
# Deck runs games as X11 clients (DISPLAY=:1, no WAYLAND_DISPLAY exported), so --socket=wayland
|
||||
# binds nothing and that socket never enters the sandbox. Without it the layer loads, maps, and
|
||||
# silently can't reach the compositor → no HDR10 offered → PQ tone-mapped to SDR, badge dark.
|
||||
# Binding xdg-run/gamescope-0 is the missing half (chiaki-ng does the same). With all three the
|
||||
# surface offers HDR10 and the presenter's existing HDR10 swapchain path engages — no client code
|
||||
# change. Harmless off-Deck: the layer no-ops when there's no gamescope socket to bind.
|
||||
# FOUR things are needed. An earlier revision of this block claimed three and was WRONG: the
|
||||
# fourth is the gate that makes the other three moot, so the Deck sat at hdr10_format=None with
|
||||
# all of (1)-(3) in place, which is exactly the field report ("HDR->SDR" in the stats overlay).
|
||||
# (1) VK_ADD_IMPLICIT_LAYER_PATH puts the layer's implicit-layer JSON on the Vulkan loader's
|
||||
# search path (the runtime point mounts the files but not onto the path). (2) ENABLE_GAMESCOPE_WSI
|
||||
# flips the layer's own `enable_environment` gate. (3) --filesystem=xdg-run/gamescope-0 binds
|
||||
# gamescope's private Wayland socket: the layer must reach the compositor over it to negotiate
|
||||
# HDR10, and the Deck runs games as X11 clients (DISPLAY=:1, no WAYLAND_DISPLAY exported) so
|
||||
# --socket=wayland binds nothing (chiaki-ng does the same). (4) GAMESCOPE_WAYLAND_DISPLAY must be
|
||||
# set INSIDE the sandbox. The layer's `isRunningUnderGamescope()` reads that env var and nothing
|
||||
# else; flatpak does not forward host env, so it arrives unset and the layer's CreateInstance
|
||||
# early-returns before it ever creates a GamescopeInstance. The layer still LOADS and still logs
|
||||
# its generic bits ("Forcing on VK_EXT_swapchain_maintenance1", swapchain destroys), which is why
|
||||
# this reads as working — but no gamescope surface is made, so no HDR10 format is ever appended
|
||||
# and (1)-(3) buy nothing. Measured on a Deck OLED (Galileo, SteamOS 3.8.16) 2026-08-05, client
|
||||
# `--browse`, reading `pf_presenter::vk::setup` "swapchain config":
|
||||
# unset -> no "[Gamescope WSI] Surface state" block at all, hdr10_format=None
|
||||
# set, hdr_enabled=0 -> "server hdr output enabled: false", hdr10_format=None
|
||||
# set, hdr_enabled=1 -> "hdr formats exposed to client: true",
|
||||
# hdr10_format=Some(A2B10G10R10_UNORM_PACK32, HDR10_ST2084_EXT)
|
||||
# DXVK_HDR is NOT the gate for us and was ruled out by measurement: the layer forces it OFF for
|
||||
# clients it has already decided to deny, it does not turn HDR on.
|
||||
# Hardcoding `gamescope-0` matches the socket bound just below, and is safe off-Deck both ways:
|
||||
# on a normal Wayland desktop --socket=wayland sets WAYLAND_DISPLAY=wayland-0 inside the sandbox
|
||||
# and the layer bails on the mismatch; on X11-only there is no gamescope socket to connect to, so
|
||||
# it prints one "Bypass layer will be unavailable" line and passes through.
|
||||
# The REMAINING gate is not ours: gamescope's `hdr_enabled` convar (Steam's HDR display setting)
|
||||
# drives the GAMESCOPE_HDR_OUTPUT_FEEDBACK X property the layer reads, and with it off no app on
|
||||
# the Deck gets HDR. See docs — that one is a user/Decky-side step, not a packaging one.
|
||||
- --env=VK_ADD_IMPLICIT_LAYER_PATH=/usr/lib/extensions/vulkan/gamescope/share/vulkan/implicit_layer.d
|
||||
- --env=ENABLE_GAMESCOPE_WSI=1
|
||||
- --env=GAMESCOPE_WAYLAND_DISPLAY=gamescope-0 # the layer's ONLY "am I under gamescope?" signal
|
||||
- --filesystem=xdg-run/gamescope-0 # gamescope's private Wayland socket (HDR negotiation)
|
||||
|
||||
build-options:
|
||||
|
||||
Reference in New Issue
Block a user