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 {
|
pub fn opaque(&self) -> bool {
|
||||||
self.is_opaque.get()
|
self.is_opaque.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn opaque_region(&self) -> Option<Rc<Region>> {
|
||||||
|
self.opaque_region.get()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object_base! {
|
object_base! {
|
||||||
|
|
|
||||||
|
|
@ -177,11 +177,16 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_rect(&self, rect: &Rect) -> bool {
|
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() {
|
if rect.is_empty() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let mut y1 = rect.y1();
|
let mut y1 = rect.y1();
|
||||||
for r in self.rects() {
|
for r in self.rects() {
|
||||||
|
let r = map(r);
|
||||||
if r.y2() <= y1 || r.x2() <= rect.x1() {
|
if r.y2() <= y1 || r.x2() <= rect.x1() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -423,6 +423,10 @@ impl Renderer<'_> {
|
||||||
) {
|
) {
|
||||||
let alpha = surface.alpha();
|
let alpha = surface.alpha();
|
||||||
if let Some(tex) = buffer.buffer.get_texture(surface) {
|
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(
|
self.base.render_texture(
|
||||||
&tex,
|
&tex,
|
||||||
alpha,
|
alpha,
|
||||||
|
|
@ -435,7 +439,7 @@ impl Renderer<'_> {
|
||||||
Some(buffer.clone()),
|
Some(buffer.clone()),
|
||||||
AcquireSync::Unnecessary,
|
AcquireSync::Unnecessary,
|
||||||
buffer.release_sync,
|
buffer.release_sync,
|
||||||
surface.opaque(),
|
opaque,
|
||||||
);
|
);
|
||||||
} else if let Some(color) = &buffer.buffer.color {
|
} else if let Some(color) = &buffer.buffer.color {
|
||||||
if let Some(rect) = Rect::new_sized(x, y, tsize.0, tsize.1) {
|
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();
|
let (dx, dy) = surface.surface.extents.get().position();
|
||||||
self.render_surface(&surface.surface, x - dx, y - dy, None);
|
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