From 94968e2d0f2d0e903b741518e81ac9b590a0e57f Mon Sep 17 00:00:00 2001 From: Victor Brekenfeld Date: Tue, 14 Dec 2021 14:12:08 +0100 Subject: [PATCH] desktop: track damage per space/output --- src/backend/renderer/utils/mod.rs | 5 ++++- src/desktop/layer.rs | 11 +++++++---- src/desktop/space.rs | 28 ++++++++++++++++++--------- src/desktop/utils.rs | 32 ++++++++++++++++++++++++------- src/desktop/window.rs | 12 ++++++++---- 5 files changed, 63 insertions(+), 25 deletions(-) diff --git a/src/backend/renderer/utils/mod.rs b/src/backend/renderer/utils/mod.rs index 6949e88..ae61bfd 100644 --- a/src/backend/renderer/utils/mod.rs +++ b/src/backend/renderer/utils/mod.rs @@ -6,7 +6,7 @@ use crate::{ SurfaceAttributes, TraversalAction, }, }; -use std::cell::RefCell; +use std::{cell::RefCell, collections::HashSet}; use wayland_server::protocol::{wl_buffer::WlBuffer, wl_surface::WlSurface}; #[derive(Default)] @@ -15,6 +15,7 @@ pub(crate) struct SurfaceState { pub(crate) buffer_scale: i32, pub(crate) buffer: Option, pub(crate) texture: Option>, + pub(crate) damage_seen: HashSet<(usize, *const ())>, } impl SurfaceState { @@ -30,6 +31,7 @@ impl SurfaceState { } } self.texture = None; + self.damage_seen.clear(); } Some(BufferAssignment::Removed) => { // remove the contents @@ -38,6 +40,7 @@ impl SurfaceState { buffer.release(); }; self.texture = None; + self.damage_seen.clear(); } None => {} } diff --git a/src/desktop/layer.rs b/src/desktop/layer.rs index 7221631..c3176b4 100644 --- a/src/desktop/layer.rs +++ b/src/desktop/layer.rs @@ -1,6 +1,6 @@ use crate::{ backend::renderer::{utils::draw_surface_tree, Frame, ImportAll, Renderer, Texture}, - desktop::{utils::*, PopupManager}, + desktop::{utils::*, PopupManager, Space}, utils::{user_data::UserDataMap, Logical, Point, Rectangle}, wayland::{ compositor::with_states, @@ -423,17 +423,20 @@ impl LayerSurface { } /// Damage of all the surfaces of this layer - pub(super) fn accumulated_damage(&self) -> Vec> { + pub(super) fn accumulated_damage( + &self, + for_values: Option<(&Space, &Output)>, + ) -> Vec> { let mut damage = Vec::new(); if let Some(surface) = self.get_surface() { - damage.extend(damage_from_surface_tree(surface, (0, 0))); + damage.extend(damage_from_surface_tree(surface, (0, 0), for_values)); for (popup, location) in PopupManager::popups_for_surface(surface) .ok() .into_iter() .flatten() { if let Some(surface) = popup.get_surface() { - let popup_damage = damage_from_surface_tree(surface, location); + let popup_damage = damage_from_surface_tree(surface, location, for_values); damage.extend(popup_damage); } } diff --git a/src/desktop/space.rs b/src/desktop/space.rs index e54ce91..f4af0e9 100644 --- a/src/desktop/space.rs +++ b/src/desktop/space.rs @@ -80,7 +80,7 @@ pub enum SpaceError { #[derive(Debug)] pub struct Space { - id: usize, + pub(super) id: usize, // in z-order, back to front windows: IndexSet, outputs: Vec, @@ -450,10 +450,15 @@ impl Space { } else { // window stayed at its place let loc = window_loc(window, &self.id); - damage.extend(window.accumulated_damage().into_iter().map(|mut rect| { - rect.loc += loc; - rect - })); + damage.extend( + window + .accumulated_damage(Some((self, output))) + .into_iter() + .map(|mut rect| { + rect.loc += loc; + rect + }), + ); } } for layer in layer_map.layers() { @@ -467,10 +472,15 @@ impl Space { damage.push(geo); } else { let location = geo.loc; - damage.extend(layer.accumulated_damage().into_iter().map(|mut rect| { - rect.loc += location; - rect - })); + damage.extend( + layer + .accumulated_damage(Some((self, output))) + .into_iter() + .map(|mut rect| { + rect.loc += location; + rect + }), + ); } } diff --git a/src/desktop/utils.rs b/src/desktop/utils.rs index 8a08fdc..67c6433 100644 --- a/src/desktop/utils.rs +++ b/src/desktop/utils.rs @@ -1,14 +1,18 @@ use crate::{ backend::renderer::utils::SurfaceState, + desktop::Space, utils::{Logical, Point, Rectangle, Size}, - wayland::compositor::{ - with_surface_tree_downward, with_surface_tree_upward, Damage, SubsurfaceCachedState, - SurfaceAttributes, TraversalAction, + wayland::{ + compositor::{ + with_surface_tree_downward, with_surface_tree_upward, Damage, SubsurfaceCachedState, + SurfaceAttributes, TraversalAction, + }, + output::Output, }, }; use wayland_server::protocol::wl_surface; -use std::cell::RefCell; +use std::{cell::RefCell, sync::Arc}; impl SurfaceState { /// Returns the size of the surface. @@ -86,11 +90,13 @@ where pub fn damage_from_surface_tree

( surface: &wl_surface::WlSurface, location: P, + key: Option<(&Space, &Output)>, ) -> Vec> where P: Into>, { let mut damage = Vec::new(); + let key = key.map(|(space, output)| (space.id, Arc::as_ptr(&output.inner) as *const ())); with_surface_tree_upward( surface, location.into(), @@ -98,7 +104,11 @@ where let mut location = *location; if let Some(data) = states.data_map.get::>() { let data = data.borrow(); - if data.texture.is_none() { + if key + .as_ref() + .map(|key| !data.damage_seen.contains(key)) + .unwrap_or(true) + { if states.role == Some("subsurface") { let current = states.cached_state.current::(); location += current.location; @@ -110,10 +120,14 @@ where |_surface, states, location| { let mut location = *location; if let Some(data) = states.data_map.get::>() { - let data = data.borrow(); + let mut data = data.borrow_mut(); let attributes = states.cached_state.current::(); - if data.texture.is_none() { + if key + .as_ref() + .map(|key| !data.damage_seen.contains(key)) + .unwrap_or(true) + { if states.role == Some("subsurface") { let current = states.cached_state.current::(); location += current.location; @@ -127,6 +141,10 @@ where rect.loc += location; rect })); + + if let Some(key) = key { + data.damage_seen.insert(key); + } } } }, diff --git a/src/desktop/window.rs b/src/desktop/window.rs index 61a8478..02be9f7 100644 --- a/src/desktop/window.rs +++ b/src/desktop/window.rs @@ -1,9 +1,10 @@ use crate::{ backend::renderer::{utils::draw_surface_tree, Frame, ImportAll, Renderer, Texture}, - desktop::{utils::*, PopupManager}, + desktop::{utils::*, PopupManager, Space}, utils::{Logical, Point, Rectangle}, wayland::{ compositor::with_states, + output::Output, shell::xdg::{SurfaceCachedState, ToplevelSurface}, }, }; @@ -245,17 +246,20 @@ impl Window { } /// Damage of all the surfaces of this window - pub(super) fn accumulated_damage(&self) -> Vec> { + pub(super) fn accumulated_damage( + &self, + for_values: Option<(&Space, &Output)>, + ) -> Vec> { let mut damage = Vec::new(); if let Some(surface) = self.0.toplevel.get_surface() { - damage.extend(damage_from_surface_tree(surface, (0, 0))); + damage.extend(damage_from_surface_tree(surface, (0, 0), for_values)); for (popup, location) in PopupManager::popups_for_surface(surface) .ok() .into_iter() .flatten() { if let Some(surface) = popup.get_surface() { - let popup_damage = damage_from_surface_tree(surface, location); + let popup_damage = damage_from_surface_tree(surface, location, for_values); damage.extend(popup_damage); } }