1
0
Fork 0
forked from wry/wry

color-management: add more capabilities

This commit is contained in:
Julian Orth 2025-03-02 15:16:07 +01:00
parent e92de36f7a
commit 8f992f7cef
13 changed files with 293 additions and 97 deletions

View file

@ -560,6 +560,10 @@ impl MetalConnector {
}
return None;
};
if ct.cd.id != self.state.color_manager.srgb_srgb().id {
// Direct scanout requires identical color descriptions.
return None;
}
if ct.alpha.is_some() {
// Direct scanout with alpha factor is not supported.
return None;

View file

@ -17,7 +17,6 @@ impl Luminance {
white: F64(80.0),
};
#[expect(dead_code)]
pub const BT1886: Self = Self {
min: F64(0.01),
max: F64(100.0),

View file

@ -100,12 +100,10 @@ impl ColorManager {
&self.srgb_linear
}
#[expect(dead_code)]
pub fn windows_scrgb(&self) -> &Rc<ColorDescription> {
&self.windows_scrgb
}
#[expect(dead_code)]
pub fn get_description(
self: &Rc<Self>,
named_primaries: Option<NamedPrimaries>,

View file

@ -3,23 +3,14 @@ use {crate::utils::ordered_float::F64, std::hash::Hash};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum NamedPrimaries {
Srgb,
#[expect(dead_code)]
PalM,
#[expect(dead_code)]
Pal,
#[expect(dead_code)]
Ntsc,
#[expect(dead_code)]
GenericFilm,
#[expect(dead_code)]
Bt2020,
#[expect(dead_code)]
Cie1931Xyz,
#[expect(dead_code)]
DciP3,
#[expect(dead_code)]
DisplayP3,
#[expect(dead_code)]
AdobeRgb,
}
@ -103,7 +94,6 @@ impl Primaries {
};
}
impl NamedPrimaries {
#[expect(dead_code)]
pub const fn primaries(self) -> Primaries {
match self {
NamedPrimaries::Srgb => Primaries::SRGB,

View file

@ -1,56 +1,63 @@
pub use consts::*;
pub mod wp_color_management_output_v1;
pub mod wp_color_management_surface_feedback_v1;
pub mod wp_color_management_surface_v1;
pub mod wp_color_manager_v1;
pub mod wp_image_description_creator_icc_v1;
pub mod wp_image_description_creator_params_v1;
pub mod wp_image_description_info_v1;
pub mod wp_image_description_v1;
const PRIMARIES_MUL: f64 = 1_000_000.0;
const PRIMARIES_MUL_INV: f64 = 1.0 / PRIMARIES_MUL;
const MIN_LUM_MUL: f64 = 10_000.0;
const MIN_LUM_MUL_INV: f64 = 1.0 / MIN_LUM_MUL;
#[expect(dead_code)]
mod consts {
pub(super) const RENDER_INTENT_PERCEPTUAL: u32 = 0;
pub(super) const RENDER_INTENT_RELATIVE: u32 = 1;
pub(super) const RENDER_INTENT_SATURATION: u32 = 2;
pub(super) const RENDER_INTENT_ABSOLUTE: u32 = 3;
pub(super) const RENDER_INTENT_RELATIVE_BPC: u32 = 4;
pub const RENDER_INTENT_PERCEPTUAL: u32 = 0;
pub const RENDER_INTENT_RELATIVE: u32 = 1;
pub const RENDER_INTENT_SATURATION: u32 = 2;
pub const RENDER_INTENT_ABSOLUTE: u32 = 3;
pub const RENDER_INTENT_RELATIVE_BPC: u32 = 4;
pub(super) const FEATURE_ICC_V2_V4: u32 = 0;
pub(super) const FEATURE_PARAMETRIC: u32 = 1;
pub(super) const FEATURE_SET_PRIMARIES: u32 = 2;
pub(super) const FEATURE_SET_TF_POWER: u32 = 3;
pub(super) const FEATURE_SET_LUMINANCES: u32 = 4;
pub(super) const FEATURE_SET_MASTERING_DISPLAY_PRIMARIES: u32 = 5;
pub(super) const FEATURE_EXTENDED_TARGET_VOLUME: u32 = 6;
pub(super) const FEATURE_WINDOWS_SCRGB: u32 = 7;
pub const FEATURE_ICC_V2_V4: u32 = 0;
pub const FEATURE_PARAMETRIC: u32 = 1;
pub const FEATURE_SET_PRIMARIES: u32 = 2;
pub const FEATURE_SET_TF_POWER: u32 = 3;
pub const FEATURE_SET_LUMINANCES: u32 = 4;
pub const FEATURE_SET_MASTERING_DISPLAY_PRIMARIES: u32 = 5;
pub const FEATURE_EXTENDED_TARGET_VOLUME: u32 = 6;
pub const FEATURE_WINDOWS_SCRGB: u32 = 7;
pub(super) const PRIMARIES_SRGB: u32 = 1;
pub(super) const PRIMARIES_PAL_M: u32 = 2;
pub(super) const PRIMARIES_PAL: u32 = 3;
pub(super) const PRIMARIES_NTSC: u32 = 4;
pub(super) const PRIMARIES_GENERIC_FILM: u32 = 5;
pub(super) const PRIMARIES_BT2020: u32 = 6;
pub(super) const PRIMARIES_CIE1931_XYZ: u32 = 7;
pub(super) const PRIMARIES_DCI_P3: u32 = 8;
pub(super) const PRIMARIES_DISPLAY_P3: u32 = 9;
pub(super) const PRIMARIES_ADOBE_RGB: u32 = 10;
pub const PRIMARIES_SRGB: u32 = 1;
pub const PRIMARIES_PAL_M: u32 = 2;
pub const PRIMARIES_PAL: u32 = 3;
pub const PRIMARIES_NTSC: u32 = 4;
pub const PRIMARIES_GENERIC_FILM: u32 = 5;
pub const PRIMARIES_BT2020: u32 = 6;
pub const PRIMARIES_CIE1931_XYZ: u32 = 7;
pub const PRIMARIES_DCI_P3: u32 = 8;
pub const PRIMARIES_DISPLAY_P3: u32 = 9;
pub const PRIMARIES_ADOBE_RGB: u32 = 10;
pub(super) const TRANSFER_FUNCTION_BT1886: u32 = 1;
pub(super) const TRANSFER_FUNCTION_GAMMA22: u32 = 2;
pub(super) const TRANSFER_FUNCTION_GAMMA28: u32 = 3;
pub(super) const TRANSFER_FUNCTION_ST240: u32 = 4;
pub(super) const TRANSFER_FUNCTION_EXT_LINEAR: u32 = 5;
pub(super) const TRANSFER_FUNCTION_LOG_100: u32 = 6;
pub(super) const TRANSFER_FUNCTION_LOG_316: u32 = 7;
pub(super) const TRANSFER_FUNCTION_XVYCC: u32 = 8;
pub(super) const TRANSFER_FUNCTION_SRGB: u32 = 9;
pub(super) const TRANSFER_FUNCTION_EXT_SRGB: u32 = 10;
pub(super) const TRANSFER_FUNCTION_ST2084_PQ: u32 = 11;
pub(super) const TRANSFER_FUNCTION_ST428: u32 = 12;
pub(super) const TRANSFER_FUNCTION_HLG: u32 = 13;
pub const TRANSFER_FUNCTION_BT1886: u32 = 1;
pub const TRANSFER_FUNCTION_GAMMA22: u32 = 2;
pub const TRANSFER_FUNCTION_GAMMA28: u32 = 3;
pub const TRANSFER_FUNCTION_ST240: u32 = 4;
pub const TRANSFER_FUNCTION_EXT_LINEAR: u32 = 5;
pub const TRANSFER_FUNCTION_LOG_100: u32 = 6;
pub const TRANSFER_FUNCTION_LOG_316: u32 = 7;
pub const TRANSFER_FUNCTION_XVYCC: u32 = 8;
pub const TRANSFER_FUNCTION_SRGB: u32 = 9;
pub const TRANSFER_FUNCTION_EXT_SRGB: u32 = 10;
pub const TRANSFER_FUNCTION_ST2084_PQ: u32 = 11;
pub const TRANSFER_FUNCTION_ST428: u32 = 12;
pub const TRANSFER_FUNCTION_HLG: u32 = 13;
pub(super) const CAUSE_LOW_VERSION: u32 = 0;
pub(super) const CAUSE_UNSUPPORTED: u32 = 1;
pub(super) const CAUSE_OPERATING_SYSTEM: u32 = 2;
pub(super) const CAUSE_NO_OUTPUT: u32 = 3;
pub const CAUSE_LOW_VERSION: u32 = 0;
pub const CAUSE_UNSUPPORTED: u32 = 1;
pub const CAUSE_OPERATING_SYSTEM: u32 = 2;
pub const CAUSE_NO_OUTPUT: u32 = 3;
}

View file

@ -43,10 +43,11 @@ impl WpColorManagementOutputV1RequestHandler for WpColorManagementOutputV1 {
client: self.client.clone(),
version: self.version,
tracker: Default::default(),
description: self.client.state.color_manager.srgb_srgb().clone(),
});
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
obj.send_ready(0);
obj.send_ready();
Ok(())
}
}

View file

@ -30,10 +30,11 @@ impl WpColorManagementSurfaceFeedbackV1 {
client: self.client.clone(),
version: self.version,
tracker: Default::default(),
description: self.client.state.color_manager.srgb_srgb().clone(),
});
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
obj.send_ready(0);
obj.send_ready();
Ok(())
}
}

View file

@ -2,15 +2,27 @@ use {
crate::{
client::{Client, ClientError},
globals::{Global, GlobalName},
ifs::color_management::{
consts::{
FEATURE_PARAMETRIC, PRIMARIES_SRGB, RENDER_INTENT_PERCEPTUAL,
TRANSFER_FUNCTION_SRGB,
ifs::{
color_management::{
consts::{
FEATURE_PARAMETRIC, FEATURE_SET_LUMINANCES, FEATURE_SET_PRIMARIES,
FEATURE_WINDOWS_SCRGB, PRIMARIES_ADOBE_RGB, PRIMARIES_BT2020,
PRIMARIES_CIE1931_XYZ, PRIMARIES_DCI_P3, PRIMARIES_DISPLAY_P3,
PRIMARIES_GENERIC_FILM, PRIMARIES_NTSC, PRIMARIES_PAL, PRIMARIES_PAL_M,
PRIMARIES_SRGB, RENDER_INTENT_PERCEPTUAL, TRANSFER_FUNCTION_BT1886,
TRANSFER_FUNCTION_EXT_LINEAR, TRANSFER_FUNCTION_EXT_SRGB,
TRANSFER_FUNCTION_GAMMA22, TRANSFER_FUNCTION_GAMMA28,
TRANSFER_FUNCTION_LOG_100, TRANSFER_FUNCTION_LOG_316, TRANSFER_FUNCTION_SRGB,
TRANSFER_FUNCTION_ST240, TRANSFER_FUNCTION_ST428, TRANSFER_FUNCTION_ST2084_PQ,
},
wp_color_management_output_v1::WpColorManagementOutputV1,
wp_color_management_surface_feedback_v1::WpColorManagementSurfaceFeedbackV1,
wp_image_description_creator_params_v1::WpImageDescriptionCreatorParamsV1,
wp_image_description_v1::WpImageDescriptionV1,
},
wl_surface::wp_color_management_surface_v1::{
WpColorManagementSurfaceV1, WpColorManagementSurfaceV1Error,
},
wp_color_management_output_v1::WpColorManagementOutputV1,
wp_color_management_surface_feedback_v1::WpColorManagementSurfaceFeedbackV1,
wp_color_management_surface_v1::WpColorManagementSurfaceV1,
wp_image_description_creator_params_v1::WpImageDescriptionCreatorParamsV1,
},
leaks::Tracker,
object::{Object, Version},
@ -63,8 +75,30 @@ impl WpColorManagerV1 {
fn send_capabilities(&self) {
self.send_supported_intent(RENDER_INTENT_PERCEPTUAL);
self.send_supported_feature(FEATURE_PARAMETRIC);
self.send_supported_feature(FEATURE_SET_PRIMARIES);
self.send_supported_feature(FEATURE_SET_LUMINANCES);
self.send_supported_feature(FEATURE_WINDOWS_SCRGB);
self.send_supported_tf_named(TRANSFER_FUNCTION_BT1886);
self.send_supported_tf_named(TRANSFER_FUNCTION_GAMMA22);
self.send_supported_tf_named(TRANSFER_FUNCTION_GAMMA28);
self.send_supported_tf_named(TRANSFER_FUNCTION_ST240);
self.send_supported_tf_named(TRANSFER_FUNCTION_EXT_LINEAR);
self.send_supported_tf_named(TRANSFER_FUNCTION_LOG_100);
self.send_supported_tf_named(TRANSFER_FUNCTION_LOG_316);
self.send_supported_tf_named(TRANSFER_FUNCTION_SRGB);
self.send_supported_tf_named(TRANSFER_FUNCTION_EXT_SRGB);
self.send_supported_tf_named(TRANSFER_FUNCTION_ST2084_PQ);
self.send_supported_tf_named(TRANSFER_FUNCTION_ST428);
self.send_supported_primaries_named(PRIMARIES_SRGB);
self.send_supported_primaries_named(PRIMARIES_PAL_M);
self.send_supported_primaries_named(PRIMARIES_PAL);
self.send_supported_primaries_named(PRIMARIES_NTSC);
self.send_supported_primaries_named(PRIMARIES_GENERIC_FILM);
self.send_supported_primaries_named(PRIMARIES_BT2020);
self.send_supported_primaries_named(PRIMARIES_CIE1931_XYZ);
self.send_supported_primaries_named(PRIMARIES_DCI_P3);
self.send_supported_primaries_named(PRIMARIES_DISPLAY_P3);
self.send_supported_primaries_named(PRIMARIES_ADOBE_RGB);
self.send_done();
}
@ -123,15 +157,17 @@ impl WpColorManagerV1RequestHandler for WpColorManagerV1 {
}
fn get_surface(&self, req: GetSurface, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let _ = self.client.lookup(req.surface)?;
let surface = self.client.lookup(req.surface)?;
let obj = Rc::new(WpColorManagementSurfaceV1 {
id: req.id,
client: self.client.clone(),
version: self.version,
tracker: Default::default(),
surface: surface.clone(),
});
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
obj.install()?;
Ok(())
}
@ -170,6 +206,9 @@ impl WpColorManagerV1RequestHandler for WpColorManagerV1 {
client: self.client.clone(),
version: self.version,
tracker: Default::default(),
tf: Default::default(),
primaries: Default::default(),
luminance: Default::default(),
});
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
@ -178,10 +217,20 @@ impl WpColorManagerV1RequestHandler for WpColorManagerV1 {
fn create_windows_scrgb(
&self,
_req: CreateWindowsScrgb,
req: CreateWindowsScrgb,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
Err(WpColorManagerV1Error::CreateWindowsScrgbNotSupported)
let obj = Rc::new(WpImageDescriptionV1 {
id: req.image_description,
client: self.client.clone(),
version: self.version,
tracker: Default::default(),
description: self.client.state.color_manager.windows_scrgb().clone(),
});
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
obj.send_ready();
Ok(())
}
}
@ -222,7 +271,7 @@ pub enum WpColorManagerV1Error {
ClientError(Box<ClientError>),
#[error("create_icc_creator is not supported")]
CreateIccCreatorNotSupported,
#[error("create_windows_scrgb is not supported")]
CreateWindowsScrgbNotSupported,
#[error(transparent)]
Surface(#[from] WpColorManagementSurfaceV1Error),
}
efrom!(WpColorManagerV1Error, ClientError);

View file

@ -1,12 +1,27 @@
use {
crate::{
client::{Client, ClientError},
cmm::{
cmm_luminance::Luminance,
cmm_primaries::{NamedPrimaries, Primaries},
cmm_transfer_function::TransferFunction,
},
ifs::color_management::{
consts::{PRIMARIES_SRGB, TRANSFER_FUNCTION_SRGB},
MIN_LUM_MUL_INV, PRIMARIES_MUL_INV,
consts::{
PRIMARIES_ADOBE_RGB, PRIMARIES_BT2020, PRIMARIES_CIE1931_XYZ, PRIMARIES_DCI_P3,
PRIMARIES_DISPLAY_P3, PRIMARIES_GENERIC_FILM, PRIMARIES_NTSC, PRIMARIES_PAL,
PRIMARIES_PAL_M, PRIMARIES_SRGB, TRANSFER_FUNCTION_BT1886,
TRANSFER_FUNCTION_EXT_LINEAR, TRANSFER_FUNCTION_EXT_SRGB,
TRANSFER_FUNCTION_GAMMA22, TRANSFER_FUNCTION_GAMMA28, TRANSFER_FUNCTION_LOG_100,
TRANSFER_FUNCTION_LOG_316, TRANSFER_FUNCTION_SRGB, TRANSFER_FUNCTION_ST240,
TRANSFER_FUNCTION_ST428, TRANSFER_FUNCTION_ST2084_PQ,
},
wp_image_description_v1::WpImageDescriptionV1,
},
leaks::Tracker,
object::{Object, Version},
utils::ordered_float::F64,
wire::{
WpImageDescriptionCreatorParamsV1Id,
wp_image_description_creator_params_v1::{
@ -16,7 +31,7 @@ use {
},
},
},
std::rc::Rc,
std::{cell::Cell, rc::Rc},
thiserror::Error,
};
@ -25,30 +40,74 @@ pub struct WpImageDescriptionCreatorParamsV1 {
pub client: Rc<Client>,
pub version: Version,
pub tracker: Tracker<Self>,
pub tf: Cell<Option<TransferFunction>>,
pub primaries: Cell<Option<(Option<NamedPrimaries>, Primaries)>>,
pub luminance: Cell<Option<Luminance>>,
}
impl WpImageDescriptionCreatorParamsV1RequestHandler for WpImageDescriptionCreatorParamsV1 {
type Error = WpImageDescriptionCreatorParamsV1Error;
fn create(&self, req: Create, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let Some(transfer_function) = self.tf.get() else {
return Err(WpImageDescriptionCreatorParamsV1Error::TfNotSet);
};
let Some((named_primaries, primaries)) = self.primaries.get() else {
return Err(WpImageDescriptionCreatorParamsV1Error::PrimariesNotSet);
};
let default_luminance = match transfer_function {
TransferFunction::Bt1886 => Luminance::BT1886,
TransferFunction::St2084Pq => Luminance::ST2084_PQ,
_ => Luminance::SRGB,
};
let mut luminance = self.luminance.get().unwrap_or(default_luminance);
if transfer_function == TransferFunction::St2084Pq {
luminance.max.0 = luminance.min.0 + 10_000.0;
}
if luminance.max.0 <= luminance.min.0 || luminance.white.0 <= luminance.min.0 {
return Err(WpImageDescriptionCreatorParamsV1Error::MinLuminanceTooLow);
}
let description = self.client.state.color_manager.get_description(
named_primaries,
primaries,
luminance,
transfer_function,
);
let obj = Rc::new(WpImageDescriptionV1 {
id: req.image_description,
client: self.client.clone(),
version: self.version,
tracker: Default::default(),
description,
});
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
obj.send_ready(0);
obj.send_ready();
self.client.remove_obj(self)?;
Ok(())
}
fn set_tf_named(&self, req: SetTfNamed, _slf: &Rc<Self>) -> Result<(), Self::Error> {
if req.tf != TRANSFER_FUNCTION_SRGB {
return Err(WpImageDescriptionCreatorParamsV1Error::UnsupportedTf(
req.tf,
));
let tf = match req.tf {
TRANSFER_FUNCTION_BT1886 => TransferFunction::Bt1886,
TRANSFER_FUNCTION_GAMMA22 => TransferFunction::Gamma22,
TRANSFER_FUNCTION_GAMMA28 => TransferFunction::Gamma28,
TRANSFER_FUNCTION_ST240 => TransferFunction::St240,
TRANSFER_FUNCTION_EXT_LINEAR => TransferFunction::Linear,
TRANSFER_FUNCTION_LOG_100 => TransferFunction::Log100,
TRANSFER_FUNCTION_LOG_316 => TransferFunction::Log316,
TRANSFER_FUNCTION_SRGB => TransferFunction::Srgb,
TRANSFER_FUNCTION_EXT_SRGB => TransferFunction::ExtSrgb,
TRANSFER_FUNCTION_ST2084_PQ => TransferFunction::St2084Pq,
TRANSFER_FUNCTION_ST428 => TransferFunction::St428,
_ => {
return Err(WpImageDescriptionCreatorParamsV1Error::UnsupportedTf(
req.tf,
));
}
};
if self.tf.replace(Some(tf)).is_some() {
return Err(WpImageDescriptionCreatorParamsV1Error::TfAlreadySet);
}
Ok(())
}
@ -62,20 +121,55 @@ impl WpImageDescriptionCreatorParamsV1RequestHandler for WpImageDescriptionCreat
req: SetPrimariesNamed,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
if req.primaries != PRIMARIES_SRGB {
return Err(
WpImageDescriptionCreatorParamsV1Error::UnsupportedPrimaries(req.primaries),
);
let primaries = match req.primaries {
PRIMARIES_SRGB => NamedPrimaries::Srgb,
PRIMARIES_PAL_M => NamedPrimaries::PalM,
PRIMARIES_PAL => NamedPrimaries::Pal,
PRIMARIES_NTSC => NamedPrimaries::Ntsc,
PRIMARIES_GENERIC_FILM => NamedPrimaries::GenericFilm,
PRIMARIES_BT2020 => NamedPrimaries::Bt2020,
PRIMARIES_CIE1931_XYZ => NamedPrimaries::Cie1931Xyz,
PRIMARIES_DCI_P3 => NamedPrimaries::DciP3,
PRIMARIES_DISPLAY_P3 => NamedPrimaries::DisplayP3,
PRIMARIES_ADOBE_RGB => NamedPrimaries::AdobeRgb,
_ => {
return Err(
WpImageDescriptionCreatorParamsV1Error::UnsupportedPrimaries(req.primaries),
);
}
};
let primaries = (Some(primaries), primaries.primaries());
if self.primaries.replace(Some(primaries)).is_some() {
return Err(WpImageDescriptionCreatorParamsV1Error::PrimariesAlreadySet);
}
Ok(())
}
fn set_primaries(&self, _req: SetPrimaries, _slf: &Rc<Self>) -> Result<(), Self::Error> {
Err(WpImageDescriptionCreatorParamsV1Error::SetPrimariesNotSupported)
fn set_primaries(&self, req: SetPrimaries, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let map = |n: i32| F64(n as f64 * PRIMARIES_MUL_INV);
let primaries = Primaries {
r: (map(req.r_x), map(req.r_y)),
g: (map(req.g_x), map(req.g_y)),
b: (map(req.b_x), map(req.b_y)),
wp: (map(req.w_x), map(req.w_y)),
};
let primaries = (None, primaries);
if self.primaries.replace(Some(primaries)).is_some() {
return Err(WpImageDescriptionCreatorParamsV1Error::PrimariesAlreadySet);
}
Ok(())
}
fn set_luminances(&self, _req: SetLuminances, _slf: &Rc<Self>) -> Result<(), Self::Error> {
Err(WpImageDescriptionCreatorParamsV1Error::SetLuminancesNotSupported)
fn set_luminances(&self, req: SetLuminances, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let luminance = Luminance {
min: F64(req.min_lum as f64 * MIN_LUM_MUL_INV),
max: F64(req.max_lum as f64),
white: F64(req.reference_lum as f64),
};
if self.luminance.replace(Some(luminance)).is_some() {
return Err(WpImageDescriptionCreatorParamsV1Error::LuminancesAlreadySet);
}
Ok(())
}
fn set_mastering_display_primaries(
@ -120,15 +214,23 @@ pub enum WpImageDescriptionCreatorParamsV1Error {
SetMasteringLuminanceNotSupported,
#[error("set_mastering_display_primaries is not supported")]
SetMasteringDisplayPrimariesNotSupported,
#[error("set_luminances is not supported")]
SetLuminancesNotSupported,
#[error("set_primaries is not supported")]
SetPrimariesNotSupported,
#[error("{} is not a supported named primary", .0)]
UnsupportedPrimaries(u32),
#[error("set_tf_power is not supported")]
SetTfPowerNotSupported,
#[error("{} is not a supported named transfer function", .0)]
UnsupportedTf(u32),
#[error("The transfer function has already been set")]
TfAlreadySet,
#[error("The primaries have already been set")]
PrimariesAlreadySet,
#[error("The luminances have already been set")]
LuminancesAlreadySet,
#[error("The minimum luminance is too low")]
MinLuminanceTooLow,
#[error("The transfer function was not set")]
TfNotSet,
#[error("The primaries were not set")]
PrimariesNotSet,
}
efrom!(WpImageDescriptionCreatorParamsV1Error, ClientError);

View file

@ -1,6 +1,7 @@
use {
crate::{
client::{Client, ClientError},
cmm::cmm_description::ColorDescription,
ifs::color_management::wp_image_description_info_v1::WpImageDescriptionInfoV1,
leaks::Tracker,
object::{Object, Version},
@ -15,6 +16,7 @@ pub struct WpImageDescriptionV1 {
pub client: Rc<Client>,
pub version: Version,
pub tracker: Tracker<Self>,
pub description: Rc<ColorDescription>,
}
impl WpImageDescriptionV1 {
@ -27,10 +29,10 @@ impl WpImageDescriptionV1 {
});
}
pub fn send_ready(&self, identity: u32) {
pub fn send_ready(&self) {
self.client.event(Ready {
self_id: self.id,
identity,
identity: self.description.id.into(),
});
}
}

View file

@ -5,6 +5,7 @@ pub mod ext_session_lock_surface_v1;
pub mod tray;
pub mod wl_subsurface;
pub mod wp_alpha_modifier_surface_v1;
pub mod wp_color_management_surface_v1;
pub mod wp_commit_timer_v1;
pub mod wp_fifo_v1;
pub mod wp_fractional_scale_v1;
@ -22,6 +23,7 @@ use {
crate::{
backend::KeyState,
client::{Client, ClientError},
cmm::cmm_description::ColorDescription,
cursor_user::{CursorUser, CursorUserId},
damage::DamageMatrix,
drm_feedback::DrmFeedback,
@ -104,6 +106,7 @@ use {
rc::{Rc, Weak},
},
thiserror::Error,
wp_color_management_surface_v1::WpColorManagementSurfaceV1,
zwp_idle_inhibitor_v1::ZwpIdleInhibitorV1,
};
@ -332,6 +335,8 @@ pub struct WlSurface {
commit_timer: CloneCell<Option<Rc<WpCommitTimerV1>>>,
before_latch_listener: EventListener<dyn BeforeLatchListener>,
is_opaque: Cell<bool>,
color_management_surface: CloneCell<Option<Rc<WpColorManagementSurfaceV1>>>,
color_description: CloneCell<Option<Rc<ColorDescription>>>,
}
impl Debug for WlSurface {
@ -461,6 +466,7 @@ struct PendingState {
fifo_barrier_wait: bool,
commit_time: Option<u64>,
tray_item_ack_serial: Option<u32>,
color_description: Option<Option<Rc<ColorDescription>>>,
}
struct AttachedSubsurfaceState {
@ -513,6 +519,7 @@ impl PendingState {
opt!(alpha_multiplier);
opt!(commit_time);
opt!(tray_item_ack_serial);
opt!(color_description);
{
let (dx1, dy1) = self.offset;
let (dx2, dy2) = mem::take(&mut next.offset);
@ -670,6 +677,8 @@ impl WlSurface {
commit_timer: Default::default(),
before_latch_listener: EventListener::new(slf.clone()),
is_opaque: Cell::new(false),
color_management_surface: Default::default(),
color_description: Default::default(),
}
}
@ -1137,6 +1146,11 @@ impl WlSurface {
}
}
}
let mut color_description_changed = false;
if let Some(desc) = pending.color_description.take() {
color_description_changed = true;
self.color_description.set(desc);
}
let mut alpha_changed = false;
if let Some(alpha) = pending.alpha_multiplier.take() {
alpha_changed = true;
@ -1144,8 +1158,11 @@ impl WlSurface {
}
let buffer_abs_pos = self.buffer_abs_pos.get();
let mut max_surface_size = buffer_abs_pos.size();
let mut damage_full =
scale_changed || buffer_transform_changed || viewport_changed || alpha_changed;
let mut damage_full = scale_changed
|| buffer_transform_changed
|| viewport_changed
|| alpha_changed
|| color_description_changed;
let mut buffer_changed = false;
let mut old_raw_size = None;
let (mut dx, mut dy) = mem::take(&mut pending.offset);
@ -1658,6 +1675,13 @@ impl WlSurface {
pub fn opaque_region(&self) -> Option<Rc<Region>> {
self.opaque_region.get()
}
pub fn color_description(&self) -> Rc<ColorDescription> {
match self.color_description.get() {
Some(cd) => cd,
None => self.client.state.color_manager.srgb_srgb().clone(),
}
}
}
object_base! {
@ -1689,6 +1713,7 @@ impl Object for WlSurface {
self.text_input_connections.clear();
self.fifo.take();
self.commit_timer.take();
self.color_management_surface.take();
}
}

View file

@ -1,7 +1,7 @@
use {
crate::{
client::{Client, ClientError},
ifs::color_management::consts::RENDER_INTENT_PERCEPTUAL,
ifs::{color_management, wl_surface::WlSurface},
leaks::Tracker,
object::{Object, Version},
wire::{
@ -21,12 +21,26 @@ pub struct WpColorManagementSurfaceV1 {
pub client: Rc<Client>,
pub version: Version,
pub tracker: Tracker<Self>,
pub surface: Rc<WlSurface>,
}
impl WpColorManagementSurfaceV1 {
pub fn install(self: &Rc<Self>) -> Result<(), WpColorManagementSurfaceV1Error> {
if self.surface.color_management_surface.is_some() {
return Err(WpColorManagementSurfaceV1Error::HasSurface);
}
self.surface
.color_management_surface
.set(Some(self.clone()));
Ok(())
}
}
impl WpColorManagementSurfaceV1RequestHandler for WpColorManagementSurfaceV1 {
type Error = WpColorManagementSurfaceV1Error;
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.surface.color_management_surface.take();
self.client.remove_obj(self)?;
Ok(())
}
@ -36,12 +50,13 @@ impl WpColorManagementSurfaceV1RequestHandler for WpColorManagementSurfaceV1 {
req: SetImageDescription,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
let _ = self.client.lookup(req.image_description)?;
if req.render_intent != RENDER_INTENT_PERCEPTUAL {
if req.render_intent != color_management::RENDER_INTENT_PERCEPTUAL {
return Err(WpColorManagementSurfaceV1Error::UnsupportedRenderIntent(
req.render_intent,
));
}
let desc = self.client.lookup(req.image_description)?;
self.surface.pending.borrow_mut().color_description = Some(Some(desc.description.clone()));
Ok(())
}
@ -50,6 +65,7 @@ impl WpColorManagementSurfaceV1RequestHandler for WpColorManagementSurfaceV1 {
_req: UnsetImageDescription,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
self.surface.pending.borrow_mut().color_description = Some(None);
Ok(())
}
}
@ -69,5 +85,7 @@ pub enum WpColorManagementSurfaceV1Error {
ClientError(Box<ClientError>),
#[error("{} is not a supported render intent", .0)]
UnsupportedRenderIntent(u32),
#[error("wl_surface already has a color-management extension")]
HasSurface,
}
efrom!(WpColorManagementSurfaceV1Error, ClientError);

View file

@ -444,7 +444,7 @@ impl Renderer<'_> {
bounds: Option<&Rect>,
) {
let alpha = surface.alpha();
let cd = self.state.color_manager.srgb_srgb();
let cd = surface.color_description();
if let Some(tex) = buffer.buffer.get_texture(surface) {
let mut opaque = surface.opaque();
if !opaque && tex.format().has_alpha {
@ -463,7 +463,7 @@ impl Renderer<'_> {
AcquireSync::Unnecessary,
buffer.release_sync,
opaque,
cd,
&cd,
);
} else if let Some(color) = &buffer.buffer.color {
if let Some(rect) = Rect::new_sized(x, y, tsize.0, tsize.1) {