Skip to content

Display seam for external DMD output (real / virtual / colorized)#558

Merged
freezy merged 3 commits into
masterfrom
dmd
Jun 28, 2026
Merged

Display seam for external DMD output (real / virtual / colorized)#558
freezy merged 3 commits into
masterfrom
dmd

Conversation

@freezy

@freezy freezy commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Small, additive changes to the GLE display seam so an external package
(VisualPinball.Engine.DMD) can fan display frames out to real DMD hardware, an on-screen virtual DMD, and a colorization stage without touching the in-scene rendering path. Also includes two small correctness/perf fixes in the in-scene DMD.

No behavior changes for existing setups. Every addition is opt-in and ReceiveGamelogicFrames
defaults to the current behavior.

Game/Engine/IGamelogicEngine.cs - two optional capability interfaces + a documented contract:

  • IRomNameProvider { string RomName } - lets a consumer resolve the active ROM (for colorization
    lookup) without reflection.
  • IDisplayFrameFormatPreference { void RequestDisplayFrameFormat(string displayId, DisplayFrameFormat format) } - lets a consumer request a frame format per display (e.g. Dmd4 for colorization vs Dmd8).
  • Documented the threading / buffer-ownership contract on OnDisplayUpdateFrame: it must be
    raised on the Unity main thread, and DisplayFrameData.Data is only valid for the duration of the
    call (a subscriber that hands it to a worker thread must copy it).

Gamelogic engines opt in by implementing the interfaces (PinMAME does so in its own repo); engines
that don't are unaffected.

Display/DisplayComponent.cs - adds bool ReceiveGamelogicFrames (default true). When an
external owner (e.g. the DMD bridge's in-scene destination) takes over a display, it flips this off
so the built-in DisplayPlayer stops writing that display's texture.

Game/DisplayPlayer.cs - honors ReceiveGamelogicFrames on frame-update, clear, and
display-requested events (the last one prevents a blank-frame flicker and a redundant Texture2D
reallocation when an externally-owned display is re-requested mid-game). Minor TryGetValue cleanups.

Display/DotMatrixDisplayComponent.cs

  • RGB24 frames are now copied to the texture with a vertical row flip, matching the orientation of
    the gray (Dmd2/4/8) path (CopyData gained a destination offset so it can copy row-by-row).
  • The gray palette lookup uses a single TryGetValue instead of ContainsKey + indexer (two
    dictionary lookups per pixel → one).
  • Removed a stray FLIPX debug log.

freezy added 3 commits June 27, 2026 16:47
Add a ReceiveGamelogicFrames flag to DisplayComponent so individual
displays can opt out of gamelogic engine frames, honored in
DisplayPlayer's clear/update handlers.

Flip RGB24 (Dmd24) frames vertically when copying into the texture
via the new CopyRgb24FrameToTexture helper, fixing upside-down
rendering.

Introduce IDisplayFrameFormatPreference to let engines request a
preferred display frame format.
Introduce IRomNameProvider as an optional capability interface so
consumers (e.g. the DMD bridge resolving colorization) can read the
running ROM name without reflecting over the concrete engine type.
Also drop the stray "FLIPX" error log from mesh regeneration.
When another subscriber (e.g. the DMD bridge's in-scene destination)
owns a display and feeds the component itself, the display player must
not reconfigure it: resizing the texture and calling Clear() caused a
visible flicker. Skip displays whose ReceiveGamelogicFrames is false.

Also document the OnDisplayUpdateFrame contract (raise on the Unity
main thread; frame buffer only valid for the synchronous call, so
subscribers retaining it must copy) and switch a couple of dictionary
lookups to TryGetValue.
@freezy freezy self-assigned this Jun 28, 2026
@greptile-apps

greptile-apps Bot commented Jun 28, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds an opt-in seam for external DMD frame handling. The main changes are:

  • Added a ReceiveGamelogicFrames flag for display ownership.
  • Skipped built-in display updates, clears, and resize requests when that flag is disabled.
  • Added optional game-logic capability interfaces for ROM names and display frame format requests.
  • Documented the display frame threading and buffer lifetime contract.
  • Flipped RGB24 DMD texture copies to match the grayscale path.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
VisualPinball.Unity/VisualPinball.Unity/Display/DisplayComponent.cs Adds the opt-in frame ownership flag with the existing behavior kept as the default.
VisualPinball.Unity/VisualPinball.Unity/Display/DotMatrixDisplayComponent.cs Flips RGB24 frame rows during raw texture copy and simplifies grayscale palette lookup.
VisualPinball.Unity/VisualPinball.Unity/Game/DisplayPlayer.cs Skips display configuration, clearing, and frame updates for externally owned displays.
VisualPinball.Unity/VisualPinball.Unity/Game/Engine/IGamelogicEngine.cs Adds optional display-related capability interfaces and documents the frame event contract.

Reviews (1): Last reviewed commit: "dmd: Skip externally-owned displays on d..." | Re-trigger Greptile

@freezy freezy merged commit e8cb5c1 into master Jun 28, 2026
16 checks passed
@freezy freezy deleted the dmd branch June 28, 2026 20:01
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