1
0
Fork 0
forked from wry/wry

wl_surface: track if surface is fully opaque

This commit is contained in:
Julian Orth 2025-02-24 09:45:11 +01:00
parent 6243278f5f
commit c796602aab
8 changed files with 59 additions and 5 deletions

View file

@ -391,6 +391,7 @@ fn render_img(image: &InstantiatedCursorImage, renderer: &mut Renderer, x: Fixed
None,
AcquireSync::None,
ReleaseSync::None,
false,
);
}
}
@ -414,6 +415,7 @@ impl Cursor for StaticCursor {
None,
AcquireSync::None,
ReleaseSync::None,
false,
);
}
}
@ -455,6 +457,7 @@ impl Cursor for AnimatedCursor {
None,
AcquireSync::None,
ReleaseSync::None,
false,
);
}
}

View file

@ -192,6 +192,8 @@ pub struct CopyTexture {
pub acquire_sync: AcquireSync,
pub release_sync: ReleaseSync,
pub alpha: Option<f32>,
#[expect(dead_code)]
pub opaque: bool,
}
#[derive(Clone, Debug)]
@ -371,6 +373,7 @@ impl dyn GfxFramebuffer {
resv.cloned(),
acquire_sync,
release_sync,
false,
);
let clear = self.format().has_alpha.then_some(&Color::TRANSPARENT);
self.render(fb_acquire_sync, fb_release_sync, &ops, clear)

View file

@ -278,7 +278,7 @@ pub struct WlSurface {
role: Cell<SurfaceRole>,
pending: RefCell<Box<PendingState>>,
input_region: CloneCell<Option<Rc<Region>>>,
opaque_region: Cell<Option<Rc<Region>>>,
opaque_region: CloneCell<Option<Rc<Region>>>,
buffer_points: RefCell<BufferPoints>,
pub buffer_points_norm: RefCell<SampleRect>,
damage_matrix: Cell<DamageMatrix>,
@ -331,6 +331,7 @@ pub struct WlSurface {
clear_fifo_on_vblank: Cell<bool>,
commit_timer: CloneCell<Option<Rc<WpCommitTimerV1>>>,
before_latch_listener: EventListener<dyn BeforeLatchListener>,
is_opaque: Cell<bool>,
}
impl Debug for WlSurface {
@ -668,6 +669,7 @@ impl WlSurface {
clear_fifo_on_vblank: Default::default(),
commit_timer: Default::default(),
before_latch_listener: EventListener::new(slf.clone()),
is_opaque: Cell::new(false),
}
}
@ -1195,6 +1197,7 @@ impl WlSurface {
}
}
let transform_changed = viewport_changed || scale_changed || buffer_transform_changed;
let mut buffer_abs_pos_size_changed = false;
if buffer_changed || transform_changed {
let mut buffer_points = self.buffer_points.borrow_mut();
let mut buffer_points_norm = self.buffer_points_norm.borrow_mut();
@ -1288,6 +1291,7 @@ impl WlSurface {
.set(buffer_abs_pos.with_size(width, height).unwrap());
max_surface_size = (width.max(old_width), height.max(old_height));
damage_full = true;
buffer_abs_pos_size_changed = true;
}
}
let has_new_frame_requests = pending.frame_request.is_not_empty();
@ -1304,15 +1308,25 @@ impl WlSurface {
mem::swap(fbs.deref_mut(), &mut pending.presentation_feedback);
fbs.is_not_empty()
};
let mut opaque_region_changed = false;
{
if let Some(region) = pending.input_region.take() {
self.input_region.set(region);
self.client.state.tree_changed();
}
if let Some(region) = pending.opaque_region.take() {
opaque_region_changed = true;
self.opaque_region.set(region);
}
}
if opaque_region_changed || buffer_abs_pos_size_changed {
let pos = self.buffer_abs_pos.get().at_point(0, 0);
let is_opaque = match self.opaque_region.get() {
None => false,
Some(o) => o.contains_rect(&pos),
};
self.is_opaque.set(is_opaque);
}
let mut tearing_changed = false;
if let Some(tearing) = pending.tearing.take() {
if self.tearing.replace(tearing) != tearing {
@ -1636,6 +1650,10 @@ impl WlSurface {
pub fn alpha(&self) -> Option<f32> {
self.alpha.get()
}
pub fn opaque(&self) -> bool {
self.is_opaque.get()
}
}
object_base! {

View file

@ -225,6 +225,7 @@ impl GuiElement for Button {
None,
AcquireSync::None,
ReleaseSync::None,
false,
);
}
}
@ -325,6 +326,7 @@ impl GuiElement for Label {
None,
AcquireSync::None,
ReleaseSync::None,
false,
);
}
}

View file

@ -175,6 +175,26 @@ where
}
false
}
pub fn contains_rect(&self, rect: &Rect) -> bool {
if rect.is_empty() {
return true;
}
let mut y1 = rect.y1();
for r in self.rects() {
if r.y2() <= y1 || r.x2() <= rect.x1() {
continue;
}
if r.y1() > y1 || r.x1() > rect.x1() || r.x2() < rect.x2() {
return false;
}
y1 = r.y2();
if y1 >= rect.y2() {
return true;
}
}
false
}
}
impl<T> Deref for Region<T>

View file

@ -124,6 +124,7 @@ impl Renderer<'_> {
None,
AcquireSync::None,
ReleaseSync::None,
false,
);
}
if let Some(status) = &rd.status {
@ -141,6 +142,7 @@ impl Renderer<'_> {
None,
AcquireSync::None,
ReleaseSync::None,
false,
);
}
}
@ -219,6 +221,7 @@ impl Renderer<'_> {
None,
AcquireSync::None,
ReleaseSync::None,
false,
);
}
}
@ -264,6 +267,7 @@ impl Renderer<'_> {
None,
AcquireSync::None,
ReleaseSync::None,
false,
);
}
}
@ -379,7 +383,6 @@ impl Renderer<'_> {
} else {
size = self.base.scale_point(size.0, size.1);
}
let alpha = surface.alpha();
if let Some(children) = children.deref() {
macro_rules! render {
($children:expr) => {
@ -401,10 +404,10 @@ impl Renderer<'_> {
};
}
render!(&children.below);
self.render_buffer(surface, &buffer, alpha, x, y, *tpoints, size, bounds);
self.render_buffer(surface, &buffer, x, y, *tpoints, size, bounds);
render!(&children.above);
} else {
self.render_buffer(surface, &buffer, alpha, x, y, *tpoints, size, bounds);
self.render_buffer(surface, &buffer, x, y, *tpoints, size, bounds);
}
}
@ -412,13 +415,13 @@ impl Renderer<'_> {
&mut self,
surface: &WlSurface,
buffer: &Rc<SurfaceBuffer>,
alpha: Option<f32>,
x: i32,
y: i32,
tpoints: SampleRect,
tsize: (i32, i32),
bounds: Option<&Rect>,
) {
let alpha = surface.alpha();
if let Some(tex) = buffer.buffer.get_texture(surface) {
self.base.render_texture(
&tex,
@ -432,6 +435,7 @@ impl Renderer<'_> {
Some(buffer.clone()),
AcquireSync::Unnecessary,
buffer.release_sync,
surface.opaque(),
);
} else if let Some(color) = &buffer.buffer.color {
if let Some(rect) = Rect::new_sized(x, y, tsize.0, tsize.1) {
@ -496,6 +500,7 @@ impl Renderer<'_> {
None,
AcquireSync::None,
ReleaseSync::None,
false,
);
}
}

View file

@ -156,6 +156,7 @@ impl RendererBase<'_> {
buffer_resv: Option<Rc<dyn BufferResv>>,
acquire_sync: AcquireSync,
release_sync: ReleaseSync,
opaque: bool,
) {
let mut texcoord = tpoints.unwrap_or_else(SampleRect::identity);
@ -198,6 +199,7 @@ impl RendererBase<'_> {
buffer_resv,
acquire_sync,
release_sync,
opaque,
}));
}
}

View file

@ -1046,6 +1046,7 @@ impl State {
resv.cloned(),
acquire_sync.clone(),
release_sync,
false,
);
if render_hardware_cursors {
if let Some(cursor_user_group) = self.cursor_user_group_hardware_cursor.get() {