Skip to content

glx/xlib: count the alpha channel in GLX_BUFFER_SIZE (Tomb Raider I-III under gamescope) - #58

Merged
utkarshdalal merged 1 commit into
zink-mesa-xlib-pipettofrom
xlib-glx-buffer-size-counts-alpha
Nov 4, 2026
Merged

utkarshdalal merged 1 commit into
zink-mesa-xlib-pipettofrom
xlib-glx-buffer-size-counts-alpha

Conversation

@utkarshdalal

@utkarshdalal utkarshdalal commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Tomb Raider I-III Remastered (OpenGL) dies about 3 s after its window maps under gamescope, while the same container renders at 60 fps under the in-app X server (RP6, payload 20261104.1, Proton 10 arm64ec, Wrapper/Turnip).

WINEDEBUG=+wgl,+opengl on both backends shows the only difference. The game calls wglChoosePixelFormatARB asking for 32 colour bits (a minimum match in Wine's chooser):

backend formats Wine offers result
in-app X server (one visual, depth 32) color 32 8,8,8,8 depth 24 stencil 8 match, 60 fps
gamescope / Xwayland (default visual depth 24) color 24 8,8,8,8 depth 24 stencil 8 (x2) 0 formats → err:wgl:set_pixel_format Invalid format -5265184 → null call, exit

Both backends load the same guest libGL (this branch's xlib GLX emulation, Server GLX vendor: Brian Paul), whose fbconfigs are the X visuals and whose GLX_BUFFER_SIZE is visinfo->depth. With the forced alpha channel that gives 24 colour bits plus 8 alpha bits on Xwayland, which no Windows driver ever reports: a DRI GLX fbconfig for the same channels says 32, and Wine copies GLX_BUFFER_SIZE straight into cColorBits.

Fix

In get_config(), count the alpha bits in GLX_BUFFER_SIZE when the visual depth only covers the RGB channels. Depth-32 visuals (the in-app X server) are unchanged.

The second commit adds a README section saying what this branch ships in GameNative (extra_libs.tzst → usr/lib/libGL.so.1.5.0, used by both display servers, built from c1567e9) and how to build it.

Provenance of the shipped binary vs this branch

The shipped libGL.so.1.5.0 reports git-c1567e9609, five commits behind this branch's head (Pipetto's May 2026 commits: Winlator window properties, dri-options hack, two Mali fixes). The test binary below is c1567e9 + this fix, so the device A/B differs from the shipped file only in the fix.

Testing on the RP6 (gamescope, container unchanged apart from the swapped archive)

  • Shipped libGL: crash at window map as above (launch2, launch4).
  • Patched libGL (emutls build): dlopen failed: cannot locate symbol "__emutls_v._glapi_tls_Context" against the shipped libglapi.so.0. Rebuilt with -fno-emulated-tls.
  • Patched libGL (ELF TLS): Wine now lists color 32 8,8,8,8, wglChoosePixelFormatARB returns format 1, SetPixelFormat(1) succeeds, the game creates its context and issues draw calls (about 200 swaps/s in the traced run). No crash.
  • Remaining issue, outside this library: the screen stays black with audio playing. gamescope's session blind (session_game_window_absent) paints black because the game loads dxgi/d3d11 and the shim binds a Vulkan override surface that never presents, while the GL frames arrive on the X window's own surface. That is a gamescope change, tracked separately.

The xlib GLX emulation reports GLX_BUFFER_SIZE as the X visual's depth. When
the visual carries an alpha channel on top of its stored planes (an 8/8/8/8
config on a depth-24 TrueColor visual, which is what Xwayland offers), that
makes the format 24 colour bits with 8 alpha bits. A DRI GLX fbconfig for the
same channels reports 32, and Wine turns GLX_BUFFER_SIZE into cColorBits, so
wglChoosePixelFormatARB requests for 32 colour bits (a minimum match) found no
format under gamescope: Tomb Raider I-III Remastered then used an
uninitialised format index and crashed right after its window mapped.

Count the alpha bits when the visual depth only covers the RGB channels. On
the in-app X server the single visual is depth 32, so nothing changes there.
@utkarshdalal

Copy link
Copy Markdown
Contributor Author

RP6 result (2026-11-04)

Built as the shipped extra_libs variant from c1567e9 + this commit only (the file we ship was built from c1567e9; Utkarsh's call is to keep that base and add only this fix, not the five later commits on this branch), ELF TLS (-fno-emulated-tls, otherwise dlopen fails on __emutls_v._glapi_tls_Context against the shipped libglapi.so.0).

Tomb Raider I-III Remastered under gamescope (with GameNative/gamescope#32 for the session blind): Wine now lists color 32 8,8,8,8, wglChoosePixelFormatARB returns format 1, SetPixelFormat(1) succeeds, the game renders its title screen at 60 fps. Before: err:wgl:set_pixel_format Invalid format -5265184 and a null-call exit 3 s after the window mapped.

Shipping candidate: graphics_driver/extra_libs-20261104.tzst = the current extra_libs.tzst with usr/lib/libGL.so.1.5.0 replaced (15524096 B), sha256 5808942d2426630aad644ccde78491991d035815c689a79f0300879a3285bb20. Not uploaded yet.

@utkarshdalal utkarshdalal reopened this Nov 4, 2026
@utkarshdalal
utkarshdalal merged commit 36373cf into zink-mesa-xlib-pipetto Nov 4, 2026
0 of 4 checks passed
utkarshdalal added a commit to utkarshdalal/GameNative that referenced this pull request Nov 4, 2026
…ame) + guest libGL extra_libs-20261104 (32-bit colour on Xwayland) (#2344)

* gamescope: payload 20261104.2 (A33 blind lifts on the game's first frame) and guest libGL extra_libs-20261104 (32-bit colour on Xwayland)

Tomb Raider I-III Remastered (OpenGL) under gamescope: crashed 3 s after its
window mapped, then (once past that) sat black with audio playing.

- extra_libs-20261104.tzst: the guest libGL (Mesa xlib GLX on zink, the same
  file on X11 and gamescope) reported GLX_BUFFER_SIZE as the X visual's depth,
  24 on Xwayland against 32 on the in-app X server; the game's
  wglChoosePixelFormatARB needs 32 and got no format. GameNative/mesa#58 counts
  the emulated alpha channel. Same archive otherwise; the manifest entry's file
  name changes because the app caches archives by name.
- payload 20261104.2: gamescope A33's startup blind lifted only on a commit from
  the Vulkan override surface; a GL guest's frames arrive on the X window's own
  surface, and this game also binds an override it never presents on, so the
  blind never lifted. GameNative/gamescope#32: the blind lifts on the first
  commit newer than the override's binding. Only bin/gamescope differs from
  20261104.1.

RP6 verified: title screen at 60 fps under gamescope, blind on at map and off
16 ms later.

* legacy: bundle the extra_libs-20261104 archive (the legacy flavor extracts graphics_driver/extra_libs.tzst from the APK, not the manifest)

---------

Co-authored-by: Utkarsh Dalal <utkarsh.dalal@toptal.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant