Merge pull request #839 from mahkoh/jorth/render-intents
Add support for more render intents
This commit is contained in:
commit
c50242562a
17 changed files with 238 additions and 63 deletions
|
|
@ -3,6 +3,7 @@ pub mod cmm_eotf;
|
||||||
pub mod cmm_luminance;
|
pub mod cmm_luminance;
|
||||||
pub mod cmm_manager;
|
pub mod cmm_manager;
|
||||||
pub mod cmm_primaries;
|
pub mod cmm_primaries;
|
||||||
|
pub mod cmm_render_intent;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod cmm_tests;
|
mod cmm_tests;
|
||||||
pub mod cmm_transform;
|
pub mod cmm_transform;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use {
|
||||||
cmm_luminance::{Luminance, TargetLuminance, white_balance},
|
cmm_luminance::{Luminance, TargetLuminance, white_balance},
|
||||||
cmm_manager::Shared,
|
cmm_manager::Shared,
|
||||||
cmm_primaries::{NamedPrimaries, Primaries},
|
cmm_primaries::{NamedPrimaries, Primaries},
|
||||||
|
cmm_render_intent::RenderIntent,
|
||||||
cmm_transform::{ColorMatrix, Local, Xyz, bradford_adjustment},
|
cmm_transform::{ColorMatrix, Local, Xyz, bradford_adjustment},
|
||||||
},
|
},
|
||||||
utils::ordered_float::F64,
|
utils::ordered_float::F64,
|
||||||
|
|
@ -39,12 +40,17 @@ pub struct ColorDescription {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LinearColorDescription {
|
impl LinearColorDescription {
|
||||||
pub fn color_transform(&self, target: &Self) -> ColorMatrix {
|
pub fn color_transform(&self, target: &Self, intent: RenderIntent) -> ColorMatrix {
|
||||||
let mut mat = target.local_from_xyz;
|
let mut mat = target.local_from_xyz;
|
||||||
if self.luminance != target.luminance {
|
if self.luminance != target.luminance {
|
||||||
mat *= white_balance(&self.luminance, &target.luminance, target.primaries.wp);
|
mat *= white_balance(
|
||||||
|
&self.luminance,
|
||||||
|
&target.luminance,
|
||||||
|
target.primaries.wp,
|
||||||
|
intent,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if self.primaries.wp != target.primaries.wp {
|
if self.primaries.wp != target.primaries.wp && intent.bradford_adjustment() {
|
||||||
mat *= bradford_adjustment(self.primaries.wp, target.primaries.wp);
|
mat *= bradford_adjustment(self.primaries.wp, target.primaries.wp);
|
||||||
}
|
}
|
||||||
mat * self.xyz_from_local
|
mat * self.xyz_from_local
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
cmm::cmm_transform::{ColorMatrix, Xyz},
|
cmm::{
|
||||||
|
cmm_render_intent::RenderIntent,
|
||||||
|
cmm_transform::{ColorMatrix, Xyz},
|
||||||
|
},
|
||||||
utils::ordered_float::F64,
|
utils::ordered_float::F64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -68,12 +71,19 @@ impl Default for Luminance {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[expect(non_snake_case)]
|
#[expect(non_snake_case)]
|
||||||
pub fn white_balance(from: &Luminance, to: &Luminance, w_to: (F64, F64)) -> ColorMatrix<Xyz, Xyz> {
|
pub fn white_balance(
|
||||||
|
from: &Luminance,
|
||||||
|
to: &Luminance,
|
||||||
|
w_to: (F64, F64),
|
||||||
|
intent: RenderIntent,
|
||||||
|
) -> ColorMatrix<Xyz, Xyz> {
|
||||||
let a = ((from.max - from.min) / (to.max - to.min) * (to.white - to.min)
|
let a = ((from.max - from.min) / (to.max - to.min) * (to.white - to.min)
|
||||||
/ (from.white - from.min))
|
/ (from.white - from.min))
|
||||||
.0;
|
.0;
|
||||||
// let d = ((from.min - to.min) / (to.max - to.min)).0.max(0.0);
|
let d = match intent.black_point_compensation() {
|
||||||
let d = 0.0;
|
true => 0.0,
|
||||||
|
false => ((from.min - to.min) / (to.max - to.min)).0,
|
||||||
|
};
|
||||||
let s = a - d;
|
let s = a - d;
|
||||||
let (F64(x_to), F64(y_to)) = w_to;
|
let (F64(x_to), F64(y_to)) = w_to;
|
||||||
let X_to = x_to / y_to;
|
let X_to = x_to / y_to;
|
||||||
|
|
|
||||||
49
src/cmm/cmm_render_intent.rs
Normal file
49
src/cmm/cmm_render_intent.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
use crate::{
|
||||||
|
ifs::color_management::{
|
||||||
|
ABSOLUTE_NO_ADAPTATION_SINCE, RENDER_INTENT_ABSOLUTE_NO_ADAPTATION,
|
||||||
|
RENDER_INTENT_PERCEPTUAL, RENDER_INTENT_RELATIVE, RENDER_INTENT_RELATIVE_BPC,
|
||||||
|
},
|
||||||
|
object::Version,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
|
||||||
|
pub enum RenderIntent {
|
||||||
|
#[default]
|
||||||
|
Perceptual,
|
||||||
|
Relative,
|
||||||
|
RelativeBpc,
|
||||||
|
AbsoluteNoAdaptation,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderIntent {
|
||||||
|
pub fn from_wayland(intent: u32, version: Version) -> Option<Self> {
|
||||||
|
let res = match intent {
|
||||||
|
RENDER_INTENT_PERCEPTUAL => Self::Perceptual,
|
||||||
|
RENDER_INTENT_RELATIVE => Self::Relative,
|
||||||
|
RENDER_INTENT_RELATIVE_BPC => Self::RelativeBpc,
|
||||||
|
RENDER_INTENT_ABSOLUTE_NO_ADAPTATION if version >= ABSOLUTE_NO_ADAPTATION_SINCE => {
|
||||||
|
Self::AbsoluteNoAdaptation
|
||||||
|
}
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn black_point_compensation(self) -> bool {
|
||||||
|
match self {
|
||||||
|
RenderIntent::Perceptual => true,
|
||||||
|
RenderIntent::RelativeBpc => true,
|
||||||
|
RenderIntent::Relative => false,
|
||||||
|
RenderIntent::AbsoluteNoAdaptation => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bradford_adjustment(self) -> bool {
|
||||||
|
match self {
|
||||||
|
RenderIntent::Perceptual => true,
|
||||||
|
RenderIntent::RelativeBpc => true,
|
||||||
|
RenderIntent::Relative => true,
|
||||||
|
RenderIntent::AbsoluteNoAdaptation => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -136,7 +136,7 @@ mod matrices {
|
||||||
mod transforms {
|
mod transforms {
|
||||||
use crate::cmm::{
|
use crate::cmm::{
|
||||||
cmm_eotf::Eotf, cmm_luminance::Luminance, cmm_manager::ColorManager,
|
cmm_eotf::Eotf, cmm_luminance::Luminance, cmm_manager::ColorManager,
|
||||||
cmm_primaries::Primaries,
|
cmm_primaries::Primaries, cmm_render_intent::RenderIntent,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn check(p1: Primaries, p2: Primaries, expected: [[f64; 4]; 3]) {
|
fn check(p1: Primaries, p2: Primaries, expected: [[f64; 4]; 3]) {
|
||||||
|
|
@ -155,7 +155,9 @@ mod transforms {
|
||||||
};
|
};
|
||||||
let d1 = d(p1);
|
let d1 = d(p1);
|
||||||
let d2 = d(p2);
|
let d2 = d(p2);
|
||||||
let m = d1.linear.color_transform(&d2.linear);
|
let m = d1
|
||||||
|
.linear
|
||||||
|
.color_transform(&d2.linear, RenderIntent::Perceptual);
|
||||||
println!("{:#?}", m);
|
println!("{:#?}", m);
|
||||||
assert!((m.0[0][0].0 - expected[0][0]).abs() < 0.001);
|
assert!((m.0[0][0].0 - expected[0][0]).abs() < 0.001);
|
||||||
assert!((m.0[0][1].0 - expected[0][1]).abs() < 0.001);
|
assert!((m.0[0][1].0 - expected[0][1]).abs() < 0.001);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
async_engine::AsyncEngine,
|
async_engine::AsyncEngine,
|
||||||
|
cmm::cmm_render_intent::RenderIntent,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
format::ARGB8888,
|
format::ARGB8888,
|
||||||
gfx_api::{AcquireSync, AlphaMode, GfxContext, GfxError, GfxTexture, ReleaseSync},
|
gfx_api::{AcquireSync, AlphaMode, GfxContext, GfxError, GfxTexture, ReleaseSync},
|
||||||
|
|
@ -398,6 +399,7 @@ fn render_img(image: &InstantiatedCursorImage, renderer: &mut Renderer, x: Fixed
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
renderer.state.color_manager.srgb_gamma22(),
|
renderer.state.color_manager.srgb_gamma22(),
|
||||||
|
RenderIntent::Perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -424,6 +426,7 @@ impl Cursor for StaticCursor {
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
renderer.state.color_manager.srgb_gamma22(),
|
renderer.state.color_manager.srgb_gamma22(),
|
||||||
|
RenderIntent::Perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -468,6 +471,7 @@ impl Cursor for AnimatedCursor {
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
renderer.state.color_manager.srgb_gamma22(),
|
renderer.state.color_manager.srgb_gamma22(),
|
||||||
|
RenderIntent::Perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
async_engine::AsyncEngine,
|
async_engine::AsyncEngine,
|
||||||
cmm::cmm_manager::ColorManager,
|
cmm::{cmm_manager::ColorManager, cmm_render_intent::RenderIntent},
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
ifs::wl_output::WlOutputGlobal,
|
ifs::wl_output::WlOutputGlobal,
|
||||||
rect::{Rect, Region},
|
rect::{Rect, Region},
|
||||||
|
|
@ -169,7 +169,14 @@ impl DamageVisualizer {
|
||||||
if region.is_not_empty() {
|
if region.is_not_empty() {
|
||||||
let age = (now - entry.time).as_millis() as u64 as f32 / decay_millis;
|
let age = (now - entry.time).as_millis() as u64 as f32 / decay_millis;
|
||||||
let color = base_color * (1.0 - age);
|
let color = base_color * (1.0 - age);
|
||||||
renderer.fill_boxes2(region.rects(), &color, srgb, dx, dy);
|
renderer.fill_boxes2(
|
||||||
|
region.rects(),
|
||||||
|
&color,
|
||||||
|
srgb,
|
||||||
|
RenderIntent::Perceptual,
|
||||||
|
dx,
|
||||||
|
dy,
|
||||||
|
);
|
||||||
used = used.union_cow(®ion).into_owned();
|
used = used.union_cow(®ion).into_owned();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
allocator::Allocator,
|
allocator::Allocator,
|
||||||
cmm::cmm_description::{ColorDescription, LinearColorDescription},
|
cmm::{
|
||||||
|
cmm_description::{ColorDescription, LinearColorDescription},
|
||||||
|
cmm_render_intent::RenderIntent,
|
||||||
|
},
|
||||||
cpu_worker::CpuWorker,
|
cpu_worker::CpuWorker,
|
||||||
cursor::Cursor,
|
cursor::Cursor,
|
||||||
damage::DamageVisualizer,
|
damage::DamageVisualizer,
|
||||||
|
|
@ -255,6 +258,7 @@ pub struct FillRect {
|
||||||
pub rect: FramebufferRect,
|
pub rect: FramebufferRect,
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
pub alpha: Option<f32>,
|
pub alpha: Option<f32>,
|
||||||
|
pub render_intent: RenderIntent,
|
||||||
pub cd: Rc<LinearColorDescription>,
|
pub cd: Rc<LinearColorDescription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,6 +281,7 @@ pub struct CopyTexture {
|
||||||
pub release_sync: ReleaseSync,
|
pub release_sync: ReleaseSync,
|
||||||
pub alpha: Option<f32>,
|
pub alpha: Option<f32>,
|
||||||
pub opaque: bool,
|
pub opaque: bool,
|
||||||
|
pub render_intent: RenderIntent,
|
||||||
pub cd: Rc<ColorDescription>,
|
pub cd: Rc<ColorDescription>,
|
||||||
pub alpha_mode: AlphaMode,
|
pub alpha_mode: AlphaMode,
|
||||||
}
|
}
|
||||||
|
|
@ -512,6 +517,7 @@ impl dyn GfxFramebuffer {
|
||||||
release_sync,
|
release_sync,
|
||||||
false,
|
false,
|
||||||
texture_cd,
|
texture_cd,
|
||||||
|
RenderIntent::Perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
let clear = self.format().has_alpha.then_some(&Color::TRANSPARENT);
|
let clear = self.format().has_alpha.then_some(&Color::TRANSPARENT);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use {
|
||||||
cmm::{
|
cmm::{
|
||||||
cmm_description::{ColorDescription, LinearColorDescription, LinearColorDescriptionId},
|
cmm_description::{ColorDescription, LinearColorDescription, LinearColorDescriptionId},
|
||||||
cmm_eotf::{Eotf, EotfPow, bt1886_eotf_args, bt1886_inv_eotf_args},
|
cmm_eotf::{Eotf, EotfPow, bt1886_eotf_args, bt1886_inv_eotf_args},
|
||||||
|
cmm_render_intent::RenderIntent,
|
||||||
cmm_transform::ColorMatrix,
|
cmm_transform::ColorMatrix,
|
||||||
},
|
},
|
||||||
cpu_worker::PendingJob,
|
cpu_worker::PendingJob,
|
||||||
|
|
@ -817,9 +818,12 @@ impl VulkanRenderer {
|
||||||
RenderPass::FrameBuffer => fb_cd,
|
RenderPass::FrameBuffer => fb_cd,
|
||||||
};
|
};
|
||||||
let tf = target_cd.eotf;
|
let tf = target_cd.eotf;
|
||||||
let color = memory
|
let color = memory.color_transforms.apply_to_color(
|
||||||
.color_transforms
|
&fr.cd,
|
||||||
.apply_to_color(&fr.cd, target_cd, fr.color);
|
target_cd,
|
||||||
|
fr.render_intent,
|
||||||
|
fr.color,
|
||||||
|
);
|
||||||
let color = color.to_array2(tf, fr.alpha);
|
let color = color.to_array2(tf, fr.alpha);
|
||||||
let source_type = match color[3] < 1.0 {
|
let source_type = match color[3] < 1.0 {
|
||||||
false => TexSourceType::Opaque,
|
false => TexSourceType::Opaque,
|
||||||
|
|
@ -883,6 +887,7 @@ impl VulkanRenderer {
|
||||||
let color_management_data_address = memory.color_transforms.get_offset(
|
let color_management_data_address = memory.color_transforms.get_offset(
|
||||||
&ct.cd.linear,
|
&ct.cd.linear,
|
||||||
target_cd,
|
target_cd,
|
||||||
|
ct.render_intent,
|
||||||
self.device.uniform_buffer_offset_mask,
|
self.device.uniform_buffer_offset_mask,
|
||||||
&mut memory.uniform_buffer_writer,
|
&mut memory.uniform_buffer_writer,
|
||||||
);
|
);
|
||||||
|
|
@ -934,6 +939,7 @@ impl VulkanRenderer {
|
||||||
memory.blend_buffer_color_management_data_address = memory.color_transforms.get_offset(
|
memory.blend_buffer_color_management_data_address = memory.color_transforms.get_offset(
|
||||||
&bb_cd.linear,
|
&bb_cd.linear,
|
||||||
fb_cd,
|
fb_cd,
|
||||||
|
RenderIntent::Perceptual,
|
||||||
self.device.uniform_buffer_offset_mask,
|
self.device.uniform_buffer_offset_mask,
|
||||||
&mut memory.uniform_buffer_writer,
|
&mut memory.uniform_buffer_writer,
|
||||||
);
|
);
|
||||||
|
|
@ -1192,9 +1198,12 @@ impl VulkanRenderer {
|
||||||
if let Some(clear) = clear
|
if let Some(clear) = clear
|
||||||
&& clear_rects.is_not_empty()
|
&& clear_rects.is_not_empty()
|
||||||
{
|
{
|
||||||
let color = memory
|
let color = memory.color_transforms.apply_to_color(
|
||||||
.color_transforms
|
clear_cd,
|
||||||
.apply_to_color(clear_cd, target_cd, *clear);
|
target_cd,
|
||||||
|
RenderIntent::Perceptual,
|
||||||
|
*clear,
|
||||||
|
);
|
||||||
let clear_value = ClearValue {
|
let clear_value = ClearValue {
|
||||||
color: ClearColorValue {
|
color: ClearColorValue {
|
||||||
float32: color.to_array(target_cd.eotf),
|
float32: color.to_array(target_cd.eotf),
|
||||||
|
|
@ -2312,7 +2321,7 @@ where
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ColorTransforms {
|
struct ColorTransforms {
|
||||||
map: AHashMap<[LinearColorDescriptionId; 2], ColorTransform>,
|
map: AHashMap<([LinearColorDescriptionId; 2], RenderIntent), ColorTransform>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ColorTransform {
|
struct ColorTransform {
|
||||||
|
|
@ -2325,14 +2334,15 @@ impl ColorTransforms {
|
||||||
&mut self,
|
&mut self,
|
||||||
src: &LinearColorDescription,
|
src: &LinearColorDescription,
|
||||||
dst: &ColorDescription,
|
dst: &ColorDescription,
|
||||||
|
intent: RenderIntent,
|
||||||
) -> Option<&mut ColorTransform> {
|
) -> Option<&mut ColorTransform> {
|
||||||
if src.embeds_into(&dst.linear) {
|
if src.embeds_into(&dst.linear) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let ct = match self.map.entry([src.id, dst.linear.id]) {
|
let ct = match self.map.entry(([src.id, dst.linear.id], intent)) {
|
||||||
Entry::Occupied(o) => o.into_mut(),
|
Entry::Occupied(o) => o.into_mut(),
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(e) => {
|
||||||
let matrix = src.color_transform(&dst.linear);
|
let matrix = src.color_transform(&dst.linear, intent);
|
||||||
let ct = ColorTransform {
|
let ct = ColorTransform {
|
||||||
matrix,
|
matrix,
|
||||||
offset: None,
|
offset: None,
|
||||||
|
|
@ -2347,9 +2357,10 @@ impl ColorTransforms {
|
||||||
&mut self,
|
&mut self,
|
||||||
src: &LinearColorDescription,
|
src: &LinearColorDescription,
|
||||||
dst: &ColorDescription,
|
dst: &ColorDescription,
|
||||||
|
intent: RenderIntent,
|
||||||
mut color: Color,
|
mut color: Color,
|
||||||
) -> Color {
|
) -> Color {
|
||||||
if let Some(ct) = self.get_or_create(src, dst) {
|
if let Some(ct) = self.get_or_create(src, dst, intent) {
|
||||||
color = ct.matrix * color;
|
color = ct.matrix * color;
|
||||||
};
|
};
|
||||||
color
|
color
|
||||||
|
|
@ -2359,10 +2370,11 @@ impl ColorTransforms {
|
||||||
&mut self,
|
&mut self,
|
||||||
src: &LinearColorDescription,
|
src: &LinearColorDescription,
|
||||||
dst: &ColorDescription,
|
dst: &ColorDescription,
|
||||||
|
intent: RenderIntent,
|
||||||
uniform_buffer_offset_mask: DeviceSize,
|
uniform_buffer_offset_mask: DeviceSize,
|
||||||
writer: &mut GenericBufferWriter,
|
writer: &mut GenericBufferWriter,
|
||||||
) -> Option<DeviceSize> {
|
) -> Option<DeviceSize> {
|
||||||
let ct = self.get_or_create(src, dst)?;
|
let ct = self.get_or_create(src, dst, intent)?;
|
||||||
if ct.offset.is_none() {
|
if ct.offset.is_none() {
|
||||||
let data = ColorManagementData {
|
let data = ColorManagementData {
|
||||||
matrix: ct.matrix.to_f32(),
|
matrix: ct.matrix.to_f32(),
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ pub mod wp_image_description_v1;
|
||||||
const UNIQUE_CM_IDS_SINCE: Version = Version(2);
|
const UNIQUE_CM_IDS_SINCE: Version = Version(2);
|
||||||
const SRGB_DEPRECATED_SINCE: Version = Version(2);
|
const SRGB_DEPRECATED_SINCE: Version = Version(2);
|
||||||
const COMPOUND_POWER_2_4_SINCE: Version = Version(2);
|
const COMPOUND_POWER_2_4_SINCE: Version = Version(2);
|
||||||
|
pub const ABSOLUTE_NO_ADAPTATION_SINCE: Version = Version(2);
|
||||||
|
|
||||||
const PRIMARIES_MUL: f64 = 1_000_000.0;
|
const PRIMARIES_MUL: f64 = 1_000_000.0;
|
||||||
const PRIMARIES_MUL_INV: f64 = 1.0 / PRIMARIES_MUL;
|
const PRIMARIES_MUL_INV: f64 = 1.0 / PRIMARIES_MUL;
|
||||||
|
|
@ -27,6 +28,7 @@ mod consts {
|
||||||
pub const RENDER_INTENT_SATURATION: u32 = 2;
|
pub const RENDER_INTENT_SATURATION: u32 = 2;
|
||||||
pub const RENDER_INTENT_ABSOLUTE: u32 = 3;
|
pub const RENDER_INTENT_ABSOLUTE: u32 = 3;
|
||||||
pub const RENDER_INTENT_RELATIVE_BPC: u32 = 4;
|
pub const RENDER_INTENT_RELATIVE_BPC: u32 = 4;
|
||||||
|
pub const RENDER_INTENT_ABSOLUTE_NO_ADAPTATION: u32 = 5;
|
||||||
|
|
||||||
pub const FEATURE_ICC_V2_V4: u32 = 0;
|
pub const FEATURE_ICC_V2_V4: u32 = 0;
|
||||||
pub const FEATURE_PARAMETRIC: u32 = 1;
|
pub const FEATURE_PARAMETRIC: u32 = 1;
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,11 @@ use {
|
||||||
globals::{Global, GlobalName},
|
globals::{Global, GlobalName},
|
||||||
ifs::{
|
ifs::{
|
||||||
color_management::{
|
color_management::{
|
||||||
COMPOUND_POWER_2_4_SINCE, FEATURE_EXTENDED_TARGET_VOLUME,
|
ABSOLUTE_NO_ADAPTATION_SINCE, COMPOUND_POWER_2_4_SINCE,
|
||||||
FEATURE_SET_MASTERING_DISPLAY_PRIMARIES, FEATURE_SET_TF_POWER,
|
FEATURE_EXTENDED_TARGET_VOLUME, FEATURE_SET_MASTERING_DISPLAY_PRIMARIES,
|
||||||
SRGB_DEPRECATED_SINCE, TRANSFER_FUNCTION_COMPOUND_POWER_2_4,
|
FEATURE_SET_TF_POWER, RENDER_INTENT_ABSOLUTE_NO_ADAPTATION, RENDER_INTENT_RELATIVE,
|
||||||
|
RENDER_INTENT_RELATIVE_BPC, SRGB_DEPRECATED_SINCE,
|
||||||
|
TRANSFER_FUNCTION_COMPOUND_POWER_2_4,
|
||||||
consts::{
|
consts::{
|
||||||
FEATURE_PARAMETRIC, FEATURE_SET_LUMINANCES, FEATURE_SET_PRIMARIES,
|
FEATURE_PARAMETRIC, FEATURE_SET_LUMINANCES, FEATURE_SET_PRIMARIES,
|
||||||
FEATURE_WINDOWS_SCRGB, PRIMARIES_ADOBE_RGB, PRIMARIES_BT2020,
|
FEATURE_WINDOWS_SCRGB, PRIMARIES_ADOBE_RGB, PRIMARIES_BT2020,
|
||||||
|
|
@ -77,6 +79,11 @@ pub struct WpColorManagerV1 {
|
||||||
impl WpColorManagerV1 {
|
impl WpColorManagerV1 {
|
||||||
fn send_capabilities(&self) {
|
fn send_capabilities(&self) {
|
||||||
self.send_supported_intent(RENDER_INTENT_PERCEPTUAL);
|
self.send_supported_intent(RENDER_INTENT_PERCEPTUAL);
|
||||||
|
self.send_supported_intent(RENDER_INTENT_RELATIVE);
|
||||||
|
self.send_supported_intent(RENDER_INTENT_RELATIVE_BPC);
|
||||||
|
if self.version >= ABSOLUTE_NO_ADAPTATION_SINCE {
|
||||||
|
self.send_supported_intent(RENDER_INTENT_ABSOLUTE_NO_ADAPTATION);
|
||||||
|
}
|
||||||
self.send_supported_feature(FEATURE_PARAMETRIC);
|
self.send_supported_feature(FEATURE_PARAMETRIC);
|
||||||
self.send_supported_feature(FEATURE_SET_PRIMARIES);
|
self.send_supported_feature(FEATURE_SET_PRIMARIES);
|
||||||
self.send_supported_feature(FEATURE_SET_LUMINANCES);
|
self.send_supported_feature(FEATURE_SET_LUMINANCES);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
backend::{ButtonState, KeyState},
|
backend::{ButtonState, KeyState},
|
||||||
client::{Client, ClientError},
|
client::{Client, ClientError},
|
||||||
cmm::cmm_description::ColorDescription,
|
cmm::{cmm_description::ColorDescription, cmm_render_intent::RenderIntent},
|
||||||
cursor_user::{CursorUser, CursorUserId},
|
cursor_user::{CursorUser, CursorUserId},
|
||||||
damage::DamageMatrix,
|
damage::DamageMatrix,
|
||||||
drm_feedback::DrmFeedback,
|
drm_feedback::DrmFeedback,
|
||||||
|
|
@ -337,6 +337,7 @@ pub struct WlSurface {
|
||||||
color_management_feedback:
|
color_management_feedback:
|
||||||
CopyHashMap<WpColorManagementSurfaceFeedbackV1Id, Rc<WpColorManagementSurfaceFeedbackV1>>,
|
CopyHashMap<WpColorManagementSurfaceFeedbackV1Id, Rc<WpColorManagementSurfaceFeedbackV1>>,
|
||||||
color_description: CloneCell<Option<Rc<ColorDescription>>>,
|
color_description: CloneCell<Option<Rc<ColorDescription>>>,
|
||||||
|
render_intent: Cell<RenderIntent>,
|
||||||
color_representation_surface: CloneCell<Option<Rc<WpColorRepresentationSurfaceV1>>>,
|
color_representation_surface: CloneCell<Option<Rc<WpColorRepresentationSurfaceV1>>>,
|
||||||
alpha_mode: Cell<AlphaMode>,
|
alpha_mode: Cell<AlphaMode>,
|
||||||
}
|
}
|
||||||
|
|
@ -476,7 +477,7 @@ struct PendingState {
|
||||||
fifo_barrier_wait: bool,
|
fifo_barrier_wait: bool,
|
||||||
commit_time: Option<u64>,
|
commit_time: Option<u64>,
|
||||||
tray_item_ack_serial: Option<u32>,
|
tray_item_ack_serial: Option<u32>,
|
||||||
color_description: Option<Option<Rc<ColorDescription>>>,
|
color_description: Option<Option<(RenderIntent, Rc<ColorDescription>)>>,
|
||||||
serial: Option<u64>,
|
serial: Option<u64>,
|
||||||
alpha_mode: Option<AlphaMode>,
|
alpha_mode: Option<AlphaMode>,
|
||||||
surface_release: SmallVec<[SurfaceRelease; 1]>,
|
surface_release: SmallVec<[SurfaceRelease; 1]>,
|
||||||
|
|
@ -689,6 +690,7 @@ impl WlSurface {
|
||||||
color_management_surface: Default::default(),
|
color_management_surface: Default::default(),
|
||||||
color_management_feedback: Default::default(),
|
color_management_feedback: Default::default(),
|
||||||
color_description: Default::default(),
|
color_description: Default::default(),
|
||||||
|
render_intent: Default::default(),
|
||||||
color_representation_surface: Default::default(),
|
color_representation_surface: Default::default(),
|
||||||
alpha_mode: Default::default(),
|
alpha_mode: Default::default(),
|
||||||
}
|
}
|
||||||
|
|
@ -1210,7 +1212,9 @@ impl WlSurface {
|
||||||
let mut color_description_changed = false;
|
let mut color_description_changed = false;
|
||||||
if let Some(desc) = pending.color_description.take() {
|
if let Some(desc) = pending.color_description.take() {
|
||||||
color_description_changed = true;
|
color_description_changed = true;
|
||||||
|
let (intent, desc) = desc.unzip();
|
||||||
self.color_description.set(desc);
|
self.color_description.set(desc);
|
||||||
|
self.render_intent.set(intent.unwrap_or_default());
|
||||||
}
|
}
|
||||||
let mut alpha_mode_changed = false;
|
let mut alpha_mode_changed = false;
|
||||||
if let Some(alpha_mode) = pending.alpha_mode.take()
|
if let Some(alpha_mode) = pending.alpha_mode.take()
|
||||||
|
|
@ -1756,6 +1760,10 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render_intent(&self) -> RenderIntent {
|
||||||
|
self.render_intent.get()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_color_management_feedback(&self, fb: &Rc<WpColorManagementSurfaceFeedbackV1>) {
|
pub fn add_color_management_feedback(&self, fb: &Rc<WpColorManagementSurfaceFeedbackV1>) {
|
||||||
self.color_management_feedback.set(fb.id, fb.clone());
|
self.color_management_feedback.set(fb.id, fb.clone());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
client::{Client, ClientError},
|
client::{Client, ClientError},
|
||||||
ifs::{color_management, wl_surface::WlSurface},
|
cmm::cmm_render_intent::RenderIntent,
|
||||||
|
ifs::wl_surface::WlSurface,
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
wire::{
|
wire::{
|
||||||
|
|
@ -51,16 +52,16 @@ impl WpColorManagementSurfaceV1RequestHandler for WpColorManagementSurfaceV1 {
|
||||||
req: SetImageDescription,
|
req: SetImageDescription,
|
||||||
_slf: &Rc<Self>,
|
_slf: &Rc<Self>,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
if req.render_intent != color_management::RENDER_INTENT_PERCEPTUAL {
|
let Some(intent) = RenderIntent::from_wayland(req.render_intent, self.version) else {
|
||||||
return Err(WpColorManagementSurfaceV1Error::UnsupportedRenderIntent(
|
return Err(WpColorManagementSurfaceV1Error::UnsupportedRenderIntent(
|
||||||
req.render_intent,
|
req.render_intent,
|
||||||
));
|
));
|
||||||
}
|
};
|
||||||
let desc = self.client.lookup(req.image_description)?;
|
let desc = self.client.lookup(req.image_description)?;
|
||||||
if desc.description.is_none() {
|
let Some(desc) = &desc.description else {
|
||||||
return Err(WpColorManagementSurfaceV1Error::NotReady);
|
return Err(WpColorManagementSurfaceV1Error::NotReady);
|
||||||
}
|
};
|
||||||
self.surface.pending.borrow_mut().color_description = Some(desc.description.clone());
|
self.surface.pending.borrow_mut().color_description = Some(Some((intent, desc.clone())));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
allocator::{BO_USE_RENDERING, BufferObject, BufferUsage},
|
allocator::{BO_USE_RENDERING, BufferObject, BufferUsage},
|
||||||
async_engine::{Phase, SpawnedFuture},
|
async_engine::{Phase, SpawnedFuture},
|
||||||
cmm::cmm_manager::ColorManager,
|
cmm::{cmm_manager::ColorManager, cmm_render_intent::RenderIntent},
|
||||||
cursor::KnownCursor,
|
cursor::KnownCursor,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
format::ARGB8888,
|
format::ARGB8888,
|
||||||
|
|
@ -207,7 +207,12 @@ impl GuiElement for Button {
|
||||||
(x1, y1 + border, x1 + border, y2 - border),
|
(x1, y1 + border, x1 + border, y2 - border),
|
||||||
(x2 - border, y1 + border, x2, y2 - border),
|
(x2 - border, y1 + border, x2, y2 - border),
|
||||||
];
|
];
|
||||||
r.fill_boxes_f(&rects, &self.border_color.get(), srgb);
|
r.fill_boxes_f(
|
||||||
|
&rects,
|
||||||
|
&self.border_color.get(),
|
||||||
|
srgb,
|
||||||
|
RenderIntent::Perceptual,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let rects = [(x1 + border, y1 + border, x2 - border, y2 - border)];
|
let rects = [(x1 + border, y1 + border, x2 - border, y2 - border)];
|
||||||
|
|
@ -215,7 +220,7 @@ impl GuiElement for Button {
|
||||||
true => self.bg_color.get(),
|
true => self.bg_color.get(),
|
||||||
false => self.bg_hover_color.get(),
|
false => self.bg_hover_color.get(),
|
||||||
};
|
};
|
||||||
r.fill_boxes_f(&rects, &color, srgb);
|
r.fill_boxes_f(&rects, &color, srgb, RenderIntent::Perceptual);
|
||||||
}
|
}
|
||||||
if let Some(tex) = self.tex.get() {
|
if let Some(tex) = self.tex.get() {
|
||||||
let (tx, ty) = r.scale_point_f(x1 + self.tex_off_x.get(), y1 + self.tex_off_y.get());
|
let (tx, ty) = r.scale_point_f(x1 + self.tex_off_x.get(), y1 + self.tex_off_y.get());
|
||||||
|
|
@ -233,6 +238,7 @@ impl GuiElement for Button {
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
srgb_srgb,
|
srgb_srgb,
|
||||||
|
RenderIntent::Perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -336,6 +342,7 @@ impl GuiElement for Label {
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
color_manager.srgb_gamma22(),
|
color_manager.srgb_gamma22(),
|
||||||
|
RenderIntent::Perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
|
cmm::cmm_render_intent::RenderIntent,
|
||||||
gfx_api::{AcquireSync, AlphaMode, GfxApiOpt, ReleaseSync, SampleRect},
|
gfx_api::{AcquireSync, AlphaMode, GfxApiOpt, ReleaseSync, SampleRect},
|
||||||
icons::{IconState, SizedIcons},
|
icons::{IconState, SizedIcons},
|
||||||
ifs::wl_surface::{
|
ifs::wl_surface::{
|
||||||
|
|
@ -80,6 +81,7 @@ impl Renderer<'_> {
|
||||||
let theme = &self.state.theme;
|
let theme = &self.state.theme;
|
||||||
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
||||||
let srgb = &srgb_srgb.linear;
|
let srgb = &srgb_srgb.linear;
|
||||||
|
let perceptual = RenderIntent::Perceptual;
|
||||||
if let Some(fs) = &fullscreen {
|
if let Some(fs) = &fullscreen {
|
||||||
fs.node_render(self, x, y, None);
|
fs.node_render(self, x, y, None);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -97,7 +99,7 @@ impl Renderer<'_> {
|
||||||
let bar_bg = self.base.scale_rect(bar_bg);
|
let bar_bg = self.base.scale_rect(bar_bg);
|
||||||
let c = theme.colors.bar_background.get();
|
let c = theme.colors.bar_background.get();
|
||||||
self.base
|
self.base
|
||||||
.fill_scaled_boxes(slice::from_ref(&bar_bg), &c, None, srgb);
|
.fill_scaled_boxes(slice::from_ref(&bar_bg), &c, None, srgb, perceptual);
|
||||||
self.base.sync();
|
self.base.sync();
|
||||||
let rd = output.render_data.borrow_mut();
|
let rd = output.render_data.borrow_mut();
|
||||||
if let Some(aw) = &rd.active_workspace {
|
if let Some(aw) = &rd.active_workspace {
|
||||||
|
|
@ -106,7 +108,7 @@ impl Renderer<'_> {
|
||||||
false => theme.colors.focused_title_background.get(),
|
false => theme.colors.focused_title_background.get(),
|
||||||
};
|
};
|
||||||
self.base
|
self.base
|
||||||
.fill_boxes2(slice::from_ref(&aw.rect), &c, srgb, x, y);
|
.fill_boxes2(slice::from_ref(&aw.rect), &c, srgb, perceptual, x, y);
|
||||||
}
|
}
|
||||||
let mut c = theme.colors.separator.get();
|
let mut c = theme.colors.separator.get();
|
||||||
if let Some(ws) = &ws
|
if let Some(ws) = &ws
|
||||||
|
|
@ -114,18 +116,30 @@ impl Renderer<'_> {
|
||||||
{
|
{
|
||||||
c = theme.colors.focused_title_background.get();
|
c = theme.colors.focused_title_background.get();
|
||||||
}
|
}
|
||||||
self.base
|
self.base.fill_boxes2(
|
||||||
.fill_boxes2(slice::from_ref(&rd.bar_separator), &c, srgb, x, y);
|
slice::from_ref(&rd.bar_separator),
|
||||||
|
&c,
|
||||||
|
srgb,
|
||||||
|
perceptual,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
);
|
||||||
let c = theme.colors.unfocused_title_background.get();
|
let c = theme.colors.unfocused_title_background.get();
|
||||||
self.base
|
self.base
|
||||||
.fill_boxes2(&rd.inactive_workspaces, &c, srgb, x, y);
|
.fill_boxes2(&rd.inactive_workspaces, &c, srgb, perceptual, x, y);
|
||||||
let c = theme.colors.captured_unfocused_title_background.get();
|
let c = theme.colors.captured_unfocused_title_background.get();
|
||||||
self.base
|
self.base
|
||||||
.fill_boxes2(&rd.captured_inactive_workspaces, &c, srgb, x, y);
|
.fill_boxes2(&rd.captured_inactive_workspaces, &c, srgb, perceptual, x, y);
|
||||||
self.base.sync();
|
self.base.sync();
|
||||||
let c = theme.colors.attention_requested_background.get();
|
let c = theme.colors.attention_requested_background.get();
|
||||||
self.base
|
self.base.fill_boxes2(
|
||||||
.fill_boxes2(&rd.attention_requested_workspaces, &c, srgb, x, y);
|
&rd.attention_requested_workspaces,
|
||||||
|
&c,
|
||||||
|
srgb,
|
||||||
|
perceptual,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
);
|
||||||
let scale = output.global.persistent.scale.get();
|
let scale = output.global.persistent.scale.get();
|
||||||
for title in &rd.titles {
|
for title in &rd.titles {
|
||||||
let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y);
|
let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y);
|
||||||
|
|
@ -143,6 +157,7 @@ impl Renderer<'_> {
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
self.state.color_manager.srgb_gamma22(),
|
self.state.color_manager.srgb_gamma22(),
|
||||||
|
perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -166,6 +181,7 @@ impl Renderer<'_> {
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
srgb_srgb,
|
srgb_srgb,
|
||||||
|
perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -210,7 +226,7 @@ impl Renderer<'_> {
|
||||||
let color = self.state.theme.colors.highlight.get();
|
let color = self.state.theme.colors.highlight.get();
|
||||||
let bounds = output.workspace_rect_rel.get().move_(x, y);
|
let bounds = output.workspace_rect_rel.get().move_(x, y);
|
||||||
self.base.sync();
|
self.base.sync();
|
||||||
self.base.fill_boxes(&[bounds], &color, srgb);
|
self.base.fill_boxes(&[bounds], &color, srgb, perceptual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,6 +248,7 @@ impl Renderer<'_> {
|
||||||
std::slice::from_ref(&pos.at_point(x, y)),
|
std::slice::from_ref(&pos.at_point(x, y)),
|
||||||
&Color::from_srgba_straight(20, 20, 20, 255),
|
&Color::from_srgba_straight(20, 20, 20, 255),
|
||||||
&self.state.color_manager.srgb_gamma22().linear,
|
&self.state.color_manager.srgb_gamma22().linear,
|
||||||
|
RenderIntent::Perceptual,
|
||||||
);
|
);
|
||||||
if let Some(tex) = placeholder.textures.borrow().get(&self.base.scale)
|
if let Some(tex) = placeholder.textures.borrow().get(&self.base.scale)
|
||||||
&& let Some(texture) = tex.texture()
|
&& let Some(texture) = tex.texture()
|
||||||
|
|
@ -253,6 +270,7 @@ impl Renderer<'_> {
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
self.state.color_manager.srgb_gamma22(),
|
self.state.color_manager.srgb_gamma22(),
|
||||||
|
RenderIntent::Perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -263,19 +281,23 @@ impl Renderer<'_> {
|
||||||
{
|
{
|
||||||
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
||||||
let srgb = &srgb_srgb.linear;
|
let srgb = &srgb_srgb.linear;
|
||||||
|
let perceptual = RenderIntent::Perceptual;
|
||||||
let rd = container.render_data.borrow_mut();
|
let rd = container.render_data.borrow_mut();
|
||||||
let c = self.state.theme.colors.unfocused_title_background.get();
|
let c = self.state.theme.colors.unfocused_title_background.get();
|
||||||
self.base.fill_boxes2(&rd.title_rects, &c, srgb, x, y);
|
self.base
|
||||||
|
.fill_boxes2(&rd.title_rects, &c, srgb, perceptual, x, y);
|
||||||
let c = self.state.theme.colors.focused_title_background.get();
|
let c = self.state.theme.colors.focused_title_background.get();
|
||||||
self.base
|
self.base
|
||||||
.fill_boxes2(&rd.active_title_rects, &c, srgb, x, y);
|
.fill_boxes2(&rd.active_title_rects, &c, srgb, perceptual, x, y);
|
||||||
let c = self.state.theme.colors.attention_requested_background.get();
|
let c = self.state.theme.colors.attention_requested_background.get();
|
||||||
self.base
|
self.base
|
||||||
.fill_boxes2(&rd.attention_title_rects, &c, srgb, x, y);
|
.fill_boxes2(&rd.attention_title_rects, &c, srgb, perceptual, x, y);
|
||||||
let c = self.state.theme.colors.separator.get();
|
let c = self.state.theme.colors.separator.get();
|
||||||
self.base.fill_boxes2(&rd.underline_rects, &c, srgb, x, y);
|
self.base
|
||||||
|
.fill_boxes2(&rd.underline_rects, &c, srgb, perceptual, x, y);
|
||||||
let c = self.state.theme.colors.border.get();
|
let c = self.state.theme.colors.border.get();
|
||||||
self.base.fill_boxes2(&rd.border_rects, &c, srgb, x, y);
|
self.base
|
||||||
|
.fill_boxes2(&rd.border_rects, &c, srgb, perceptual, x, y);
|
||||||
if let Some(lar) = &rd.last_active_rect {
|
if let Some(lar) = &rd.last_active_rect {
|
||||||
let c = self
|
let c = self
|
||||||
.state
|
.state
|
||||||
|
|
@ -284,7 +306,7 @@ impl Renderer<'_> {
|
||||||
.focused_inactive_title_background
|
.focused_inactive_title_background
|
||||||
.get();
|
.get();
|
||||||
self.base
|
self.base
|
||||||
.fill_boxes2(std::slice::from_ref(lar), &c, srgb, x, y);
|
.fill_boxes2(std::slice::from_ref(lar), &c, srgb, perceptual, x, y);
|
||||||
}
|
}
|
||||||
if let Some(titles) = rd.titles.get(&self.base.scale) {
|
if let Some(titles) = rd.titles.get(&self.base.scale) {
|
||||||
for title in titles {
|
for title in titles {
|
||||||
|
|
@ -305,6 +327,7 @@ impl Renderer<'_> {
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
srgb_srgb,
|
srgb_srgb,
|
||||||
|
perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -382,6 +405,7 @@ impl Renderer<'_> {
|
||||||
&color,
|
&color,
|
||||||
None,
|
None,
|
||||||
&self.state.color_manager.srgb_gamma22().linear,
|
&self.state.color_manager.srgb_gamma22().linear,
|
||||||
|
RenderIntent::Perceptual,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -392,6 +416,7 @@ impl Renderer<'_> {
|
||||||
slice::from_ref(rect),
|
slice::from_ref(rect),
|
||||||
&color,
|
&color,
|
||||||
&self.state.color_manager.srgb_gamma22().linear,
|
&self.state.color_manager.srgb_gamma22().linear,
|
||||||
|
RenderIntent::Perceptual,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -469,6 +494,7 @@ impl Renderer<'_> {
|
||||||
let buf = &buffer.buffer.buf;
|
let buf = &buffer.buffer.buf;
|
||||||
let alpha = surface.alpha();
|
let alpha = surface.alpha();
|
||||||
let cd = surface.color_description();
|
let cd = surface.color_description();
|
||||||
|
let intent = surface.render_intent();
|
||||||
let alpha_mode = surface.alpha_mode();
|
let alpha_mode = surface.alpha_mode();
|
||||||
if let Some(tex) = buf.get_texture(surface) {
|
if let Some(tex) = buf.get_texture(surface) {
|
||||||
let mut opaque = surface.opaque();
|
let mut opaque = surface.opaque();
|
||||||
|
|
@ -489,6 +515,7 @@ impl Renderer<'_> {
|
||||||
buffer.release_sync,
|
buffer.release_sync,
|
||||||
opaque,
|
opaque,
|
||||||
&cd,
|
&cd,
|
||||||
|
intent,
|
||||||
alpha_mode,
|
alpha_mode,
|
||||||
);
|
);
|
||||||
} else if let Some(color) = &buf.color {
|
} else if let Some(color) = &buf.color {
|
||||||
|
|
@ -503,7 +530,7 @@ impl Renderer<'_> {
|
||||||
);
|
);
|
||||||
self.base.sync();
|
self.base.sync();
|
||||||
self.base
|
self.base
|
||||||
.fill_scaled_boxes(&[rect], &color, alpha, &cd.linear);
|
.fill_scaled_boxes(&[rect], &color, alpha, &cd.linear, intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -539,21 +566,23 @@ impl Renderer<'_> {
|
||||||
];
|
];
|
||||||
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
let srgb_srgb = self.state.color_manager.srgb_gamma22();
|
||||||
let srgb = &srgb_srgb.linear;
|
let srgb = &srgb_srgb.linear;
|
||||||
self.base.fill_boxes(&borders, &bc, srgb);
|
let perceptual = RenderIntent::Perceptual;
|
||||||
|
self.base.fill_boxes(&borders, &bc, srgb, perceptual);
|
||||||
let title = [Rect::new_sized_saturating(
|
let title = [Rect::new_sized_saturating(
|
||||||
x + bw,
|
x + bw,
|
||||||
y + bw,
|
y + bw,
|
||||||
pos.width() - 2 * bw,
|
pos.width() - 2 * bw,
|
||||||
th,
|
th,
|
||||||
)];
|
)];
|
||||||
self.base.fill_boxes(&title, &tc, srgb);
|
self.base.fill_boxes(&title, &tc, srgb, perceptual);
|
||||||
let title_underline = [Rect::new_sized_saturating(
|
let title_underline = [Rect::new_sized_saturating(
|
||||||
x + bw,
|
x + bw,
|
||||||
y + bw + th,
|
y + bw + th,
|
||||||
pos.width() - 2 * bw,
|
pos.width() - 2 * bw,
|
||||||
tuh,
|
tuh,
|
||||||
)];
|
)];
|
||||||
self.base.fill_boxes(&title_underline, &uc, srgb);
|
self.base
|
||||||
|
.fill_boxes(&title_underline, &uc, srgb, perceptual);
|
||||||
let rect = floating.title_rect.get().move_(x, y);
|
let rect = floating.title_rect.get().move_(x, y);
|
||||||
let bounds = self.base.scale_rect(rect);
|
let bounds = self.base.scale_rect(rect);
|
||||||
let (mut x1, y1) = rect.position();
|
let (mut x1, y1) = rect.position();
|
||||||
|
|
@ -586,6 +615,7 @@ impl Renderer<'_> {
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
srgb_srgb,
|
srgb_srgb,
|
||||||
|
perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -609,6 +639,7 @@ impl Renderer<'_> {
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
false,
|
false,
|
||||||
srgb_srgb,
|
srgb_srgb,
|
||||||
|
perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
cmm::cmm_description::{ColorDescription, LinearColorDescription},
|
cmm::{
|
||||||
|
cmm_description::{ColorDescription, LinearColorDescription},
|
||||||
|
cmm_render_intent::RenderIntent,
|
||||||
|
},
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AcquireSync, AlphaMode, BufferResv, CopyTexture, FillRect, FramebufferRect, GfxApiOpt,
|
AcquireSync, AlphaMode, BufferResv, CopyTexture, FillRect, FramebufferRect, GfxApiOpt,
|
||||||
GfxTexture, ReleaseSync, SampleRect,
|
GfxTexture, ReleaseSync, SampleRect,
|
||||||
|
|
@ -70,12 +73,19 @@ impl RendererBase<'_> {
|
||||||
color: &Color,
|
color: &Color,
|
||||||
alpha: Option<f32>,
|
alpha: Option<f32>,
|
||||||
cd: &Rc<LinearColorDescription>,
|
cd: &Rc<LinearColorDescription>,
|
||||||
|
render_intent: RenderIntent,
|
||||||
) {
|
) {
|
||||||
self.fill_boxes3(boxes, color, alpha, cd, 0, 0, true);
|
self.fill_boxes3(boxes, color, alpha, cd, render_intent, 0, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_boxes(&mut self, boxes: &[Rect], color: &Color, cd: &Rc<LinearColorDescription>) {
|
pub fn fill_boxes(
|
||||||
self.fill_boxes3(boxes, color, None, cd, 0, 0, false);
|
&mut self,
|
||||||
|
boxes: &[Rect],
|
||||||
|
color: &Color,
|
||||||
|
cd: &Rc<LinearColorDescription>,
|
||||||
|
render_intent: RenderIntent,
|
||||||
|
) {
|
||||||
|
self.fill_boxes3(boxes, color, None, cd, render_intent, 0, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_boxes2(
|
pub fn fill_boxes2(
|
||||||
|
|
@ -83,10 +93,11 @@ impl RendererBase<'_> {
|
||||||
boxes: &[Rect],
|
boxes: &[Rect],
|
||||||
color: &Color,
|
color: &Color,
|
||||||
cd: &Rc<LinearColorDescription>,
|
cd: &Rc<LinearColorDescription>,
|
||||||
|
render_intent: RenderIntent,
|
||||||
dx: i32,
|
dx: i32,
|
||||||
dy: i32,
|
dy: i32,
|
||||||
) {
|
) {
|
||||||
self.fill_boxes3(boxes, color, None, cd, dx, dy, false);
|
self.fill_boxes3(boxes, color, None, cd, render_intent, dx, dy, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_boxes3(
|
fn fill_boxes3(
|
||||||
|
|
@ -95,6 +106,7 @@ impl RendererBase<'_> {
|
||||||
color: &Color,
|
color: &Color,
|
||||||
alpha: Option<f32>,
|
alpha: Option<f32>,
|
||||||
cd: &Rc<LinearColorDescription>,
|
cd: &Rc<LinearColorDescription>,
|
||||||
|
render_intent: RenderIntent,
|
||||||
dx: i32,
|
dx: i32,
|
||||||
dy: i32,
|
dy: i32,
|
||||||
scaled: bool,
|
scaled: bool,
|
||||||
|
|
@ -120,6 +132,7 @@ impl RendererBase<'_> {
|
||||||
),
|
),
|
||||||
color: *color,
|
color: *color,
|
||||||
alpha,
|
alpha,
|
||||||
|
render_intent,
|
||||||
cd: cd.clone(),
|
cd: cd.clone(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
@ -130,8 +143,9 @@ impl RendererBase<'_> {
|
||||||
boxes: &[(f32, f32, f32, f32)],
|
boxes: &[(f32, f32, f32, f32)],
|
||||||
color: &Color,
|
color: &Color,
|
||||||
cd: &Rc<LinearColorDescription>,
|
cd: &Rc<LinearColorDescription>,
|
||||||
|
render_intent: RenderIntent,
|
||||||
) {
|
) {
|
||||||
self.fill_boxes2_f(boxes, color, cd, 0.0, 0.0);
|
self.fill_boxes2_f(boxes, color, cd, render_intent, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_boxes2_f(
|
pub fn fill_boxes2_f(
|
||||||
|
|
@ -139,6 +153,7 @@ impl RendererBase<'_> {
|
||||||
boxes: &[(f32, f32, f32, f32)],
|
boxes: &[(f32, f32, f32, f32)],
|
||||||
color: &Color,
|
color: &Color,
|
||||||
cd: &Rc<LinearColorDescription>,
|
cd: &Rc<LinearColorDescription>,
|
||||||
|
render_intent: RenderIntent,
|
||||||
dx: f32,
|
dx: f32,
|
||||||
dy: f32,
|
dy: f32,
|
||||||
) {
|
) {
|
||||||
|
|
@ -160,6 +175,7 @@ impl RendererBase<'_> {
|
||||||
),
|
),
|
||||||
color: *color,
|
color: *color,
|
||||||
alpha: None,
|
alpha: None,
|
||||||
|
render_intent,
|
||||||
cd: cd.clone(),
|
cd: cd.clone(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
@ -180,6 +196,7 @@ impl RendererBase<'_> {
|
||||||
release_sync: ReleaseSync,
|
release_sync: ReleaseSync,
|
||||||
opaque: bool,
|
opaque: bool,
|
||||||
cd: &Rc<ColorDescription>,
|
cd: &Rc<ColorDescription>,
|
||||||
|
render_intent: RenderIntent,
|
||||||
alpha_mode: AlphaMode,
|
alpha_mode: AlphaMode,
|
||||||
) {
|
) {
|
||||||
// log::info!("rendering texture {:?}", std::ptr::from_ref(&**texture) as *const u8);
|
// log::info!("rendering texture {:?}", std::ptr::from_ref(&**texture) as *const u8);
|
||||||
|
|
@ -227,6 +244,7 @@ impl RendererBase<'_> {
|
||||||
acquire_sync,
|
acquire_sync,
|
||||||
release_sync,
|
release_sync,
|
||||||
opaque,
|
opaque,
|
||||||
|
render_intent,
|
||||||
cd: cd.clone(),
|
cd: cd.clone(),
|
||||||
alpha_mode,
|
alpha_mode,
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,10 @@ use {
|
||||||
cli::RunArgs,
|
cli::RunArgs,
|
||||||
client::{Client, ClientCaps, ClientId, Clients, NUM_CACHED_SERIAL_RANGES, SerialRange},
|
client::{Client, ClientCaps, ClientId, Clients, NUM_CACHED_SERIAL_RANGES, SerialRange},
|
||||||
clientmem::ClientMemOffset,
|
clientmem::ClientMemOffset,
|
||||||
cmm::{cmm_description::ColorDescription, cmm_manager::ColorManager},
|
cmm::{
|
||||||
|
cmm_description::ColorDescription, cmm_manager::ColorManager,
|
||||||
|
cmm_render_intent::RenderIntent,
|
||||||
|
},
|
||||||
compositor::{LIBEI_SOCKET, LogLevel},
|
compositor::{LIBEI_SOCKET, LogLevel},
|
||||||
config::ConfigProxy,
|
config::ConfigProxy,
|
||||||
control_center::{
|
control_center::{
|
||||||
|
|
@ -1332,6 +1335,7 @@ impl State {
|
||||||
release_sync,
|
release_sync,
|
||||||
false,
|
false,
|
||||||
src_cd,
|
src_cd,
|
||||||
|
RenderIntent::Perceptual,
|
||||||
AlphaMode::PremultipliedElectrical,
|
AlphaMode::PremultipliedElectrical,
|
||||||
);
|
);
|
||||||
if render_hardware_cursors
|
if render_hardware_cursors
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue