glass panels: dirty-skip -- repaint only the windows whose gauges changed

Follow-on to the HALFTONE->COLORONCOLOR fix.  BTGlassPanels_Tick repainted all 7
glass windows every ~16 Hz pump unconditionally.  Now each window carries a change
token and the pump re-blits ONLY the windows whose token differs:

  token = FNV-1a checksum of the shared gauge pixelBuffer masked to the bits this
          window can show (SVGA16::PlaneChecksum over primary + Eng-twin + RGB-group
          ports)  combined with  each button's RENDERED lamp brightness + held/latch.

Folding the flash BRIGHTNESS (not the raw lamp state) into the token means a flashing
lamp repaints exactly when it toggles; a static panel or an idle cockpit skips its
expand + StretchDIBits entirely.  The masked checksum reads the RENDERED RESULT of the
gauges' values, so it catches everything -- discrete value gauges, the continuous
radar sweep, any imagery -- with no gauge->port->window plumbing and no risk of a
frozen display (full pass, no stride; collision-free in practice).

Measured (dev box, solo mission, BT_GLASS_DIRTY): ~31 pumps/2s -> 4-15 window-repaints
vs 217-224 always-on (~15-40x fewer); avg frame work 3.3 -> 0.93ms.  BT_GLASS_DIRTY=1
logs the repaint tally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-09 23:01:20 -05:00
co-authored by Claude Opus 4.8
parent f3d27f51c2
commit c9e25e59c5
2 changed files with 113 additions and 3 deletions
+22
View File
@@ -692,6 +692,28 @@ void SVGA16::DrawDevSurface(LPDIRECT3DDEVICE9 device, int slot, int mask, int pa
device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, sizeof(InsetVert));
}
//===========================================================================//
// GLASS dirty-skip: FNV-1a over the shared pixelBuffer masked to `mask` -- the bits
// one glass window can show. The glass repaint pump compares this per window and
// re-blits only the ones whose plane changed (L4GLASSWIN BTGlassPanels_Tick). Full
// pass (no stride) so a single-word gauge change is never missed; ~640*480 cheap
// integer ops, run at most once per window per ~16 Hz pump.
//===========================================================================//
unsigned long SVGA16::PlaneChecksum(int mask) const
{
int w = pixelBuffer.Data.Size.x;
int h = pixelBuffer.Data.Size.y;
const Word *p = pixelBuffer.Data.MapPointer;
if (p == NULL || w <= 0 || h <= 0)
return 0;
unsigned long sum = 2166136261UL; // FNV-1a offset basis
Word m = (Word)mask;
int n = w * h;
for (int i = 0; i < n; ++i)
sum = (sum ^ (unsigned long)(p[i] & m)) * 16777619UL;
return sum;
}
//===========================================================================//
// GLASS per-display windows -- the CPU (no-D3D) analog of DrawDevSurface: expand
// one bit-plane of the shared gauge pixelBuffer into a 32-bit BGRA image that the