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,
},
};
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<WlBuffer>,
pub(crate) texture: Option<Box<dyn std::any::Any + 'static>>,
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 => {}
}

View File

@ -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<Rectangle<i32, Logical>> {
pub(super) fn accumulated_damage(
&self,
for_values: Option<(&Space, &Output)>,
) -> Vec<Rectangle<i32, Logical>> {
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);
}
}

View File

@ -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<Window>,
outputs: Vec<Output>,
@ -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
}),
);
}
}

View File

@ -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<P>(
surface: &wl_surface::WlSurface,
location: P,
key: Option<(&Space, &Output)>,
) -> Vec<Rectangle<i32, Logical>>
where
P: Into<Point<i32, Logical>>,
{
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::<RefCell<SurfaceState>>() {
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::<SubsurfaceCachedState>();
location += current.location;
@ -110,10 +120,14 @@ where
|_surface, states, location| {
let mut location = *location;
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>();
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::<SubsurfaceCachedState>();
location += current.location;
@ -127,6 +141,10 @@ where
rect.loc += location;
rect
}));
if let Some(key) = key {
data.damage_seen.insert(key);
}
}
}
},

View File

@ -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<Rectangle<i32, Logical>> {
pub(super) fn accumulated_damage(
&self,
for_values: Option<(&Space, &Output)>,
) -> Vec<Rectangle<i32, Logical>> {
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);
}
}