alpha-multiplier: perform multiplication in the renderer
This commit is contained in:
parent
33718340f7
commit
0872a1251d
8 changed files with 46 additions and 22 deletions
|
|
@ -570,7 +570,7 @@ impl MetalConnector {
|
||||||
match opt {
|
match opt {
|
||||||
GfxApiOpt::Sync => {}
|
GfxApiOpt::Sync => {}
|
||||||
GfxApiOpt::FillRect(fr) => {
|
GfxApiOpt::FillRect(fr) => {
|
||||||
if fr.color == Color::SOLID_BLACK {
|
if fr.effective_color() == Color::SOLID_BLACK {
|
||||||
// Black fills can be ignored because this is the CRTC background color.
|
// Black fills can be ignored because this is the CRTC background color.
|
||||||
if fr.rect.is_covering() {
|
if fr.rect.is_covering() {
|
||||||
// If fill covers the entire screen, we don't have to look further.
|
// If fill covers the entire screen, we don't have to look further.
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ impl SampleRect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub struct FramebufferRect {
|
pub struct FramebufferRect {
|
||||||
pub x1: f32,
|
pub x1: f32,
|
||||||
pub x2: f32,
|
pub x2: f32,
|
||||||
|
|
@ -171,6 +171,17 @@ impl FramebufferRect {
|
||||||
pub struct FillRect {
|
pub struct FillRect {
|
||||||
pub rect: FramebufferRect,
|
pub rect: FramebufferRect,
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
|
pub alpha: Option<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FillRect {
|
||||||
|
pub fn effective_color(&self) -> Color {
|
||||||
|
let mut color = self.color;
|
||||||
|
if let Some(alpha) = self.alpha {
|
||||||
|
color = color * alpha;
|
||||||
|
}
|
||||||
|
color
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CopyTexture {
|
pub struct CopyTexture {
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ enum RenderError {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct GfxGlState {
|
struct GfxGlState {
|
||||||
triangles: RefCell<Vec<[f32; 2]>>,
|
triangles: RefCell<Vec<[f32; 2]>>,
|
||||||
fill_rect: VecStorage<&'static FillRect>,
|
fill_rect: VecStorage<FillRect>,
|
||||||
copy_tex: VecStorage<&'static CopyTexture>,
|
copy_tex: VecStorage<&'static CopyTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,7 +233,11 @@ fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) -> Option<SyncFile> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GfxApiOpt::FillRect(f) => {
|
GfxApiOpt::FillRect(f) => {
|
||||||
fill_rect.push(f);
|
fill_rect.push(FillRect {
|
||||||
|
rect: f.rect,
|
||||||
|
color: f.effective_color(),
|
||||||
|
alpha: None,
|
||||||
|
});
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
GfxApiOpt::CopyTexture(c) => {
|
GfxApiOpt::CopyTexture(c) => {
|
||||||
|
|
@ -249,7 +253,7 @@ fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) -> Option<SyncFile> {
|
||||||
triangles.clear();
|
triangles.clear();
|
||||||
let mut color = None;
|
let mut color = None;
|
||||||
while i < fill_rect.len() {
|
while i < fill_rect.len() {
|
||||||
let fr = fill_rect[i];
|
let fr = &fill_rect[i];
|
||||||
match color {
|
match color {
|
||||||
None => color = Some(fr.color),
|
None => color = Some(fr.color),
|
||||||
Some(c) if c == fr.color => {}
|
Some(c) if c == fr.color => {}
|
||||||
|
|
|
||||||
|
|
@ -505,7 +505,7 @@ impl VulkanRenderer {
|
||||||
let memory = &mut *self.memory.borrow_mut();
|
let memory = &mut *self.memory.borrow_mut();
|
||||||
let clear_value = clear.map(|clear| ClearValue {
|
let clear_value = clear.map(|clear| ClearValue {
|
||||||
color: ClearColorValue {
|
color: ClearColorValue {
|
||||||
float32: clear.to_array_srgb(),
|
float32: clear.to_array_srgb(None),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
let load_clear = memory.paint_regions.len() == 1 && {
|
let load_clear = memory.paint_regions.len() == 1 && {
|
||||||
|
|
@ -620,7 +620,7 @@ impl VulkanRenderer {
|
||||||
GfxApiOpt::FillRect(r) => {
|
GfxApiOpt::FillRect(r) => {
|
||||||
let push = FillPushConstants {
|
let push = FillPushConstants {
|
||||||
pos: r.rect.to_points(),
|
pos: r.rect.to_points(),
|
||||||
color: r.color.to_array_srgb(),
|
color: r.color.to_array_srgb(r.alpha),
|
||||||
};
|
};
|
||||||
for region in &memory.paint_regions {
|
for region in &memory.paint_regions {
|
||||||
let mut push = push;
|
let mut push = push;
|
||||||
|
|
|
||||||
|
|
@ -441,11 +441,12 @@ impl GfxFramebuffer for TestGfxFb {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let fill_rect = |f: &FillRect, staging: &mut [Color]| {
|
let fill_rect = |f: &FillRect, staging: &mut [Color]| {
|
||||||
|
let color = f.effective_color();
|
||||||
let (x1, y1, x2, y2) = fb_points(width, height, &f.rect);
|
let (x1, y1, x2, y2) = fb_points(width, height, &f.rect);
|
||||||
for y in y1..y2 {
|
for y in y1..y2 {
|
||||||
for x in x1..x2 {
|
for x in x1..x2 {
|
||||||
let dst = &mut staging[(y * width + x) as usize];
|
let dst = &mut staging[(y * width + x) as usize];
|
||||||
*dst = dst.and_then(&f.color);
|
*dst = dst.and_then(&color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,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_boxes3(slice::from_ref(&bar_bg), &c, x, y, true);
|
.fill_boxes3(slice::from_ref(&bar_bg), &c, None, x, y, true);
|
||||||
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 {
|
||||||
let c = match aw.captured {
|
let c = match aw.captured {
|
||||||
|
|
@ -336,7 +336,8 @@ impl Renderer<'_> {
|
||||||
};
|
};
|
||||||
let color = self.state.theme.colors.highlight.get();
|
let color = self.state.theme.colors.highlight.get();
|
||||||
self.base.ops.push(GfxApiOpt::Sync);
|
self.base.ops.push(GfxApiOpt::Sync);
|
||||||
self.base.fill_scaled_boxes(slice::from_ref(bounds), &color);
|
self.base
|
||||||
|
.fill_scaled_boxes(slice::from_ref(bounds), &color, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_highlight(&mut self, rect: &Rect) {
|
pub fn render_highlight(&mut self, rect: &Rect) {
|
||||||
|
|
@ -440,11 +441,7 @@ impl Renderer<'_> {
|
||||||
};
|
};
|
||||||
if !rect.is_empty() {
|
if !rect.is_empty() {
|
||||||
self.base.ops.push(GfxApiOpt::Sync);
|
self.base.ops.push(GfxApiOpt::Sync);
|
||||||
let mut color = *color;
|
self.base.fill_scaled_boxes(&[rect], color, alpha);
|
||||||
if let Some(alpha) = alpha {
|
|
||||||
color = color * alpha;
|
|
||||||
}
|
|
||||||
self.base.fill_scaled_boxes(&[rect], &color);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -64,19 +64,27 @@ impl RendererBase<'_> {
|
||||||
rect
|
rect
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_scaled_boxes(&mut self, boxes: &[Rect], color: &Color) {
|
pub fn fill_scaled_boxes(&mut self, boxes: &[Rect], color: &Color, alpha: Option<f32>) {
|
||||||
self.fill_boxes3(boxes, color, 0, 0, true);
|
self.fill_boxes3(boxes, color, alpha, 0, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_boxes(&mut self, boxes: &[Rect], color: &Color) {
|
pub fn fill_boxes(&mut self, boxes: &[Rect], color: &Color) {
|
||||||
self.fill_boxes3(boxes, color, 0, 0, false);
|
self.fill_boxes3(boxes, color, None, 0, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_boxes2(&mut self, boxes: &[Rect], color: &Color, dx: i32, dy: i32) {
|
pub fn fill_boxes2(&mut self, boxes: &[Rect], color: &Color, dx: i32, dy: i32) {
|
||||||
self.fill_boxes3(boxes, color, dx, dy, false);
|
self.fill_boxes3(boxes, color, None, dx, dy, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_boxes3(&mut self, boxes: &[Rect], color: &Color, dx: i32, dy: i32, scaled: bool) {
|
pub fn fill_boxes3(
|
||||||
|
&mut self,
|
||||||
|
boxes: &[Rect],
|
||||||
|
color: &Color,
|
||||||
|
alpha: Option<f32>,
|
||||||
|
dx: i32,
|
||||||
|
dy: i32,
|
||||||
|
scaled: bool,
|
||||||
|
) {
|
||||||
if boxes.is_empty() || *color == Color::TRANSPARENT {
|
if boxes.is_empty() || *color == Color::TRANSPARENT {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -97,6 +105,7 @@ impl RendererBase<'_> {
|
||||||
self.fb_height,
|
self.fb_height,
|
||||||
),
|
),
|
||||||
color: *color,
|
color: *color,
|
||||||
|
alpha,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -129,6 +138,7 @@ impl RendererBase<'_> {
|
||||||
self.fb_height,
|
self.fb_height,
|
||||||
),
|
),
|
||||||
color: *color,
|
color: *color,
|
||||||
|
alpha: None,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,9 @@ impl Color {
|
||||||
[to_u8(self.r), to_u8(self.g), to_u8(self.b), to_u8(self.a)]
|
[to_u8(self.r), to_u8(self.g), to_u8(self.b), to_u8(self.a)]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_array_srgb(self) -> [f32; 4] {
|
pub fn to_array_srgb(self, alpha: Option<f32>) -> [f32; 4] {
|
||||||
[self.r, self.g, self.b, self.a]
|
let a = alpha.unwrap_or(1.0);
|
||||||
|
[self.r * a, self.g * a, self.b * a, self.a * a]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[expect(dead_code)]
|
#[expect(dead_code)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue