desktop: track damage per space/output
This commit is contained in:
parent
3b39d780fe
commit
94968e2d0f
|
@ -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 => {}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue