feat(hdr): z-ordered multi-layer compositing with PQ support#289
Open
vanceingalls wants to merge 1 commit intofeat/hdr-phase-1from
Open
feat(hdr): z-ordered multi-layer compositing with PQ support#289vanceingalls wants to merge 1 commit intofeat/hdr-phase-1from
vanceingalls wants to merge 1 commit intofeat/hdr-phase-1from
Conversation
This was referenced Apr 16, 2026
Collaborator
Author
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
This was referenced Apr 16, 2026
45cb5a7 to
16ff590
Compare
e19081a to
1ea1b2b
Compare
16ff590 to
823ba6b
Compare
1ea1b2b to
528ea17
Compare
Per-frame z-order analysis groups elements into DOM and HDR layers, composited bottom-to-top. Adjacent DOM elements merge into single screenshots. PQ (HDR10/smpte2084) support via sRGB-to-PQ LUT with 203-nit SDR reference white. queryElementStacking walks DOM for effective z-index, groupIntoLayers splits on HDR/DOM boundaries. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
912fced to
f39b02a
Compare
2837b2c to
eb10879
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Phase 1 only handled HDR video on the bottom with DOM on top. Real compositions need arbitrary z-interleaving — HDR video between DOM layers, multiple HDR videos at different z-depths, SDR video as background below HDR. This PR adds per-frame z-order analysis and layer-by-layer compositing.
What it does
Per-frame algorithm:
queryElementStacking()asks Chrome for every timed element's z-index, bounds, opacity, visibility, and whether it's an HDR video.groupIntoLayers()walks the z-sorted list. Each time the content type switches (DOM ↔ HDR), a new layer starts. Adjacent DOM elements merge into a single layer (fewer Chrome screenshots).Example z-order:
This produces 3 screenshots + 2 native blits = 5 layer operations per frame.
Also adds PQ (HDR10) support:
buildSrgbToHdrLut("pq")— PQ OETF (SMPTE 2084) maps SDR white to ~203 nits (~58% PQ signal)blitRgba8OverRgb48le()now acceptstransfer: "hlg" | "pq"parameterblitRgb48leRegion()— positioned rectangular copy with bounds clipping and optional opacityFiles changed
packages/engine/src/utils/layerCompositor.tsgroupIntoLayers(),CompositeLayertypepackages/engine/src/services/videoFrameInjector.tsqueryElementStacking()with effective z-index walk,ElementStackingInfotypepackages/engine/src/utils/alphaBlit.tsblitRgb48leRegion(), transfer parameterpackages/producer/src/services/renderOrchestrator.tsHow to test
Render a composition with SDR video below HDR video below text overlays. All three should be visible at their correct z-depths.
Stack position
4 of 6 — Stacked on #288 (two-pass compositing). Generalizes the fixed two-layer model to arbitrary N-layer compositing.
🤖 Generated with Claude Code