1
0
Fork 0
forked from wry/wry

theme: add support for alpha modes

This commit is contained in:
Julian Orth 2026-02-21 14:14:45 +01:00
parent c6db02a43d
commit 37674a229c
5 changed files with 93 additions and 34 deletions

View file

@ -1,6 +1,7 @@
use { use {
crate::{ crate::{
cmm::{cmm_eotf::Eotf, cmm_primaries::Primaries}, cmm::{cmm_eotf::Eotf, cmm_primaries::Primaries},
gfx_api::AlphaMode,
theme::Color, theme::Color,
utils::ordered_float::F64, utils::ordered_float::F64,
}, },
@ -140,11 +141,14 @@ impl<T, U> Mul<Color> for ColorMatrix<T, U> {
} }
} }
let [r, g, b] = self * [rgba[0] as f64, rgba[1] as f64, rgba[2] as f64]; let [r, g, b] = self * [rgba[0] as f64, rgba[1] as f64, rgba[2] as f64];
let mut color = Color::new(Eotf::Linear, r as f32, g as f32, b as f32); Color::new(
if a < 1.0 { Eotf::Linear,
color = color * a; AlphaMode::Straight,
} r as f32,
color g as f32,
b as f32,
a,
)
} }
} }

View file

@ -292,6 +292,14 @@ pub enum ResetStatus {
Other(u32), Other(u32),
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
pub enum AlphaMode {
#[default]
PremultipliedElectrical,
PremultipliedOptical,
Straight,
}
pub trait GfxBlendBuffer: Any + Debug {} pub trait GfxBlendBuffer: Any + Debug {}
pub trait GfxFramebuffer: Debug { pub trait GfxFramebuffer: Debug {

View file

@ -2,6 +2,7 @@ use {
crate::{ crate::{
client::{CAP_JAY_COMPOSITOR, Client, ClientCaps, ClientError}, client::{CAP_JAY_COMPOSITOR, Client, ClientCaps, ClientError},
cmm::cmm_eotf::Eotf, cmm::cmm_eotf::Eotf,
gfx_api::AlphaMode,
globals::{Global, GlobalName}, globals::{Global, GlobalName},
leaks::Tracker, leaks::Tracker,
object::{Object, Version}, object::{Object, Version},
@ -97,7 +98,14 @@ impl JayDamageTrackingRequestHandler for JayDamageTracking {
req: SetVisualizerColor, req: SetVisualizerColor,
_slf: &Rc<Self>, _slf: &Rc<Self>,
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
let color = Color::new(Eotf::Gamma22, req.r, req.g, req.b) * req.a; let color = Color::new(
Eotf::Gamma22,
AlphaMode::Straight,
req.r,
req.g,
req.b,
req.a,
);
self.client.state.damage_visualizer.set_color(color); self.client.state.damage_visualizer.set_color(color);
Ok(()) Ok(())
} }

View file

@ -1,6 +1,6 @@
use { use {
crate::{ crate::{
gfx_api::{AcquireSync, GfxApiOpt, ReleaseSync, SampleRect}, gfx_api::{AcquireSync, AlphaMode, GfxApiOpt, ReleaseSync, SampleRect},
icons::{IconState, SizedIcons}, icons::{IconState, SizedIcons},
ifs::wl_surface::{ ifs::wl_surface::{
SurfaceBuffer, WlSurface, SurfaceBuffer, WlSurface,
@ -493,8 +493,13 @@ impl Renderer<'_> {
Some(bounds) => rect.intersect(*bounds), Some(bounds) => rect.intersect(*bounds),
}; };
if !rect.is_empty() { if !rect.is_empty() {
let color = Color::from_u32_premultiplied( let color = Color::from_u32(
cd.eotf, color[0], color[1], color[2], color[3], cd.eotf,
AlphaMode::PremultipliedElectrical,
color[0],
color[1],
color[2],
color[3],
); );
self.base.sync(); self.base.sync();
self.base self.base

View file

@ -3,6 +3,7 @@
use { use {
crate::{ crate::{
cmm::cmm_eotf::{Eotf, bt1886_eotf_args, bt1886_inv_eotf_args}, cmm::cmm_eotf::{Eotf, bt1886_eotf_args, bt1886_inv_eotf_args},
gfx_api::AlphaMode,
utils::clonecell::CloneCell, utils::clonecell::CloneCell,
}, },
jay_config::theme::BarPosition, jay_config::theme::BarPosition,
@ -72,7 +73,27 @@ impl Color {
a: 1.0, a: 1.0,
}; };
pub fn new(eotf: Eotf, mut r: f32, mut g: f32, mut b: f32) -> Self { pub fn new(
eotf: Eotf,
alpha_mode: AlphaMode,
mut r: f32,
mut g: f32,
mut b: f32,
a: f32,
) -> Self {
if eotf == Eotf::Linear {
if alpha_mode == AlphaMode::Straight && a < 1.0 {
for c in [&mut r, &mut g, &mut b] {
*c *= a;
}
}
return Self { r, g, b, a };
}
if alpha_mode == AlphaMode::PremultipliedElectrical && a < 1.0 && a > 0.0 {
for c in [&mut r, &mut g, &mut b] {
*c /= a;
}
}
#[inline(always)] #[inline(always)]
fn linear(c: f32) -> f32 { fn linear(c: f32) -> f32 {
c c
@ -144,23 +165,12 @@ impl Color {
} }
Eotf::CompoundPower24 => convert!(compound_power_2_4), Eotf::CompoundPower24 => convert!(compound_power_2_4),
} }
Self { r, g, b, a: 1.0 } if alpha_mode != AlphaMode::PremultipliedOptical && a < 1.0 {
}
pub fn new_premultiplied(eotf: Eotf, mut r: f32, mut g: f32, mut b: f32, a: f32) -> Self {
if eotf == Eotf::Linear {
return Self { r, g, b, a };
}
if a < 1.0 && a > 0.0 {
for c in [&mut r, &mut g, &mut b] { for c in [&mut r, &mut g, &mut b] {
*c /= a; *c *= a;
} }
} }
let mut c = Self::new(eotf, r, g, b); Self { r, g, b, a }
if a < 1.0 {
c = c * a;
}
c
} }
pub fn is_opaque(&self) -> bool { pub fn is_opaque(&self) -> bool {
@ -172,26 +182,43 @@ impl Color {
} }
pub fn from_srgb(r: u8, g: u8, b: u8) -> Self { pub fn from_srgb(r: u8, g: u8, b: u8) -> Self {
Self::new(Eotf::Gamma22, to_f32(r), to_f32(g), to_f32(b)) Self::new(
Eotf::Gamma22,
AlphaMode::PremultipliedOptical,
to_f32(r),
to_f32(g),
to_f32(b),
1.0,
)
} }
pub fn from_srgba_premultiplied(r: u8, g: u8, b: u8, a: u8) -> Self { pub fn from_srgba_premultiplied(r: u8, g: u8, b: u8, a: u8) -> Self {
Self::new_premultiplied(Eotf::Gamma22, to_f32(r), to_f32(g), to_f32(b), to_f32(a)) Self::new(
Eotf::Gamma22,
AlphaMode::PremultipliedElectrical,
to_f32(r),
to_f32(g),
to_f32(b),
to_f32(a),
)
} }
pub fn from_u32_premultiplied(eotf: Eotf, r: u32, g: u32, b: u32, a: u32) -> Self { pub fn from_u32(eotf: Eotf, alpha_mode: AlphaMode, r: u32, g: u32, b: u32, a: u32) -> Self {
fn to_f32(c: u32) -> f32 { fn to_f32(c: u32) -> f32 {
((c as f64) / (u32::MAX as f64)) as f32 ((c as f64) / (u32::MAX as f64)) as f32
} }
Self::new_premultiplied(eotf, to_f32(r), to_f32(g), to_f32(b), to_f32(a)) Self::new(eotf, alpha_mode, to_f32(r), to_f32(g), to_f32(b), to_f32(a))
} }
pub fn from_srgba_straight(r: u8, g: u8, b: u8, a: u8) -> Self { pub fn from_srgba_straight(r: u8, g: u8, b: u8, a: u8) -> Self {
let mut c = Self::new(Eotf::Gamma22, to_f32(r), to_f32(g), to_f32(b)); Self::new(
if a < 255 { Eotf::Gamma22,
c = c * to_f32(a); AlphaMode::Straight,
} to_f32(r),
c to_f32(g),
to_f32(b),
to_f32(a),
)
} }
pub fn to_srgba_premultiplied(self) -> [u8; 4] { pub fn to_srgba_premultiplied(self) -> [u8; 4] {
@ -314,7 +341,14 @@ impl Color {
impl From<jay_config::theme::Color> for Color { impl From<jay_config::theme::Color> for Color {
fn from(f: jay_config::theme::Color) -> Self { fn from(f: jay_config::theme::Color) -> Self {
let [r, g, b, a] = f.to_f32_premultiplied(); let [r, g, b, a] = f.to_f32_premultiplied();
Self::new_premultiplied(Eotf::Gamma22, r, g, b, a) Self::new(
Eotf::Gamma22,
AlphaMode::PremultipliedElectrical,
r,
g,
b,
a,
)
} }
} }