Ask the platform what colour the screen actually is
FR-DSP-8's acquisition half. `dr_plat::display` surveys the session's
displays and reduces each one's profile to an output space the pipeline
can encode into, stating the mechanism per display server as
FR-PLAT-LIN-2 requires:
- X11 reads the `_ICC_PROFILE` / `_ICC_PROFILE_<n>` root-window
properties, enumerating and numbering the outputs through RandR,
which also yields the rectangles a window move is measured against.
- Wayland binds `wp_color_manager_v1` and asks each `wl_output` for
its image description, accepting either an ICC profile on a file
descriptor or primaries stated as chromaticities.
- Where neither answers, sRGB is assumed and the reason travels with
it as data rather than into a log, so the About page can say which
path the session is on.
A display profile is a measurement of one panel and is none of the four
spaces the pipeline knows. Rather than grow an ICC engine, the profile
is reduced to D50-adapted colorants and matched against the four; a
match that is merely nearest is marked as such and shown as such.
Verified on this machine: mutter 50 advertises the colour-management
global and reports eDP-1 as sRGB, and the same session forced onto X11
enumerates the output through RandR and correctly finds no atom.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,22 @@ pub struct Chromaticities {
|
||||
pub white: [f64; 2],
|
||||
}
|
||||
|
||||
impl Chromaticities {
|
||||
/// This gamut's linear RGB to the ICC profile connection space, row-major.
|
||||
///
|
||||
/// The same three columns [`ColourSpace::to_pcs_xyz`] produces, for a set
|
||||
/// of primaries that is *not* one of the four the pipeline knows. That is
|
||||
/// the only reason this is public: a display's profile describes primaries
|
||||
/// nobody chose, and the only way to ask which of the four it is nearest
|
||||
/// is to put both through the same reduction and compare the numbers
|
||||
/// (see `dr_plat::display`). Comparing raw xy pairs instead would be
|
||||
/// wrong, because a profile's colorants have already been adapted to D50
|
||||
/// and a space's published chromaticities have not.
|
||||
pub fn to_pcs_xyz(&self) -> [f32; 9] {
|
||||
narrow(mul(adaptation(white_xyz(self), PCS_D50), rgb_to_xyz(self)))
|
||||
}
|
||||
}
|
||||
|
||||
/// How a space maps linear light onto the numbers stored in a file.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Transfer {
|
||||
@@ -183,8 +199,7 @@ impl ColourSpace {
|
||||
/// defined at D50 and nowhere else — a profile carrying unadapted D65
|
||||
/// colorants describes a space nobody asked for.
|
||||
pub fn to_pcs_xyz(self) -> [f32; 9] {
|
||||
let c = self.chromaticities();
|
||||
narrow(mul(adaptation(white_xyz(&c), PCS_D50), rgb_to_xyz(&c)))
|
||||
self.chromaticities().to_pcs_xyz()
|
||||
}
|
||||
|
||||
/// The white-point adaptation folded into [`Self::to_pcs_xyz`], row-major.
|
||||
|
||||
Reference in New Issue
Block a user