PrismCore / API reference / Display
Enumeration
DisplayCriteriaLogic
enum DisplayCriteriaLogicDeclared in Sources/PrismCore/Display/DisplayCriteriaController.swift · PrismCore 3.5.4
The pure decisions DisplayCriteriaController acts on, split out so they compile — and test — on every platform, while the controller itself only exists where AVDisplayManager does (tvOS).
Type methods
static func writeIsRedundant(previous: WrittenCriteria?, next: WrittenCriteria) -> BoolSkip the write when the previously-written criteria are still active and identical. previous is nil after a reset (or before the first write), and then the write always happens.
static func panelPresentsHDR(headroomIsRaised: Bool, wroteHDRCriteria: Bool, panelHasProvenHDR: Bool) -> BoolWill the panel present this session in HDR?
UIScreen.currentEDRHeadroom is not a readout of the panel's HDMI mode — it rises around a dynamic-range transition and decays back to 1.0 while the panel keeps presenting HDR. So a raised headroom is trusted as a positive, and its absence is answered by history: once a criteria write has demonstrably driven this display into HDR, an HDR write that ended quietly means "already there", not "refused". A panel that never proved itself (Match Dynamic Range off, genuinely SDR display) keeps the conservative answer and is never offered a PQ master it would reject.
static func settleBounds(wantsHDRPanel: Bool) -> (startGrace: Duration, settleCap: Duration)How long waitForSwitch may spend on each stage, by what the last write asked of the panel.
A dynamic-range switch is a real HDMI renegotiation — HDCP re-auth, mode engage, often through an AVR — and on living-room chains it routinely takes 2–5 s to end, and over a second to visibly start. The old flat 1 s + 2 s bounds lost that race often enough to matter: the master loaded against the panel's old mode, tvOS refused the DV claim (-11868), and the rejection fallback silently replayed the title as HDR10 — a different HDMI mode with the TV's other picture preset. One play engaged Dolby Vision, the next didn't, and which one a viewer got was a coin flip (found on an Apple TV 4K driving a real panel, 2026-08-07).
Both waits exit on the first positive signal (mode-switch-end, raised headroom, in-progress flag clearing), so generous caps cost nothing on panels that report their switches; the caps only bind where the switch is genuinely still running or unobservable. Rate-only writes keep the old bounds — a refresh-rate switch has no range claim to lose a race for, and stretching every SDR load would be pure dead time.
Structure
DisplayCriteriaLogic.SettleReport
struct SettleReportWhat one waitForSwitch actually did, with real elapsed times — the telemetry that turns settle budgets from bets into measurements.
The elapsed fields are wall-clock readings, deliberately not derived from tick counts times tick length: a budget-derived number reports the budget, and a settle that exits early then looks exactly like one that ran to its cap. Hosts are expected to log summary (Aether's Log screen shows it under its prismcore category), so slow chains show their real handshake times and the bounds in settleBounds(wantsHDRPanel:) can be tuned from evidence.
Initializers
init(outcome: Outcome, switchStartedAfterMilliseconds: Int? = nil, clearedAfterMilliseconds: Int? = nil, totalMilliseconds: Int)No documentation comment in the source.
Instance properties
let switchStartedAfterMilliseconds: Int?When stage 1 saw the switch start; nil when none ever did.
let clearedAfterMilliseconds: Int?When the in-progress flag cleared without an HDR signal; only set for .clearedWithoutHDRSignal.
Enumeration
DisplayCriteriaLogic.SettleReport.Outcome
enum OutcomeNo documentation comment in the source.
Cases
case matchingDisabledMatch Content is fully off — tvOS ignored the write, nothing can switch, nothing was waited for.
case alreadyPresentingHDRAn HDR write met a panel already presenting HDR — no wait.
case noSwitchStartedNothing visibly started within the grace: the panel already satisfied the criteria (or its switch is unobservable).
case inProgressClearedThe in-progress flag cleared without an end notification — terminal only for rate-only writes, where there is no range engage left to confirm.
case clearedWithoutHDRSignalHDR targets only: the in-progress flag cleared, the rest of the cap was spent watching for an HDR signal (end notification, raised headroom), and none came. The clear was ambiguous — a panel that finished quietly looks exactly like one that ABORTED the switch and stayed SDR — so the wait doesn't end on it; but a cap's worth of silence afterwards means the master this session serves may well be about to meet an SDR panel (-11868, and the rejection fallback takes it from there). Found on a panel that takes HDR10 fine when parked there, yet cleared its runtime switch at ~2.9 s with the mode never engaging.
case capExpiredThe settle cap expired with the switch still reporting in-progress — the unobservable-switch case the cap exists for.
Structure
DisplayCriteriaLogic.WrittenCriteria
struct WrittenCriteriaWhat a criteria write asked the panel for, reduced to the fields whose equality means "the panel is already there". Re-writing identical criteria is not a no-op: it starts a redundant HDMI mode switch, and on panels whose Dolby Vision switch is unobservable that redundant switch makes every settle wait run to its cap.
Initializers
init(target: DisplayCriteriaChoice.Target, refreshRate: Float)No documentation comment in the source.
Instance properties
Generated from the public symbols of PrismCore 3.5.4. All types