wl_surface: check if partially-opaque surface is opaque within render bounds
This commit is contained in:
parent
c796602aab
commit
446779ab83
3 changed files with 33 additions and 1 deletions
|
|
@ -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! {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue