1
0
Fork 0
forked from wry/wry

wl_surface: check if partially-opaque surface is opaque within render bounds

This commit is contained in:
Julian Orth 2025-02-24 10:31:00 +01:00
parent c796602aab
commit 446779ab83
3 changed files with 33 additions and 1 deletions

View file

@ -1654,6 +1654,10 @@ impl WlSurface {
pub fn opaque(&self) -> bool {
self.is_opaque.get()
}
pub fn opaque_region(&self) -> Option<Rc<Region>> {
self.opaque_region.get()
}
}
object_base! {

View file

@ -177,11 +177,16 @@ where
}
pub fn contains_rect(&self, rect: &Rect) -> bool {
self.contains_rect2(rect, |r| *r)
}
pub fn contains_rect2(&self, rect: &Rect, map: impl Fn(&Rect<T>) -> Rect<T>) -> bool {
if rect.is_empty() {
return true;
}
let mut y1 = rect.y1();
for r in self.rects() {
let r = map(r);
if r.y2() <= y1 || r.x2() <= rect.x1() {
continue;
}

View file

@ -423,6 +423,10 @@ impl Renderer<'_> {
) {
let alpha = surface.alpha();
if let Some(tex) = buffer.buffer.get_texture(surface) {
let mut opaque = surface.opaque();
if !opaque && tex.format().has_alpha {
opaque = self.bounds_are_opaque(x, y, bounds, surface);
}
self.base.render_texture(
&tex,
alpha,
@ -435,7 +439,7 @@ impl Renderer<'_> {
Some(buffer.clone()),
AcquireSync::Unnecessary,
buffer.release_sync,
surface.opaque(),
opaque,
);
} else if let Some(color) = &buffer.buffer.color {
if let Some(rect) = Rect::new_sized(x, y, tsize.0, tsize.1) {
@ -519,4 +523,23 @@ impl Renderer<'_> {
let (dx, dy) = surface.surface.extents.get().position();
self.render_surface(&surface.surface, x - dx, y - dy, None);
}
fn bounds_are_opaque(
&self,
x: i32,
y: i32,
bounds: Option<&Rect>,
surface: &WlSurface,
) -> bool {
let Some(bounds) = bounds else {
return false;
};
let Some(region) = surface.opaque_region() else {
return false;
};
let surface_size = surface.buffer_abs_pos.get().at_point(0, 0);
let surface_size = self.base.scale_rect(surface_size);
let bounds = bounds.move_(-x, -y).intersect(surface_size);
region.contains_rect2(&bounds, |r| self.base.scale_rect(*r))
}
}