Repository navigation
Conversation
With DM_HDR=1, vi::QueryDisplayHdrStatus answers HDR on for Switch 2 SDKs, and the game makes an RGB10A2 window of PQ code values in BT.2020 (Donkey Kong Bananza). The Mac and iOS layers become RGBA16Float in extended linear BT.2020. present.metal decodes PQ (1.0 at the 203-nit paper white) and 8-bit sRGB, and rolls highlights off into the screen's EDR headroom. Without DM_HDR nothing changes. The layer HDR metadata calls are still dropped, and logged while HDR is on. Screenshots take 10-bit windows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A launcher row on the Mac and iOS, off by default, shown when the game's sdk module names the Ounce spec. The findings and gaps are in Donkey Kong Bananza's note and docs/reference/rendering.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With DM_HDR=1 it queries the HDR status, then replaces its RGBA8 window with an RGB10A2 PQ one, declaring SDR 0 to 203 nits and extended 0 to 1000; the present decodes it with the right colours and crop. Measured to the title screen on the Mac. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The status query answers HDR only while the window's screen can show EDR, and the game follows the window between screens: Mario Kart World asks every frame and switches windows. The format is 1, as the SDK's own QueryHdrStatus sets on = (format == 1) (found in seedds#1249). The HDR layer carries HDR10 metadata with the game's declared range, and Core Animation maps highlights into the headroom. The host's own roll-off is gone: side by side it looked the same and reached the screen in the same time. Screenshots bring highlights to SDR white with their hue. Adds t_present_hdr and DM_PRESENT_SHOWN, a log of when frames reach the screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With 2, a screen without EDR gets the game's HDR picture mapped down by Core Animation instead of the game's own SDR. On Mario Kart World the mapped picture is more saturated than its SDR; which is better is open. Moving the window between screens drops frames whether or not the game rebuilds its window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bananza asks for the HDR status every frame, as Mario Kart World does, and reaches the screen in the same time with HDR on. The Mac front end logged "no EDR metadata" on every DM_HDR=1 start: the else belonged to the check before the DM_HDR=2 title. DM_HDR_PAPER_WHITE and DM_HDR_PEAK have no launcher setting; they stand for what a console's HDR calibration sets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…window as it is; the RGBA16Float extended-range layer showed black blocks over flat areas on an M5 (#1) On a MacBook Air M5 (macOS 27.0.1) the extended linear BT.2020 layer showed black blocks with coloured squares over Mario Kart World's course-map water, now and then and after the window came back to the front, while the game's frames were clean. The layer now takes the PQ window as it is; an SDR source is encoded as HDR10 at the paper white (present_mode 3). DM_HDR_LAYER=float keeps the old layer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… float source encoded for the PQ layer Follow-up to the PQ layer (maxdavidson#1). The present code is shared, so the iPhone's front end only makes the same layer: RGB10A2 in BT.2100 PQ, with DM_HDR_LAYER=float keeping the RGBA16Float one on either platform (hle_vi.c dm_hdr_layer_float). - present_mode: a float source (linear BT.709) into the PQ layer is encoded as HDR10 at the paper white (mode 4), not decoded as sRGB first; t_present_hdr checks it (24 checks). - Docs and comments: the metadata's opticalOutputScale counts for the float layer only (Core Animation takes 10,000 for a normalized format), the Metal HUD shows at the screen's peak on the PQ layer, and the float layer's description moved to DM_HDR_LAYER. Donkey Kong Bananza's note has the two layers' times on an M4 Pro. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…runs The game asks for its HDR status every frame and switches between its SDR and HDR windows when the answer changes (as when the window moves to another screen), so HDR output can change while it runs. hle_vi.c keeps the mode (0 off, 1 by the screen, 2 on any screen) as a value the front end sets (dm_hdr_set_mode), read from DM_HDR at start. On iOS, dm_setting_live takes DM_HDR for Switch 2 games, so the gear menu offers the HDR output row: turning it on sets the PQ layer first, then the answer; turning it off answers SDR first, then gives the layer back its BGRA8 format. The frames around the change are drawn for the drawable they reach (present_mode). The declared range is kept while the layer is SDR, for the metadata once it is HDR. t_present_hdr: 27 checks (off, on again and mode 2 while the game runs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ut the 8x1 sources in a 2x1 bar of the 16:9 display, and 15 of 27 checks failed The present now lays the picture out in the vi layer's shape, the display's 16:9 when no layer is sized (nvn_mtl.m present_shape). The test calls mtl_present_layer(N, 1), as t_present_crop and t_present_alloc do, so each source texel lands on its own target texel again. 27 of 27 pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…za; the iPhone shows HDR on the PQ layer Ocarina of Time (0400486024DEC000, Mac app, chain cfcc3a82c78b): it boots an RGBA8 window (0x25), asks vi::QueryDisplayHdrStatus every frame, and told HDR (DM_HDR=2) makes an RGB10A2 window (0x3d) with SDR 0..203 and extended 0..710 nits; no new RED line. On an LG monitor with HDR off in macOS, DM_HDR=1 answers SDR and it keeps the RGBA8 window. Donkey Kong Bananza on an iPhone 17 Pro (iOS 27.2) shows HDR on the PQ layer. Open: with HDR on only, the picture jumps back a frame now and then while the frame rate drops. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s the screen's current EDR headroom (Mac) HDR paper white (120 to 400 nits, default 203) and HDR peak (400 to 1600, default 1000) are rows under HDR output, drawn while it is on, and set the existing DM_HDR_PAPER_WHITE and DM_HDR_PEAK: what a console's HDR calibration sets. At the defaults the answers are unchanged. HDR output gets a description and level=basic, so the two rows show with it. DM_HDR_PEAK=auto (the row's Automatic, Mac only) answers the paper white times the window's screen's current EDR headroom (maximumExtendedDynamicRangeColorComponentValue, read beside the potential headroom four times a second), rounded to 10 nits, never below the paper white and at most 16 bits, logged when it changes, at most once a second. iOS would need UIScreen.currentEDRHeadroom; without it auto is the paper white. Ocarina of Time (0400486024DEC000, v131072) on a MacBook Pro M2 Pro's XDR panel (potential headroom 16, macOS 27.2) declares min(peak, 3.5 x paper white): DM_HDR_PEAK=400 gives 0..400, 1600 gives 0..710, DM_HDR_PAPER_WHITE=300 gives 0..1000. With Automatic and the window in front, the headroom followed the brightness slider both ways (16 at low brightness, 3.2 at full) and the game declared its range again during play (0..710 -> 0..650 -> 0..710). Front-ends: new: DM_HDR_PEAK=auto reads the weak front_hdr_headroom() (the window's screen's current EDR headroom, front_mac.m); a front end without it answers the paper white for auto. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maxdavidson
force-pushed
the
feat/switch2-hdr-output
branch
2 times, most recently
from
November 10, 2026 18:43
8c265de to
cf2ca59
Compare
maxdavidson
pushed a commit
that referenced
this pull request
Nov 10, 2026
…en that can show EDR, the game's HDR10 window goes as it is into an RGB10A2 BT.2100 PQ layer, and the peak follows the screen's current headroom with no HDR10 metadata on the layer, on the Mac and iOS - hle_vi.c: with DM_HDR=1 (the HDR output row, on by default) vi::QueryDisplayHdrStatus answers HDR on, format 1, while the window's screen can show EDR (DM_HDR=2: on any screen), and the game asks every frame, so its window follows the screen; the iOS in-game menu turns it on and off while the game runs. The paper white (DM_HDR_PAPER_WHITE, the HDR paper white row) is 100 nits by default, the screen's own white: macOS shows a PQ layer at EDR = nits / 100, measured with an extended-range screen capture, so the game's normal picture matches SDR and the headroom is left to its highlights (by eye, Mario Kart World at 100 had SDR's base brightness with brighter highlights; at 203 the whole picture was brighter). - The peak (DM_HDR_PEAK, the HDR peak row) is automatic by default: 100 nits times the screen's current headroom (front_hdr_headroom: NSScreen's maximumExtendedDynamicRangeColorComponentValue on the Mac, UIScreen's currentEDRHeadroom on iOS), in steps of about 6 % taken once they have held for a second, at least twice the paper white, so the game tone-maps into what the screen shows. Donkey Kong Bananza and Ocarina of Time declare within the peak they are told, and all three games' pixels stay within it. - No HDR10 metadata on the layer (DM_HDR_META=1 adds it): with metadata above 100 x headroom Core Animation compresses the whole picture, mid-tones included (measured), and Mario Kart World declares about 1.8 times the peak it is told; and in fullscreen a layer with metadata of any range showed rectangles of older frames under GPU load, in the host and in a standalone app with no game, judged by eye without knowing the mode (dm/gfx/tools/hdr_rects.mm), none without. A fixed peak above the screen's is rolled off in the present above three quarters of the screen's held peak (present.metal mode 4), keyed on the smaller of the declared range and the peak told. - present.metal and nvn_mtl.m present_mode: the HDR10 window as it is into the PQ layer, an SDR or float source encoded at the paper white while the status answers HDR and at 100 nits, the screen's SDR white, while it answers SDR (at 203 an SDR screen showed the SDR picture twice as bright and clipped), an HDR frame brought to SDR white with its hue for screenshots and SDR drawables; RGB10A2 windows are PQ only once the status has answered HDR. A PQ layer rather than an extended-range float one, which showed black blocks over flat areas on a MacBook Air M5 while the game's frames were clean. - With metadata in fullscreen (DM_PRESENT_AFTER_GPU), the drawable is handed to the system once its present pass has completed, without signalDrawable, which with the pass completed made frames a refresh late; it costs frames a refresh late when the pass ends close to the refresh, so it is off without metadata and in a window. - dm/gfx/tools/edr_probe.m measures how macOS maps a PQ layer into EDR; dm/gfx/tools/hdr_rects.mm reproduces the rectangles with no game. - t_present_hdr: the status answer, the automatic peak and its hold, the PQ decode and encode, the roll-off's curve, SDR and float sources, screenshots; test_settings: the rows and their per-platform defaults. - Notes: Donkey Kong Bananza, Mario Kart World and Ocarina of Time's HDR windows and what each declares; three reference entries in docs/reference/rendering.md. The PQ layer is beecrepaldi-afk's (#1), the present after the GPU and the standalone app that found the rectangles b1tdr3amer24's (#2), the paper white and peak rows and the automatic peak's front end hook Amost's (#3). Front-ends: new: HDR output for Switch 2 games (DM_HDR, DM_HDR_PAPER_WHITE, DM_HDR_PEAK rows): the front end makes the HDR layer RGB10A2 in kCGColorSpaceITUR_2100_PQ with wantsExtendedDynamicRangeContent (front_mac.m, front_ios.m) Front-ends: new: the HDR output row defaults to on; the host's own default, DM_HDR unset, stays SDR, so a front end that does not pass the row's value starts the game in SDR Front-ends: new: front_hdr_screen() (the window's screen can show EDR) and front_hdr_headroom() (its current EDR headroom) are weak hooks in hle_vi.c; without front_hdr_headroom the automatic peak answers 1000 and nothing is rolled off Front-ends: new: a front end calls dm_hdr_layer_meta_set() with whether it gave the layer HDR10 metadata, and receives the game's declared range through front_hdr_content_range() for that metadata Co-authored-by: beecrepaldi-afk <beecrepaldi@gmail.com> Co-authored-by: b1tdr3amer24 <240231594+b1tdr3amer24@users.noreply.github.com> Co-authored-by: Amost <6445689+Amost-@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
|
Thanks for the launcher rows and the Automatic peak, and for the measurements on the M2 Pro. Your work is in seedds#1176, in its single commit, with you as a co-author. That pull request is now one squashed commit on current main, so this one can't be merged here, and I'm closing it. What changed on top of it, from measurements on a MacBook Pro M4 Pro's XDR screen and an LG C3 TV (macOS 27.2):
Your headroom readings (16 at low brightness, 3.2 at full) are in the reference entry, credited to this PR. If the M2 Pro shows something different with the new defaults, a follow-up is welcome. |
maxdavidson
pushed a commit
that referenced
this pull request
Nov 11, 2026
…en that can show EDR, the game's HDR10 window goes as it is into an RGB10A2 BT.2100 PQ layer, and the peak follows the screen's current headroom with no HDR10 metadata on the layer, on the Mac and iOS - hle_vi.c: with DM_HDR=1 (the HDR output row, on by default) vi::QueryDisplayHdrStatus answers HDR on, format 1, while the window's screen can show EDR (DM_HDR=2: on any screen), and the game asks every frame, so its window follows the screen; the iOS in-game menu turns it on and off while the game runs. The paper white (DM_HDR_PAPER_WHITE, the HDR paper white row) is 100 nits by default, the screen's own white: macOS shows a PQ layer at EDR = nits / 100, measured with an extended-range screen capture, so the game's normal picture matches SDR and the headroom is left to its highlights (by eye, Mario Kart World at 100 had SDR's base brightness with brighter highlights; at 203 the whole picture was brighter). - The peak (DM_HDR_PEAK, the HDR peak row) is automatic by default: 100 nits times the screen's current headroom (front_hdr_headroom: NSScreen's maximumExtendedDynamicRangeColorComponentValue on the Mac, UIScreen's currentEDRHeadroom on iOS), in steps of about 6 % taken once they have held for a second, at least twice the paper white, so the game tone-maps into what the screen shows. Donkey Kong Bananza and Ocarina of Time declare within the peak they are told, and all three games' pixels stay within it. - No HDR10 metadata on the layer (DM_HDR_META=1 adds it): with metadata above 100 x headroom Core Animation compresses the whole picture, mid-tones included (measured), and Mario Kart World declares about 1.8 times the peak it is told; and in fullscreen a layer with metadata of any range showed rectangles of older frames under GPU load, in the host and in a standalone app with no game, judged by eye without knowing the mode (dm/gfx/tools/hdr_rects.mm), none without. A fixed peak above the screen's is rolled off in the present above three quarters of the screen's held peak (present.metal mode 4), keyed on the smaller of the declared range and the peak told. - present.metal and nvn_mtl.m present_mode: the HDR10 window as it is into the PQ layer, an SDR or float source encoded at the paper white while the status answers HDR and at 100 nits, the screen's SDR white, while it answers SDR (at 203 an SDR screen showed the SDR picture twice as bright and clipped), an HDR frame brought to SDR white with its hue for screenshots and SDR drawables; RGB10A2 windows are PQ only once the status has answered HDR. A PQ layer rather than an extended-range float one, which showed black blocks over flat areas on a MacBook Air M5 while the game's frames were clean. - With metadata in fullscreen (DM_PRESENT_AFTER_GPU), the drawable is handed to the system once its present pass has completed, without signalDrawable, which with the pass completed made frames a refresh late; it costs frames a refresh late when the pass ends close to the refresh, so it is off without metadata and in a window. - dm/gfx/tools/edr_probe.m measures how macOS maps a PQ layer into EDR; dm/gfx/tools/hdr_rects.mm reproduces the rectangles with no game. - t_present_hdr: the status answer, the automatic peak and its hold, the PQ decode and encode, the roll-off's curve, SDR and float sources, screenshots; test_settings: the rows and their per-platform defaults. - Notes: Donkey Kong Bananza, Mario Kart World and Ocarina of Time's HDR windows and what each declares; three reference entries in docs/reference/rendering.md. The PQ layer is beecrepaldi-afk's (#1), the present after the GPU and the standalone app that found the rectangles b1tdr3amer24's (#2), the paper white and peak rows and the automatic peak's front end hook Amost's (#3). Front-ends: new: HDR output for Switch 2 games (DM_HDR, DM_HDR_PAPER_WHITE, DM_HDR_PEAK rows): the front end makes the HDR layer RGB10A2 in kCGColorSpaceITUR_2100_PQ with wantsExtendedDynamicRangeContent (front_mac.m, front_ios.m) Front-ends: new: the HDR output row defaults to on; the host's own default, DM_HDR unset, stays SDR, so a front end that does not pass the row's value starts the game in SDR Front-ends: new: front_hdr_screen() (the window's screen can show EDR) and front_hdr_headroom() (its current EDR headroom) are weak hooks in hle_vi.c; without front_hdr_headroom the automatic peak answers 1000 and nothing is rolled off Front-ends: new: a front end calls dm_hdr_layer_meta_set() with whether it gave the layer HDR10 metadata, and receives the game's declared range through front_hdr_content_range() for that metadata Co-authored-by: beecrepaldi-afk <beecrepaldi@gmail.com> Co-authored-by: b1tdr3amer24 <240231594+b1tdr3amer24@users.noreply.github.com> Co-authored-by: Amost <6445689+Amost-@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maxdavidson
pushed a commit
that referenced
this pull request
Nov 12, 2026
…en that can show EDR, the game's HDR10 window goes as it is into an RGB10A2 BT.2100 PQ layer, and the peak follows the screen's current headroom with no HDR10 metadata on the layer, on the Mac and iOS - hle_vi.c: with DM_HDR=1 (the HDR output row, on by default) vi::QueryDisplayHdrStatus answers HDR on, format 1, while the window's screen can show EDR (DM_HDR=2: on any screen), and the game asks every frame, so its window follows the screen; the iOS in-game menu turns it on and off while the game runs. The paper white (DM_HDR_PAPER_WHITE, the HDR paper white row) is 100 nits by default, the screen's own white: macOS shows a PQ layer at EDR = nits / 100, measured with an extended-range screen capture, so the game's normal picture matches SDR and the headroom is left to its highlights (by eye, Mario Kart World at 100 had SDR's base brightness with brighter highlights; at 203 the whole picture was brighter). - The peak (DM_HDR_PEAK, the HDR peak row) is automatic by default: 100 nits times the screen's current headroom (front_hdr_headroom: NSScreen's maximumExtendedDynamicRangeColorComponentValue on the Mac, UIScreen's currentEDRHeadroom on iOS), in steps of about 6 % taken once they have held for a second, at least twice the paper white, so the game tone-maps into what the screen shows. Donkey Kong Bananza and Ocarina of Time declare within the peak they are told, and all three games' pixels stay within it. - No HDR10 metadata on the layer (DM_HDR_META=1 adds it): with metadata above 100 x headroom Core Animation compresses the whole picture, mid-tones included (measured), and Mario Kart World declares about 1.8 times the peak it is told; and in fullscreen a layer with metadata of any range showed rectangles of older frames under GPU load, in the host and in a standalone app with no game, judged by eye without knowing the mode (dm/gfx/tools/hdr_rects.mm), none without. A fixed peak above the screen's is rolled off in the present above three quarters of the screen's held peak (present.metal mode 4), keyed on the smaller of the declared range and the peak told. - present.metal and nvn_mtl.m present_mode: the HDR10 window as it is into the PQ layer, an SDR or float source encoded at the paper white while the status answers HDR and at 100 nits, the screen's SDR white, while it answers SDR (at 203 an SDR screen showed the SDR picture twice as bright and clipped), an HDR frame brought to SDR white with its hue for screenshots and SDR drawables; RGB10A2 windows are PQ only once the status has answered HDR. A PQ layer rather than an extended-range float one, which showed black blocks over flat areas on a MacBook Air M5 while the game's frames were clean. - With metadata in fullscreen (DM_PRESENT_AFTER_GPU), the drawable is handed to the system once its present pass has completed, without signalDrawable, which with the pass completed made frames a refresh late; it costs frames a refresh late when the pass ends close to the refresh, so it is off without metadata and in a window. - dm/gfx/tools/edr_probe.m measures how macOS maps a PQ layer into EDR; dm/gfx/tools/hdr_rects.mm reproduces the rectangles with no game. - t_present_hdr: the status answer, the automatic peak and its hold, the PQ decode and encode, the roll-off's curve, SDR and float sources, screenshots; test_settings: the rows and their per-platform defaults. - Notes: Donkey Kong Bananza, Mario Kart World and Ocarina of Time's HDR windows and what each declares; three reference entries in docs/reference/rendering.md. The PQ layer is beecrepaldi-afk's (#1), the present after the GPU and the standalone app that found the rectangles b1tdr3amer24's (#2), the paper white and peak rows and the automatic peak's front end hook Amost's (#3). Front-ends: new: HDR output for Switch 2 games (DM_HDR, DM_HDR_PAPER_WHITE, DM_HDR_PEAK rows): the front end makes the HDR layer RGB10A2 in kCGColorSpaceITUR_2100_PQ with wantsExtendedDynamicRangeContent (front_mac.m, front_ios.m) Front-ends: new: the HDR output row defaults to on; the host's own default, DM_HDR unset, stays SDR, so a front end that does not pass the row's value starts the game in SDR Front-ends: new: front_hdr_screen() (the window's screen can show EDR) and front_hdr_headroom() (its current EDR headroom) are weak hooks in hle_vi.c; without front_hdr_headroom the automatic peak answers 1000 and nothing is rolled off Front-ends: new: a front end calls dm_hdr_layer_meta_set() with whether it gave the layer HDR10 metadata, and receives the game's declared range through front_hdr_content_range() for that metadata Co-authored-by: beecrepaldi-afk <beecrepaldi@gmail.com> Co-authored-by: b1tdr3amer24 <240231594+b1tdr3amer24@users.noreply.github.com> Co-authored-by: Amost <6445689+Amost-@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maxdavidson
pushed a commit
that referenced
this pull request
Nov 13, 2026
…en that can show EDR, the game's HDR10 window goes as it is into an RGB10A2 BT.2100 PQ layer, and the peak follows the screen's current headroom with no HDR10 metadata on the layer, on the Mac and iOS - hle_vi.c: with DM_HDR=1 (the HDR output row, on by default) vi::QueryDisplayHdrStatus answers HDR on, format 1, while the window's screen can show EDR (DM_HDR=2: on any screen), and the game asks every frame, so its window follows the screen; the iOS in-game menu turns it on and off while the game runs. The paper white (DM_HDR_PAPER_WHITE, the HDR paper white row) is 100 nits by default, the screen's own white: macOS shows a PQ layer at EDR = nits / 100, measured with an extended-range screen capture, so the game's normal picture matches SDR and the headroom is left to its highlights (by eye, Mario Kart World at 100 had SDR's base brightness with brighter highlights; at 203 the whole picture was brighter). - The peak (DM_HDR_PEAK, the HDR peak row) is automatic by default: 100 nits times the screen's current headroom (front_hdr_headroom: NSScreen's maximumExtendedDynamicRangeColorComponentValue on the Mac, UIScreen's currentEDRHeadroom on iOS), in steps of about 6 % taken once they have held for a second, at least twice the paper white, so the game tone-maps into what the screen shows. Donkey Kong Bananza and Ocarina of Time declare within the peak they are told, and all three games' pixels stay within it. - No HDR10 metadata on the layer (DM_HDR_META=1 adds it): with metadata above 100 x headroom Core Animation compresses the whole picture, mid-tones included (measured), and Mario Kart World declares about 1.8 times the peak it is told; and in fullscreen a layer with metadata of any range showed rectangles of older frames under GPU load, in the host and in a standalone app with no game, judged by eye without knowing the mode (dm/gfx/tools/hdr_rects.mm), none without. A fixed peak above the screen's is rolled off in the present above three quarters of the screen's held peak (present.metal mode 4), keyed on the smaller of the declared range and the peak told. - present.metal and nvn_mtl.m present_mode: the HDR10 window as it is into the PQ layer, an SDR or float source encoded at the paper white while the status answers HDR and at 100 nits, the screen's SDR white, while it answers SDR (at 203 an SDR screen showed the SDR picture twice as bright and clipped), an HDR frame brought to SDR white with its hue for screenshots and SDR drawables; RGB10A2 windows are PQ only once the status has answered HDR. A PQ layer rather than an extended-range float one, which showed black blocks over flat areas on a MacBook Air M5 while the game's frames were clean. - With metadata in fullscreen (DM_PRESENT_AFTER_GPU), the drawable is handed to the system once its present pass has completed, without signalDrawable, which with the pass completed made frames a refresh late; it costs frames a refresh late when the pass ends close to the refresh, so it is off without metadata and in a window. - dm/gfx/tools/edr_probe.m measures how macOS maps a PQ layer into EDR; dm/gfx/tools/hdr_rects.mm reproduces the rectangles with no game. - t_present_hdr: the status answer, the automatic peak and its hold, the PQ decode and encode, the roll-off's curve, SDR and float sources, screenshots; test_settings: the rows and their per-platform defaults. - Notes: Donkey Kong Bananza, Mario Kart World and Ocarina of Time's HDR windows and what each declares; three reference entries in docs/reference/rendering.md. The PQ layer is beecrepaldi-afk's (#1), the present after the GPU and the standalone app that found the rectangles b1tdr3amer24's (#2), the paper white and peak rows and the automatic peak's front end hook Amost's (#3). Front-ends: new: HDR output for Switch 2 games (DM_HDR, DM_HDR_PAPER_WHITE, DM_HDR_PEAK rows): the front end makes the HDR layer RGB10A2 in kCGColorSpaceITUR_2100_PQ with wantsExtendedDynamicRangeContent (front_mac.m, front_ios.m) Front-ends: new: the HDR output row defaults to on; the host's own default, DM_HDR unset, stays SDR, so a front end that does not pass the row's value starts the game in SDR Front-ends: new: front_hdr_screen() (the window's screen can show EDR) and front_hdr_headroom() (its current EDR headroom) are weak hooks in hle_vi.c; without front_hdr_headroom the automatic peak answers 1000 and nothing is rolled off Front-ends: new: a front end calls dm_hdr_layer_meta_set() with whether it gave the layer HDR10 metadata, and receives the game's declared range through front_hdr_content_range() for that metadata Co-authored-by: beecrepaldi-afk <beecrepaldi@gmail.com> Co-authored-by: b1tdr3amer24 <240231594+b1tdr3amer24@users.noreply.github.com> Co-authored-by: Amost <6445689+Amost-@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
What and why
The calibration follow-up from my test comment on seedds#1176 (seedds#1176 (comment)). The paper white and the peak that the status query answers (
DM_HDR_PAPER_WHITE,DM_HDR_PEAK) had no launcher setting, though they are what a console's HDR calibration sets. Ocarina of Time shows that they matter: it declares min(peak, 3.5 × paper white), so the paper white is what lifts its highlights.level=basic, so the two rows show with it.DM_HDR_PEAK=autoanswers the paper white × the window's screen's current EDR headroom (maximumExtendedDynamicRangeColorComponentValue, read beside the potential headroom the front end already polls four times a second). Rounded to 10 nits, never below the paper white, at most 16 bits, logged when it changes (at most once a second). iOS would needUIScreen.currentEDRHeadroom(not done), so the row offers Automatic on the Mac only.Docs:
docs/settings.md(the two rows),docs/env_switches.tsv(both switches are nowplayer), a bullet in the HDR entry ofdocs/reference/rendering.md, and Ocarina of Time's HDR note.Checked
t_present_hdr34/34, with 7 new checks for the peak (a number;autoat headroom 3.5, 16, 1, 0.5, NaN and 1000;autoon a screen without EDR).test_settings.py5/5, including a new test that the rows are Switch 2 only, sub-settings of HDR output, with Automatic on the Mac only.test_docspasses.test_env_switchesfails only onDM_NVN_BC_ALIASand three switches quoted only in the docs, the same as on ec134cc without this change. The host builds (make -C dm/host GAME=0400486024DEC000 dmhost), and the clang-tidy ratchet on the four changed C/ObjC files is 0 above and 0 below the baseline.regress.pynot run: only the HDR status answer and the settings rows change, and only with HDR output on.Front ends
Front-ends: new:
DM_HDR_PEAK=autoreads the weakfront_hdr_headroom()(the window's screen's current EDR headroom;front_mac.mdefines it). A front end without it answers the paper white forauto.Docs
test_docspasses)This merges cleanly with #2 except in Ocarina of Time's README, where both add a bullet at the end of the HDR output section: keep both. Happy to rebase after #2 lands.
🤖 Generated with Claude Code