Merge pull request #750 from mahkoh/jorth/color-representation
vulkan: implement all alpha modes
This commit is contained in:
commit
b976f25cf9
25 changed files with 231 additions and 64 deletions
|
|
@ -9,8 +9,8 @@ use {
|
|||
},
|
||||
cmm::cmm_description::ColorDescription,
|
||||
gfx_api::{
|
||||
AcquireSync, BufferResv, GfxApiOpt, GfxRenderPass, GfxTexture, ReleaseSync, SyncFile,
|
||||
create_render_pass,
|
||||
AcquireSync, AlphaMode, BufferResv, GfxApiOpt, GfxRenderPass, GfxTexture, ReleaseSync,
|
||||
SyncFile, create_render_pass,
|
||||
},
|
||||
ifs::wl_output::BlendSpace,
|
||||
rect::Region,
|
||||
|
|
@ -668,6 +668,10 @@ impl MetalConnector {
|
|||
}
|
||||
return None;
|
||||
};
|
||||
if ct.alpha_mode != AlphaMode::PremultipliedElectrical {
|
||||
// Direct scanout requires premultiplied electrical alpha.
|
||||
return None;
|
||||
}
|
||||
if !ct.cd.embeds_into(cd) {
|
||||
// Direct scanout requires embeddable color descriptions.
|
||||
return None;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use {
|
||||
crate::{
|
||||
cmm::{cmm_eotf::Eotf, cmm_primaries::Primaries},
|
||||
gfx_api::AlphaMode,
|
||||
theme::Color,
|
||||
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 mut color = Color::new(Eotf::Linear, r as f32, g as f32, b as f32);
|
||||
if a < 1.0 {
|
||||
color = color * a;
|
||||
}
|
||||
color
|
||||
Color::new(
|
||||
Eotf::Linear,
|
||||
AlphaMode::Straight,
|
||||
r as f32,
|
||||
g as f32,
|
||||
b as f32,
|
||||
a,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use {
|
|||
async_engine::AsyncEngine,
|
||||
fixed::Fixed,
|
||||
format::ARGB8888,
|
||||
gfx_api::{AcquireSync, GfxContext, GfxError, GfxTexture, ReleaseSync},
|
||||
gfx_api::{AcquireSync, AlphaMode, GfxContext, GfxError, GfxTexture, ReleaseSync},
|
||||
rect::Rect,
|
||||
renderer::Renderer,
|
||||
scale::Scale,
|
||||
|
|
@ -398,6 +398,7 @@ fn render_img(image: &InstantiatedCursorImage, renderer: &mut Renderer, x: Fixed
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
renderer.state.color_manager.srgb_gamma22(),
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -423,6 +424,7 @@ impl Cursor for StaticCursor {
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
renderer.state.color_manager.srgb_gamma22(),
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -466,6 +468,7 @@ impl Cursor for AnimatedCursor {
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
renderer.state.color_manager.srgb_gamma22(),
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,6 +219,7 @@ pub struct CopyTexture {
|
|||
pub alpha: Option<f32>,
|
||||
pub opaque: bool,
|
||||
pub cd: Rc<ColorDescription>,
|
||||
pub alpha_mode: AlphaMode,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
|
@ -292,6 +293,14 @@ pub enum ResetStatus {
|
|||
Other(u32),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
|
||||
pub enum AlphaMode {
|
||||
#[default]
|
||||
PremultipliedElectrical,
|
||||
PremultipliedOptical,
|
||||
Straight,
|
||||
}
|
||||
|
||||
pub trait GfxBlendBuffer: Any + Debug {}
|
||||
|
||||
pub trait GfxFramebuffer: Debug {
|
||||
|
|
@ -435,6 +444,7 @@ impl dyn GfxFramebuffer {
|
|||
release_sync,
|
||||
false,
|
||||
texture_cd,
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
let clear = self.format().has_alpha.then_some(&Color::TRANSPARENT);
|
||||
self.render(
|
||||
|
|
@ -817,6 +827,10 @@ pub trait GfxContext: Debug {
|
|||
false
|
||||
}
|
||||
|
||||
fn supports_alpha_modes(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn supports_invalid_modifier(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
mod allocator;
|
||||
mod alpha_modes;
|
||||
mod blend_buffer;
|
||||
mod bo_allocator;
|
||||
mod buffer_cache;
|
||||
|
|
@ -387,6 +388,10 @@ impl GfxContext for Context {
|
|||
self.0.device.descriptor_buffer.is_some()
|
||||
}
|
||||
|
||||
fn supports_alpha_modes(&self) -> bool {
|
||||
self.0.device.descriptor_buffer.is_some()
|
||||
}
|
||||
|
||||
fn create_dmabuf_buffer(
|
||||
&self,
|
||||
dmabuf: &OwnedFd,
|
||||
|
|
|
|||
15
src/gfx_apis/vulkan/alpha_modes.rs
Normal file
15
src/gfx_apis/vulkan/alpha_modes.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
use crate::gfx_api::AlphaMode;
|
||||
|
||||
pub const AM_PREMULTIPLIED_ELECTRICAL: u32 = 0;
|
||||
pub const AM_PREMULTIPLIED_OPTICAL: u32 = 1;
|
||||
pub const AM_STRAIGHT: u32 = 2;
|
||||
|
||||
impl AlphaMode {
|
||||
pub fn to_vulkan(self) -> u32 {
|
||||
match self {
|
||||
AlphaMode::PremultipliedElectrical => AM_PREMULTIPLIED_ELECTRICAL,
|
||||
AlphaMode::PremultipliedOptical => AM_PREMULTIPLIED_OPTICAL,
|
||||
AlphaMode::Straight => AM_STRAIGHT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
use {
|
||||
crate::gfx_apis::vulkan::{
|
||||
VulkanError, descriptor::VulkanDescriptorSetLayout, device::VulkanDevice,
|
||||
shaders::VulkanShader,
|
||||
crate::{
|
||||
gfx_api::AlphaMode,
|
||||
gfx_apis::vulkan::{
|
||||
VulkanError, descriptor::VulkanDescriptorSetLayout, device::VulkanDevice,
|
||||
shaders::VulkanShader,
|
||||
},
|
||||
},
|
||||
arrayvec::ArrayVec,
|
||||
ash::{
|
||||
|
|
@ -37,6 +40,7 @@ pub(super) struct PipelineCreateInfo {
|
|||
pub(super) blend: bool,
|
||||
pub(super) src_has_alpha: bool,
|
||||
pub(super) has_alpha_mult: bool,
|
||||
pub(super) alpha_mode: AlphaMode,
|
||||
pub(super) eotf: u32,
|
||||
pub(super) inv_eotf: u32,
|
||||
pub(super) descriptor_set_layouts: ArrayVec<Rc<VulkanDescriptorSetLayout>, 2>,
|
||||
|
|
@ -76,8 +80,8 @@ impl VulkanDevice {
|
|||
};
|
||||
let destroy_layout =
|
||||
on_drop(|| unsafe { self.device.destroy_pipeline_layout(pipeline_layout, None) });
|
||||
let mut frag_spec_data = ArrayVec::<_, { 5 * 4 }>::new();
|
||||
let mut frag_spec_entries = ArrayVec::<_, 5>::new();
|
||||
let mut frag_spec_data = ArrayVec::<_, { 6 * 4 }>::new();
|
||||
let mut frag_spec_entries = ArrayVec::<_, 6>::new();
|
||||
let mut frag_spec_entry = |data: &[u8]| {
|
||||
let entry = SpecializationMapEntry::default()
|
||||
.constant_id(frag_spec_entries.len() as _)
|
||||
|
|
@ -91,6 +95,7 @@ impl VulkanDevice {
|
|||
frag_spec_entry(&info.eotf.to_ne_bytes());
|
||||
frag_spec_entry(&info.inv_eotf.to_ne_bytes());
|
||||
frag_spec_entry(&(info.has_color_management_data as u32).to_ne_bytes());
|
||||
frag_spec_entry(&info.alpha_mode.to_vulkan().to_ne_bytes());
|
||||
let frag_spec = SpecializationInfo::default()
|
||||
.map_entries(&frag_spec_entries)
|
||||
.data(&frag_spec_data);
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use {
|
|||
},
|
||||
cpu_worker::PendingJob,
|
||||
gfx_api::{
|
||||
AcquireSync, BufferResv, BufferResvUser, GfxApiOpt, GfxBlendBuffer, GfxFormat,
|
||||
GfxTexture, GfxWriteModifier, ReleaseSync, SyncFile,
|
||||
AcquireSync, AlphaMode, BufferResv, BufferResvUser, GfxApiOpt, GfxBlendBuffer,
|
||||
GfxFormat, GfxTexture, GfxWriteModifier, ReleaseSync, SyncFile,
|
||||
},
|
||||
gfx_apis::vulkan::{
|
||||
VulkanError,
|
||||
|
|
@ -209,6 +209,7 @@ struct VulkanTexOp {
|
|||
alpha: f32,
|
||||
source_type: TexSourceType,
|
||||
copy_type: TexCopyType,
|
||||
alpha_mode: AlphaMode,
|
||||
range_address: DeviceAddress,
|
||||
instances: u32,
|
||||
tex_cd: Rc<ColorDescription>,
|
||||
|
|
@ -258,6 +259,7 @@ type FillPipelines = Rc<StaticMap<TexSourceType, Rc<VulkanPipeline>>>;
|
|||
struct TexPipelineKey {
|
||||
tex_copy_type: TexCopyType,
|
||||
tex_source_type: TexSourceType,
|
||||
tex_alpha_mode: AlphaMode,
|
||||
eotf: VulkanEotf,
|
||||
has_color_management_data: bool,
|
||||
}
|
||||
|
|
@ -431,6 +433,7 @@ impl VulkanRenderer {
|
|||
blend: src_has_alpha,
|
||||
src_has_alpha,
|
||||
has_alpha_mult: false,
|
||||
alpha_mode: AlphaMode::PremultipliedOptical,
|
||||
// all transformations are applied in the compositor
|
||||
eotf: EOTF_LINEAR,
|
||||
inv_eotf: EOTF_LINEAR,
|
||||
|
|
@ -474,11 +477,16 @@ impl VulkanRenderer {
|
|||
tex_cd: &ColorDescription,
|
||||
tex_copy_type: TexCopyType,
|
||||
tex_source_type: TexSourceType,
|
||||
mut tex_alpha_mode: AlphaMode,
|
||||
has_color_management_data: bool,
|
||||
) -> Result<Rc<VulkanPipeline>, VulkanError> {
|
||||
if tex_source_type == TexSourceType::Opaque {
|
||||
tex_alpha_mode = AlphaMode::PremultipliedElectrical;
|
||||
}
|
||||
let key = TexPipelineKey {
|
||||
tex_copy_type,
|
||||
tex_source_type,
|
||||
tex_alpha_mode,
|
||||
eotf: tex_cd.eotf.to_vulkan(),
|
||||
has_color_management_data,
|
||||
};
|
||||
|
|
@ -505,6 +513,7 @@ impl VulkanRenderer {
|
|||
blend: src_has_alpha || has_alpha_mult,
|
||||
src_has_alpha,
|
||||
has_alpha_mult,
|
||||
alpha_mode: key.tex_alpha_mode,
|
||||
eotf: key.eotf.to_vulkan(),
|
||||
inv_eotf: pipelines.eotf.to_vulkan(),
|
||||
descriptor_set_layouts: self.tex_descriptor_set_layouts.clone(),
|
||||
|
|
@ -543,6 +552,7 @@ impl VulkanRenderer {
|
|||
blend: false,
|
||||
src_has_alpha: true,
|
||||
has_alpha_mult: false,
|
||||
alpha_mode: AlphaMode::PremultipliedElectrical,
|
||||
eotf: key.eotf.to_vulkan(),
|
||||
inv_eotf: fb_eotf.to_vulkan(),
|
||||
descriptor_set_layouts,
|
||||
|
|
@ -886,6 +896,7 @@ impl VulkanRenderer {
|
|||
alpha: ct.alpha.unwrap_or_default(),
|
||||
source_type,
|
||||
copy_type,
|
||||
alpha_mode: ct.alpha_mode,
|
||||
range_address: 0,
|
||||
instances: 0,
|
||||
tex_cd: ct.cd.clone(),
|
||||
|
|
@ -1333,6 +1344,7 @@ impl VulkanRenderer {
|
|||
&c.tex_cd,
|
||||
c.copy_type,
|
||||
c.source_type,
|
||||
c.alpha_mode,
|
||||
c.color_management_data_address.is_some(),
|
||||
)?;
|
||||
bind(&pipeline);
|
||||
|
|
|
|||
8
src/gfx_apis/vulkan/shaders/alpha_modes.glsl
Normal file
8
src/gfx_apis/vulkan/shaders/alpha_modes.glsl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef ALPHA_MODES_GLSL
|
||||
#define ALPHA_MODES_GLSL
|
||||
|
||||
#define AM_PREMULTIPLIED_ELECTRICAL 0
|
||||
#define AM_PREMULTIPLIED_OPTICAL 1
|
||||
#define AM_STRAIGHT 2
|
||||
|
||||
#endif
|
||||
|
|
@ -6,5 +6,6 @@ layout(constant_id = 1) const bool has_alpha_multiplier = false;
|
|||
layout(constant_id = 2) const uint eotf = 0;
|
||||
layout(constant_id = 3) const uint inv_eotf = 0;
|
||||
layout(constant_id = 4) const bool has_matrix = false;
|
||||
layout(constant_id = 5) const uint alpha_mode = 0;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "tex.common.glsl"
|
||||
#include "tex_set.glsl"
|
||||
#include "eotfs.glsl"
|
||||
#include "alpha_modes.glsl"
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler sam;
|
||||
layout(location = 0) in vec2 tex_pos;
|
||||
|
|
@ -15,12 +16,15 @@ layout(location = 0) out vec4 out_color;
|
|||
|
||||
void main() {
|
||||
vec4 c = textureLod(sampler2D(tex, sam), tex_pos, 0);
|
||||
if (eotf != inv_eotf || has_matrix) {
|
||||
if (eotf != inv_eotf || has_matrix || alpha_mode != AM_PREMULTIPLIED_ELECTRICAL) {
|
||||
vec3 rgb = c.rgb;
|
||||
if (src_has_alpha) {
|
||||
if (src_has_alpha && alpha_mode == AM_PREMULTIPLIED_ELECTRICAL) {
|
||||
rgb /= mix(c.a, 1.0, c.a == 0.0);
|
||||
}
|
||||
rgb = apply_eotf(rgb);
|
||||
if (src_has_alpha && alpha_mode == AM_PREMULTIPLIED_OPTICAL) {
|
||||
rgb /= mix(c.a, 1.0, c.a == 0.0);
|
||||
}
|
||||
if (has_matrix) {
|
||||
rgb = (cm_data.matrix * vec4(rgb, 1.0)).rgb;
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,8 +1,9 @@
|
|||
302a9f250bdc4f8e0e71a9f77c9a8a7aa55fd003bc91c2422a700c4abd83f54e src/gfx_apis/vulkan/shaders/alpha_modes.glsl
|
||||
b6a0df1e231fab533499329636b7a580384784418baee06c147af5fcc384cf5c src/gfx_apis/vulkan/shaders/eotfs.glsl
|
||||
8a38df18851cd13884499820f26939fb7319f45d913d867f254d8118d59fb117 src/gfx_apis/vulkan/shaders/fill.common.glsl
|
||||
21c488d12aa5ad2f109ec44cb856dfe837e02ea9025b5ed64439d742c17cbf30 src/gfx_apis/vulkan/shaders/fill.frag
|
||||
4fb481d8d73afdfb0d8f077eb8665d86f06c8a32a91e44ed369ef5dff554646d src/gfx_apis/vulkan/shaders/fill.vert
|
||||
63af15c4e00587a7bb8494934c88d9874712a511217829b50f3c08fa3c461082 src/gfx_apis/vulkan/shaders/frag_spec_const.glsl
|
||||
f93524fd077bc9984702b1e0f92232f80bfe28a0a92439dc164c1ea41fd16d64 src/gfx_apis/vulkan/shaders/frag_spec_const.glsl
|
||||
c315a064b48dd5bdb607a6b79c30d31b6e59ffec69e93d50ab875abf97c41bbf src/gfx_apis/vulkan/shaders/legacy/fill.common.glsl
|
||||
590d061b97446fc501158609eaf098b71bc7b328c008b586ff36613ce690d618 src/gfx_apis/vulkan/shaders/legacy/fill.frag
|
||||
ad22a79e1a88a12daa40c0a2b953084c129a408297c8ca544d60e0b6001470b9 src/gfx_apis/vulkan/shaders/legacy/fill.vert
|
||||
|
|
@ -13,6 +14,6 @@ e0a8769dd7938dd02e66db9e9048ed6bef8f8c42671f2e2c7a7976a6d498f685 src/gfx_apis/vu
|
|||
5069f619c7d722815a022e2d84720a2d8290af49a3ed49ea0cd26b52115cc39a src/gfx_apis/vulkan/shaders/out.frag
|
||||
0adc7e12328c15fb3e7e6c8b8701a182223c2f15337e14131f41dd247e697809 src/gfx_apis/vulkan/shaders/out.vert
|
||||
e22d4d3318a350def8ef19c7b27dc6a308a84c2fe9d7c02b81107f72073cd481 src/gfx_apis/vulkan/shaders/tex.common.glsl
|
||||
06993d4d882fe5c651e5ab54f0116b9622352a97f3575985076ef464b472dd39 src/gfx_apis/vulkan/shaders/tex.frag
|
||||
1f196cee646a934072beb3e5648a5042c035953d9a0c26b0a22e330c2f8bb994 src/gfx_apis/vulkan/shaders/tex.frag
|
||||
423cf327c9fcc4070dbf75321c1224a1589b6cf3d2f1ea5e8bd0362e1a9f3aa1 src/gfx_apis/vulkan/shaders/tex.vert
|
||||
b982f7101c22931a33b32dce3408387f3392c0f0ad0ca5852da265b0d12856bb src/gfx_apis/vulkan/shaders/tex_set.glsl
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use {
|
|||
crate::{
|
||||
client::{CAP_JAY_COMPOSITOR, Client, ClientCaps, ClientError},
|
||||
cmm::cmm_eotf::Eotf,
|
||||
gfx_api::AlphaMode,
|
||||
globals::{Global, GlobalName},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
|
|
@ -97,7 +98,14 @@ impl JayDamageTrackingRequestHandler for JayDamageTracking {
|
|||
req: SetVisualizerColor,
|
||||
_slf: &Rc<Self>,
|
||||
) -> 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);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use {
|
|||
drm_feedback::DrmFeedback,
|
||||
fixed::Fixed,
|
||||
gfx_api::{
|
||||
AsyncShmGfxTexture, BufferResv, BufferResvUser, GfxError, GfxStagingBuffer,
|
||||
AlphaMode, AsyncShmGfxTexture, BufferResv, BufferResvUser, GfxError, GfxStagingBuffer,
|
||||
ReleaseSync, SampleRect, SyncFile,
|
||||
},
|
||||
ifs::{
|
||||
|
|
@ -353,6 +353,7 @@ pub struct WlSurface {
|
|||
CopyHashMap<WpColorManagementSurfaceFeedbackV1Id, Rc<WpColorManagementSurfaceFeedbackV1>>,
|
||||
color_description: CloneCell<Option<Rc<ColorDescription>>>,
|
||||
color_representation_surface: CloneCell<Option<Rc<WpColorRepresentationSurfaceV1>>>,
|
||||
alpha_mode: Cell<AlphaMode>,
|
||||
}
|
||||
|
||||
impl Debug for WlSurface {
|
||||
|
|
@ -490,6 +491,7 @@ struct PendingState {
|
|||
tray_item_ack_serial: Option<u32>,
|
||||
color_description: Option<Option<Rc<ColorDescription>>>,
|
||||
serial: Option<u64>,
|
||||
alpha_mode: Option<AlphaMode>,
|
||||
}
|
||||
|
||||
struct AttachedSubsurfaceState {
|
||||
|
|
@ -544,6 +546,7 @@ impl PendingState {
|
|||
opt!(tray_item_ack_serial);
|
||||
opt!(color_description);
|
||||
opt!(serial);
|
||||
opt!(alpha_mode);
|
||||
{
|
||||
let (dx1, dy1) = self.offset;
|
||||
let (dx2, dy2) = mem::take(&mut next.offset);
|
||||
|
|
@ -708,6 +711,7 @@ impl WlSurface {
|
|||
color_management_feedback: Default::default(),
|
||||
color_description: Default::default(),
|
||||
color_representation_surface: Default::default(),
|
||||
alpha_mode: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1202,6 +1206,12 @@ impl WlSurface {
|
|||
color_description_changed = true;
|
||||
self.color_description.set(desc);
|
||||
}
|
||||
let mut alpha_mode_changed = false;
|
||||
if let Some(alpha_mode) = pending.alpha_mode.take()
|
||||
&& self.alpha_mode.replace(alpha_mode) != alpha_mode
|
||||
{
|
||||
alpha_mode_changed = true;
|
||||
}
|
||||
let mut alpha_changed = false;
|
||||
if let Some(alpha) = pending.alpha_multiplier.take() {
|
||||
alpha_changed = true;
|
||||
|
|
@ -1213,7 +1223,8 @@ impl WlSurface {
|
|||
|| buffer_transform_changed
|
||||
|| viewport_changed
|
||||
|| alpha_changed
|
||||
|| color_description_changed;
|
||||
|| color_description_changed
|
||||
|| alpha_mode_changed;
|
||||
let mut buffer_changed = false;
|
||||
let mut old_raw_size = None;
|
||||
let (mut dx, mut dy) = mem::take(&mut pending.offset);
|
||||
|
|
@ -1725,6 +1736,10 @@ impl WlSurface {
|
|||
self.alpha.get()
|
||||
}
|
||||
|
||||
pub fn alpha_mode(&self) -> AlphaMode {
|
||||
self.alpha_mode.get()
|
||||
}
|
||||
|
||||
pub fn opaque(&self) -> bool {
|
||||
self.is_opaque.get()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientError},
|
||||
gfx_api::AlphaMode,
|
||||
ifs::wl_surface::WlSurface,
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
|
|
@ -22,12 +23,11 @@ pub struct WpColorRepresentationSurfaceV1 {
|
|||
pub version: Version,
|
||||
pub tracker: Tracker<Self>,
|
||||
pub surface: Rc<WlSurface>,
|
||||
pub supports_alpha_modes: bool,
|
||||
}
|
||||
|
||||
pub const AM_PREMULTIPLIED_ELECTRICAL: u32 = 0;
|
||||
#[expect(dead_code)]
|
||||
pub const AM_PREMULTIPLIED_OPTICAL: u32 = 1;
|
||||
#[expect(dead_code)]
|
||||
pub const AM_STRAIGHT: u32 = 2;
|
||||
|
||||
impl WpColorRepresentationSurfaceV1 {
|
||||
|
|
@ -47,16 +47,22 @@ impl WpColorRepresentationSurfaceV1RequestHandler for WpColorRepresentationSurfa
|
|||
|
||||
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
self.surface.color_representation_surface.take();
|
||||
self.surface.pending.borrow_mut().alpha_mode = Some(Default::default());
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_alpha_mode(&self, req: SetAlphaMode, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||
if req.alpha_mode != AM_PREMULTIPLIED_ELECTRICAL {
|
||||
return Err(WpColorRepresentationSurfaceV1Error::UnsupportedAlphaMode(
|
||||
req.alpha_mode,
|
||||
));
|
||||
}
|
||||
let sam = self.supports_alpha_modes;
|
||||
let alpha_mode = match req.alpha_mode {
|
||||
AM_PREMULTIPLIED_ELECTRICAL => AlphaMode::PremultipliedElectrical,
|
||||
AM_PREMULTIPLIED_OPTICAL if sam => AlphaMode::PremultipliedOptical,
|
||||
AM_STRAIGHT if sam => AlphaMode::Straight,
|
||||
n => {
|
||||
return Err(WpColorRepresentationSurfaceV1Error::UnsupportedAlphaMode(n));
|
||||
}
|
||||
};
|
||||
self.surface.pending.borrow_mut().alpha_mode = Some(alpha_mode);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use {
|
|||
client::{Client, ClientError},
|
||||
globals::{Global, GlobalName},
|
||||
ifs::wl_surface::wp_color_representation_surface_v1::{
|
||||
AM_PREMULTIPLIED_ELECTRICAL, WpColorRepresentationSurfaceV1,
|
||||
WpColorRepresentationSurfaceV1Error,
|
||||
AM_PREMULTIPLIED_ELECTRICAL, AM_PREMULTIPLIED_OPTICAL, AM_STRAIGHT,
|
||||
WpColorRepresentationSurfaceV1, WpColorRepresentationSurfaceV1Error,
|
||||
},
|
||||
leaks::Tracker,
|
||||
object::{Object, Version},
|
||||
|
|
@ -35,11 +35,18 @@ impl WpColorRepresentationManagerV1Global {
|
|||
client: &Rc<Client>,
|
||||
version: Version,
|
||||
) -> Result<(), WpColorRepresentationManagerV1Error> {
|
||||
let mut supports_alpha_modes = false;
|
||||
if let Some(ctx) = client.state.render_ctx.get()
|
||||
&& ctx.supports_alpha_modes()
|
||||
{
|
||||
supports_alpha_modes = true;
|
||||
}
|
||||
let obj = Rc::new(WpColorRepresentationManagerV1 {
|
||||
id,
|
||||
client: client.clone(),
|
||||
tracker: Default::default(),
|
||||
version,
|
||||
supports_alpha_modes,
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
|
|
@ -53,11 +60,16 @@ pub struct WpColorRepresentationManagerV1 {
|
|||
pub client: Rc<Client>,
|
||||
pub version: Version,
|
||||
pub tracker: Tracker<Self>,
|
||||
pub supports_alpha_modes: bool,
|
||||
}
|
||||
|
||||
impl WpColorRepresentationManagerV1 {
|
||||
fn send_capabilities(&self) {
|
||||
self.send_supported_alpha_mode(AM_PREMULTIPLIED_ELECTRICAL);
|
||||
if self.supports_alpha_modes {
|
||||
self.send_supported_alpha_mode(AM_PREMULTIPLIED_OPTICAL);
|
||||
self.send_supported_alpha_mode(AM_STRAIGHT);
|
||||
}
|
||||
self.send_done();
|
||||
}
|
||||
|
||||
|
|
@ -89,6 +101,7 @@ impl WpColorRepresentationManagerV1RequestHandler for WpColorRepresentationManag
|
|||
version: self.version,
|
||||
tracker: Default::default(),
|
||||
surface: surface.clone(),
|
||||
supports_alpha_modes: self.supports_alpha_modes,
|
||||
});
|
||||
track!(self.client, obj);
|
||||
self.client.add_client_obj(&obj)?;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ use {
|
|||
fixed::Fixed,
|
||||
format::ARGB8888,
|
||||
gfx_api::{
|
||||
AcquireSync, GfxContext, GfxFramebuffer, GfxTexture, ReleaseSync, needs_render_usage,
|
||||
AcquireSync, AlphaMode, GfxContext, GfxFramebuffer, GfxTexture, ReleaseSync,
|
||||
needs_render_usage,
|
||||
},
|
||||
ifs::zwlr_layer_shell_v1::OVERLAY,
|
||||
portal::{
|
||||
|
|
@ -230,6 +231,7 @@ impl GuiElement for Button {
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
srgb_srgb,
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -332,6 +334,7 @@ impl GuiElement for Label {
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
color_manager.srgb_gamma22(),
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use {
|
||||
crate::{
|
||||
gfx_api::{AcquireSync, GfxApiOpt, ReleaseSync, SampleRect},
|
||||
gfx_api::{AcquireSync, AlphaMode, GfxApiOpt, ReleaseSync, SampleRect},
|
||||
icons::{IconState, SizedIcons},
|
||||
ifs::wl_surface::{
|
||||
SurfaceBuffer, WlSurface,
|
||||
|
|
@ -145,6 +145,7 @@ impl Renderer<'_> {
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
self.state.color_manager.srgb_gamma22(),
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
x += bar_rect.x1() - non_exclusive_rect_rel.x1();
|
||||
|
|
@ -167,6 +168,7 @@ impl Renderer<'_> {
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
srgb_srgb,
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
for item in output.tray_items.iter() {
|
||||
|
|
@ -253,6 +255,7 @@ impl Renderer<'_> {
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
self.state.color_manager.srgb_gamma22(),
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
self.render_tl_aux(placeholder.tl_data(), bounds, true);
|
||||
|
|
@ -304,6 +307,7 @@ impl Renderer<'_> {
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
srgb_srgb,
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -466,6 +470,7 @@ impl Renderer<'_> {
|
|||
) {
|
||||
let alpha = surface.alpha();
|
||||
let cd = surface.color_description();
|
||||
let alpha_mode = surface.alpha_mode();
|
||||
if let Some(tex) = buffer.buffer.get_texture(surface) {
|
||||
let mut opaque = surface.opaque();
|
||||
if !opaque && tex.format().has_alpha {
|
||||
|
|
@ -485,6 +490,7 @@ impl Renderer<'_> {
|
|||
buffer.release_sync,
|
||||
opaque,
|
||||
&cd,
|
||||
alpha_mode,
|
||||
);
|
||||
} else if let Some(color) = &buffer.buffer.color {
|
||||
if let Some(rect) = Rect::new_sized(x, y, tsize.0, tsize.1) {
|
||||
|
|
@ -493,8 +499,8 @@ impl Renderer<'_> {
|
|||
Some(bounds) => rect.intersect(*bounds),
|
||||
};
|
||||
if !rect.is_empty() {
|
||||
let color = Color::from_u32_premultiplied(
|
||||
cd.eotf, color[0], color[1], color[2], color[3],
|
||||
let color = Color::from_u32(
|
||||
cd.eotf, alpha_mode, color[0], color[1], color[2], color[3],
|
||||
);
|
||||
self.base.sync();
|
||||
self.base
|
||||
|
|
@ -581,6 +587,7 @@ impl Renderer<'_> {
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
srgb_srgb,
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
x1 += th;
|
||||
|
|
@ -603,6 +610,7 @@ impl Renderer<'_> {
|
|||
ReleaseSync::None,
|
||||
false,
|
||||
srgb_srgb,
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
}
|
||||
let body = Rect::new_sized_saturating(
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use {
|
|||
crate::{
|
||||
cmm::cmm_description::{ColorDescription, LinearColorDescription},
|
||||
gfx_api::{
|
||||
AcquireSync, BufferResv, CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxTexture,
|
||||
ReleaseSync, SampleRect,
|
||||
AcquireSync, AlphaMode, BufferResv, CopyTexture, FillRect, FramebufferRect, GfxApiOpt,
|
||||
GfxTexture, ReleaseSync, SampleRect,
|
||||
},
|
||||
rect::Rect,
|
||||
scale::Scale,
|
||||
|
|
@ -181,6 +181,7 @@ impl RendererBase<'_> {
|
|||
release_sync: ReleaseSync,
|
||||
opaque: bool,
|
||||
cd: &Rc<ColorDescription>,
|
||||
alpha_mode: AlphaMode,
|
||||
) {
|
||||
// log::info!("rendering texture {:?}", std::ptr::from_ref(&**texture) as *const u8);
|
||||
// log::info!("{:?}", backtrace::Backtrace::new());
|
||||
|
|
@ -228,6 +229,7 @@ impl RendererBase<'_> {
|
|||
release_sync,
|
||||
opaque,
|
||||
cd: cd.clone(),
|
||||
alpha_mode,
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,9 @@ use {
|
|||
forker::ForkerProxy,
|
||||
format::Format,
|
||||
gfx_api::{
|
||||
AcquireSync, BufferResv, GfxBlendBuffer, GfxContext, GfxError, GfxFramebuffer,
|
||||
GfxTexture, PendingShmTransfer, ReleaseSync, STAGING_DOWNLOAD, SampleRect, SyncFile,
|
||||
AcquireSync, AlphaMode, BufferResv, GfxBlendBuffer, GfxContext, GfxError,
|
||||
GfxFramebuffer, GfxTexture, PendingShmTransfer, ReleaseSync, STAGING_DOWNLOAD,
|
||||
SampleRect, SyncFile,
|
||||
},
|
||||
gfx_apis::create_gfx_context,
|
||||
globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal},
|
||||
|
|
@ -1272,6 +1273,7 @@ impl State {
|
|||
release_sync,
|
||||
false,
|
||||
src_cd,
|
||||
AlphaMode::PremultipliedElectrical,
|
||||
);
|
||||
if render_hardware_cursors
|
||||
&& let Some(cursor_user_group) = self.cursor_user_group_hardware_cursor.get()
|
||||
|
|
|
|||
84
src/theme.rs
84
src/theme.rs
|
|
@ -3,6 +3,7 @@
|
|||
use {
|
||||
crate::{
|
||||
cmm::cmm_eotf::{Eotf, bt1886_eotf_args, bt1886_inv_eotf_args},
|
||||
gfx_api::AlphaMode,
|
||||
utils::clonecell::CloneCell,
|
||||
},
|
||||
jay_config::theme::BarPosition,
|
||||
|
|
@ -72,7 +73,27 @@ impl Color {
|
|||
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)]
|
||||
fn linear(c: f32) -> f32 {
|
||||
c
|
||||
|
|
@ -144,23 +165,12 @@ impl Color {
|
|||
}
|
||||
Eotf::CompoundPower24 => convert!(compound_power_2_4),
|
||||
}
|
||||
Self { r, g, b, 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 {
|
||||
if alpha_mode != AlphaMode::PremultipliedOptical && a < 1.0 {
|
||||
for c in [&mut r, &mut g, &mut b] {
|
||||
*c /= a;
|
||||
*c *= a;
|
||||
}
|
||||
}
|
||||
let mut c = Self::new(eotf, r, g, b);
|
||||
if a < 1.0 {
|
||||
c = c * a;
|
||||
}
|
||||
c
|
||||
Self { r, g, b, a }
|
||||
}
|
||||
|
||||
pub fn is_opaque(&self) -> bool {
|
||||
|
|
@ -172,26 +182,43 @@ impl Color {
|
|||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
((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 {
|
||||
let mut c = Self::new(Eotf::Gamma22, to_f32(r), to_f32(g), to_f32(b));
|
||||
if a < 255 {
|
||||
c = c * to_f32(a);
|
||||
}
|
||||
c
|
||||
Self::new(
|
||||
Eotf::Gamma22,
|
||||
AlphaMode::Straight,
|
||||
to_f32(r),
|
||||
to_f32(g),
|
||||
to_f32(b),
|
||||
to_f32(a),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_srgba_premultiplied(self) -> [u8; 4] {
|
||||
|
|
@ -314,7 +341,14 @@ impl Color {
|
|||
impl From<jay_config::theme::Color> for Color {
|
||||
fn from(f: jay_config::theme::Color) -> Self {
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue