desktop: track damage per space/output

This commit is contained in:
Victor Brekenfeld 2021-12-14 14:12:08 +01:00
parent 3b39d780fe
commit 94968e2d0f
5 changed files with 63 additions and 25 deletions

View File

@ -6,7 +6,7 @@ use crate::{
SurfaceAttributes, TraversalAction, SurfaceAttributes, TraversalAction,
}, },
}; };
use std::cell::RefCell; use std::{cell::RefCell, collections::HashSet};
use wayland_server::protocol::{wl_buffer::WlBuffer, wl_surface::WlSurface}; use wayland_server::protocol::{wl_buffer::WlBuffer, wl_surface::WlSurface};
#[derive(Default)] #[derive(Default)]
@ -15,6 +15,7 @@ pub(crate) struct SurfaceState {
pub(crate) buffer_scale: i32, pub(crate) buffer_scale: i32,
pub(crate) buffer: Option<WlBuffer>, pub(crate) buffer: Option<WlBuffer>,
pub(crate) texture: Option<Box<dyn std::any::Any + 'static>>, pub(crate) texture: Option<Box<dyn std::any::Any + 'static>>,
pub(crate) damage_seen: HashSet<(usize, *const ())>,
} }
impl SurfaceState { impl SurfaceState {
@ -30,6 +31,7 @@ impl SurfaceState {
} }
} }
self.texture = None; self.texture = None;
self.damage_seen.clear();
} }
Some(BufferAssignment::Removed) => { Some(BufferAssignment::Removed) => {
// remove the contents // remove the contents
@ -38,6 +40,7 @@ impl SurfaceState {
buffer.release(); buffer.release();
}; };
self.texture = None; self.texture = None;
self.damage_seen.clear();
} }
None => {} None => {}
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
backend::renderer::{utils::draw_surface_tree, Frame, ImportAll, Renderer, Texture}, backend::renderer::{utils::draw_surface_tree, Frame, ImportAll, Renderer, Texture},
desktop::{utils::*, PopupManager}, desktop::{utils::*, PopupManager, Space},
utils::{user_data::UserDataMap, Logical, Point, Rectangle}, utils::{user_data::UserDataMap, Logical, Point, Rectangle},
wayland::{ wayland::{
compositor::with_states, compositor::with_states,
@ -423,17 +423,20 @@ impl LayerSurface {
} }
/// Damage of all the surfaces of this layer /// Damage of all the surfaces of this layer
pub(super) fn accumulated_damage(&self) -> Vec<Rectangle<i32, Logical>> { pub(super) fn accumulated_damage(
&self,
for_values: Option<(&Space, &Output)>,
) -> Vec<Rectangle<i32, Logical>> {
let mut damage = Vec::new(); let mut damage = Vec::new();
if let Some(surface) = self.get_surface() { 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) for (popup, location) in PopupManager::popups_for_surface(surface)
.ok() .ok()
.into_iter() .into_iter()
.flatten() .flatten()
{ {
if let Some(surface) = popup.get_surface() { 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); damage.extend(popup_damage);
} }
} }

View File

@ -80,7 +80,7 @@ pub enum SpaceError {
#[derive(Debug)] #[derive(Debug)]
pub struct Space { pub struct Space {
id: usize, pub(super) id: usize,
// in z-order, back to front // in z-order, back to front
windows: IndexSet<Window>, windows: IndexSet<Window>,
outputs: Vec<Output>, outputs: Vec<Output>,
@ -450,10 +450,15 @@ impl Space {
} else { } else {
// window stayed at its place // window stayed at its place
let loc = window_loc(window, &self.id); let loc = window_loc(window, &self.id);
damage.extend(window.accumulated_damage().into_iter().map(|mut rect| { damage.extend(
window
.accumulated_damage(Some((self, output)))
.into_iter()
.map(|mut rect| {
rect.loc += loc; rect.loc += loc;
rect rect
})); }),
);
} }
} }
for layer in layer_map.layers() { for layer in layer_map.layers() {
@ -467,10 +472,15 @@ impl Space {
damage.push(geo); damage.push(geo);
} else { } else {
let location = geo.loc; let location = geo.loc;
damage.extend(layer.accumulated_damage().into_iter().map(|mut rect| { damage.extend(
layer
.accumulated_damage(Some((self, output)))
.into_iter()
.map(|mut rect| {
rect.loc += location; rect.loc += location;
rect rect
})); }),
);
} }
} }

View File

@ -1,14 +1,18 @@
use crate::{ use crate::{
backend::renderer::utils::SurfaceState, backend::renderer::utils::SurfaceState,
desktop::Space,
utils::{Logical, Point, Rectangle, Size}, utils::{Logical, Point, Rectangle, Size},
wayland::compositor::{ wayland::{
compositor::{
with_surface_tree_downward, with_surface_tree_upward, Damage, SubsurfaceCachedState, with_surface_tree_downward, with_surface_tree_upward, Damage, SubsurfaceCachedState,
SurfaceAttributes, TraversalAction, SurfaceAttributes, TraversalAction,
}, },
output::Output,
},
}; };
use wayland_server::protocol::wl_surface; use wayland_server::protocol::wl_surface;
use std::cell::RefCell; use std::{cell::RefCell, sync::Arc};
impl SurfaceState { impl SurfaceState {
/// Returns the size of the surface. /// Returns the size of the surface.
@ -86,11 +90,13 @@ where
pub fn damage_from_surface_tree<P>( pub fn damage_from_surface_tree<P>(
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
location: P, location: P,
key: Option<(&Space, &Output)>,
) -> Vec<Rectangle<i32, Logical>> ) -> Vec<Rectangle<i32, Logical>>
where where
P: Into<Point<i32, Logical>>, P: Into<Point<i32, Logical>>,
{ {
let mut damage = Vec::new(); let mut damage = Vec::new();
let key = key.map(|(space, output)| (space.id, Arc::as_ptr(&output.inner) as *const ()));
with_surface_tree_upward( with_surface_tree_upward(
surface, surface,
location.into(), location.into(),
@ -98,7 +104,11 @@ where
let mut location = *location; let mut location = *location;
if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() { if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() {
let data = data.borrow(); 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") { if states.role == Some("subsurface") {
let current = states.cached_state.current::<SubsurfaceCachedState>(); let current = states.cached_state.current::<SubsurfaceCachedState>();
location += current.location; location += current.location;
@ -110,10 +120,14 @@ where
|_surface, states, location| { |_surface, states, location| {
let mut location = *location; let mut location = *location;
if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() { if let Some(data) = states.data_map.get::<RefCell<SurfaceState>>() {
let data = data.borrow(); let mut data = data.borrow_mut();
let attributes = states.cached_state.current::<SurfaceAttributes>(); let attributes = states.cached_state.current::<SurfaceAttributes>();
if data.texture.is_none() { if key
.as_ref()
.map(|key| !data.damage_seen.contains(key))
.unwrap_or(true)
{
if states.role == Some("subsurface") { if states.role == Some("subsurface") {
let current = states.cached_state.current::<SubsurfaceCachedState>(); let current = states.cached_state.current::<SubsurfaceCachedState>();
location += current.location; location += current.location;
@ -127,6 +141,10 @@ where
rect.loc += location; rect.loc += location;
rect rect
})); }));
if let Some(key) = key {
data.damage_seen.insert(key);
}
} }
} }
}, },

View File

@ -1,9 +1,10 @@
use crate::{ use crate::{
backend::renderer::{utils::draw_surface_tree, Frame, ImportAll, Renderer, Texture}, backend::renderer::{utils::draw_surface_tree, Frame, ImportAll, Renderer, Texture},
desktop::{utils::*, PopupManager}, desktop::{utils::*, PopupManager, Space},
utils::{Logical, Point, Rectangle}, utils::{Logical, Point, Rectangle},
wayland::{ wayland::{
compositor::with_states, compositor::with_states,
output::Output,
shell::xdg::{SurfaceCachedState, ToplevelSurface}, shell::xdg::{SurfaceCachedState, ToplevelSurface},
}, },
}; };
@ -245,17 +246,20 @@ impl Window {
} }
/// Damage of all the surfaces of this window /// Damage of all the surfaces of this window
pub(super) fn accumulated_damage(&self) -> Vec<Rectangle<i32, Logical>> { pub(super) fn accumulated_damage(
&self,
for_values: Option<(&Space, &Output)>,
) -> Vec<Rectangle<i32, Logical>> {
let mut damage = Vec::new(); let mut damage = Vec::new();
if let Some(surface) = self.0.toplevel.get_surface() { 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) for (popup, location) in PopupManager::popups_for_surface(surface)
.ok() .ok()
.into_iter() .into_iter()
.flatten() .flatten()
{ {
if let Some(surface) = popup.get_surface() { 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); damage.extend(popup_damage);
} }
} }