Wait screen: paint into the backbuffer, not after Present (load flicker)

The pre-mission overlay painted the window DC AFTER ExecuteIdle's
Present -- every cycle flashed the black D3D frame before the GDI
redraw, visible as flicker while the game loads (user report).  The
overlay now lands IN the presented frame: the backbuffer refuses GetDC
on this driver (D3DERR_INVALIDCALL without LOCKABLE_BACKBUFFER, not
worth forcing game-wide), so the text+spinner GDI-paint goes into a
cached offscreen plain surface (GetDC always legal there) and
StretchRects onto the backbuffer before Present.  D3DPOOL_DEFAULT cache
released at every device-Reset site; window-DC path remains for the
pre-device seat wait and as the fallback; one-shot [waitscreen] boot log
says which path is live.

Verified: 14 rapid PrintWindow captures of the waiting state all carry
the text (pre-fix runs alternated black frames).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-22 16:33:41 -05:00
co-authored by Claude Opus 4.8
parent 2cccf877f5
commit c421ec4af8
3 changed files with 116 additions and 15 deletions
+15
View File
@@ -63,6 +63,21 @@ version skew (a stale steam exe shipped 2 days behind), tripled build time, and
([[reconstruction-gotchas]]); everything links always, so this class of trap no longer varies
by build flavor.
## The pre-mission WAITING SCREEN (2026-07-22) [T2]
Every pre-run state (seat wait, roster full, WaitingForEgg, LoadingMission, WaitingForLaunch)
paints an animated overlay -- Consolas green text + a 12-segment spinner phased on
GetTickCount/80 (`BTWaitScreenPaintDC`, L4VIDEO.cpp) -- so a joining player never sees "Not
Responding" or a frozen frame. Two paint paths: PRE-DEVICE (relay seat wait, L4NET
`RelayWaitTick`) paints the window DC directly (nothing else presents -- safe); ONCE THE
DEVICE EXISTS (`DPLRenderer::ExecuteIdle`) it must NOT paint after Present (the black D3D
frame alternating with GDI = the load-time flicker, user-reported) -- and the backbuffer
refuses `GetDC` (D3DERR_INVALIDCALL without D3DPRESENTFLAG_LOCKABLE_BACKBUFFER, which we
won't force game-wide), so the overlay GDI-paints into a cached OFFSCREEN PLAIN surface
(`mWaitOverlaySurface`, GetDC always legal there) and `StretchRect`s onto the backbuffer
BEFORE Present. D3DPOOL_DEFAULT: released at every device-Reset site. One-shot boot log
`[waitscreen] paint path:` says which path is live. Verified: 14 rapid PrintWindow frames
all carry the text (was alternating black).
## Plan of record (2026-07-17)
Working branch `glass-cockpit` (from master `e2c21c4`). Steps: (1) gates+scaffolding [THIS],