Merge pull request #473 from dragonnn/render_layers

Add layer definition to RenderElement
This commit is contained in:
Victoria Brekenfeld 2022-01-24 16:01:05 +01:00 committed by GitHub
commit 8558253b13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 110 additions and 53 deletions

View File

@ -332,6 +332,12 @@ impl LayerMap {
self.layers.retain(|layer| layer.alive()); self.layers.retain(|layer| layer.alive());
self.surfaces.retain(|s| s.as_ref().is_alive()); self.surfaces.retain(|s| s.as_ref().is_alive());
} }
/// Returns layers count
#[allow(clippy::len_without_is_empty)] //we don't need is_empty on that struct for now, mark as allow
pub fn len(&self) -> usize {
self.layers.len()
}
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]

View File

@ -10,6 +10,33 @@ use std::{
}; };
use wayland_server::protocol::wl_surface::WlSurface; use wayland_server::protocol::wl_surface::WlSurface;
/// Indicates default values for some zindexs inside smithay
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum RenderZindex {
/// WlrLayer::Background default zindex
Background = 10,
/// WlrLayer::Bottom default zindex
Bottom = 20,
/// Default zindex for Windows
Shell = 30,
/// WlrLayer::Top default zindex
Top = 40,
/// Default zindex for Windows PopUps
Popups = 50,
/// Default Layer for RenderElements
Overlay = 60,
/// Default Layer for Overlay PopUp
PopupsOverlay = 70,
}
/// Elements rendered by [`Space::render_output`] in addition to windows, layers and popups.
pub type DynamicRenderElements<R> =
Box<dyn RenderElement<R, <R as Renderer>::Frame, <R as Renderer>::Error, <R as Renderer>::TextureId>>;
pub(super) type SpaceElem<R> =
dyn SpaceElement<R, <R as Renderer>::Frame, <R as Renderer>::Error, <R as Renderer>::TextureId>;
/// Trait for custom elements to be rendered during [`Space::render_output`]. /// Trait for custom elements to be rendered during [`Space::render_output`].
pub trait RenderElement<R, F, E, T> pub trait RenderElement<R, F, E, T>
where where
@ -58,6 +85,11 @@ where
damage: &[Rectangle<i32, Logical>], damage: &[Rectangle<i32, Logical>],
log: &slog::Logger, log: &slog::Logger,
) -> Result<(), R::Error>; ) -> Result<(), R::Error>;
/// Returns z_index of RenderElement, reverf too [`RenderZindex`] for default values
fn z_index(&self) -> u8 {
RenderZindex::Overlay as u8
}
} }
pub(crate) trait SpaceElement<R, F, E, T> pub(crate) trait SpaceElement<R, F, E, T>
@ -85,6 +117,7 @@ where
damage: &[Rectangle<i32, Logical>], damage: &[Rectangle<i32, Logical>],
log: &slog::Logger, log: &slog::Logger,
) -> Result<(), R::Error>; ) -> Result<(), R::Error>;
fn z_index(&self) -> u8;
} }
impl<R, F, E, T> SpaceElement<R, F, E, T> for Box<dyn RenderElement<R, F, E, T>> impl<R, F, E, T> SpaceElement<R, F, E, T> for Box<dyn RenderElement<R, F, E, T>>
@ -118,6 +151,10 @@ where
) -> Result<(), R::Error> { ) -> Result<(), R::Error> {
(&**self as &dyn RenderElement<R, F, E, T>).draw(renderer, frame, scale, location, damage, log) (&**self as &dyn RenderElement<R, F, E, T>).draw(renderer, frame, scale, location, damage, log)
} }
fn z_index(&self) -> u8 {
RenderElement::z_index(self.as_ref())
}
} }
/// Generic helper for drawing [`WlSurface`]s and their subsurfaces /// Generic helper for drawing [`WlSurface`]s and their subsurfaces

View File

@ -5,7 +5,7 @@ use crate::{
space::{Space, SpaceElement}, space::{Space, SpaceElement},
}, },
utils::{Logical, Point, Rectangle}, utils::{Logical, Point, Rectangle},
wayland::output::Output, wayland::{output::Output, shell::wlr_layer::Layer},
}; };
use std::{ use std::{
any::TypeId, any::TypeId,
@ -13,6 +13,8 @@ use std::{
collections::HashMap, collections::HashMap,
}; };
use super::RenderZindex;
#[derive(Default)] #[derive(Default)]
pub struct LayerState { pub struct LayerState {
pub drawn: bool, pub drawn: bool,
@ -69,4 +71,18 @@ where
} }
res res
} }
fn z_index(&self) -> u8 {
if let Some(layer) = self.layer() {
let z_index = match layer {
Layer::Background => RenderZindex::Background,
Layer::Bottom => RenderZindex::Bottom,
Layer::Top => RenderZindex::Top,
Layer::Overlay => RenderZindex::Overlay,
};
z_index as u8
} else {
0
}
}
} }

View File

@ -13,7 +13,6 @@ use crate::{
wayland::{ wayland::{
compositor::{get_parent, is_sync_subsurface}, compositor::{get_parent, is_sync_subsurface},
output::Output, output::Output,
shell::wlr_layer::Layer as WlrLayer,
}, },
}; };
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
@ -43,10 +42,6 @@ pub struct Space {
logger: ::slog::Logger, logger: ::slog::Logger,
} }
/// Elements rendered by [`Space::render_output`] in addition to windows, layers and popups.
pub type DynamicRenderElements<R> =
Box<dyn RenderElement<R, <R as Renderer>::Frame, <R as Renderer>::Error, <R as Renderer>::TextureId>>;
impl PartialEq for Space { impl PartialEq for Space {
fn eq(&self, other: &Space) -> bool { fn eq(&self, other: &Space) -> bool {
self.id == other.id self.id == other.id
@ -415,9 +410,6 @@ impl Space {
return Err(RenderError::UnmappedOutput); return Err(RenderError::UnmappedOutput);
} }
type SpaceElem<R> =
dyn SpaceElement<R, <R as Renderer>::Frame, <R as Renderer>::Error, <R as Renderer>::TextureId>;
let mut state = output_state(self.id, output); let mut state = output_state(self.id, output);
let output_size = output let output_size = output
.current_mode() .current_mode()
@ -439,23 +431,31 @@ impl Space {
.flat_map(|l| l.popup_elements::<R>(self.id)) .flat_map(|l| l.popup_elements::<R>(self.id))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut render_elements: Vec<&SpaceElem<R>> = Vec::with_capacity(
custom_elements.len()
+ layer_map.len()
+ self.windows.len()
+ window_popups.len()
+ layer_popups.len(),
);
render_elements.extend(custom_elements.iter().map(|l| l as &SpaceElem<R>));
render_elements.extend(self.windows.iter().map(|l| l as &SpaceElem<R>));
render_elements.extend(window_popups.iter().map(|l| l as &SpaceElem<R>));
render_elements.extend(layer_map.layers().map(|l| l as &SpaceElem<R>));
render_elements.extend(layer_popups.iter().map(|l| l as &SpaceElem<R>));
render_elements.sort_by_key(|e| e.z_index());
// This will hold all the damage we need for this rendering step // This will hold all the damage we need for this rendering step
let mut damage = Vec::<Rectangle<i32, Logical>>::new(); let mut damage = Vec::<Rectangle<i32, Logical>>::new();
// First add damage for windows gone // First add damage for windows gone
for old_toplevel in state for old_toplevel in state
.last_state .last_state
.iter() .iter()
.filter_map(|(id, geo)| { .filter_map(|(id, geo)| {
if !self if !render_elements.iter().any(|e| ToplevelId::from(*e) == *id) {
.windows
.iter()
.map(|w| w as &SpaceElem<R>)
.chain(window_popups.iter().map(|p| p as &SpaceElem<R>))
.chain(layer_map.layers().map(|l| l as &SpaceElem<R>))
.chain(layer_popups.iter().map(|p| p as &SpaceElem<R>))
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
.any(|e| ToplevelId::from(e) == *id)
{
Some(*geo) Some(*geo)
} else { } else {
None None
@ -468,17 +468,9 @@ impl Space {
} }
// lets iterate front to back and figure out, what new windows or unmoved windows we have // lets iterate front to back and figure out, what new windows or unmoved windows we have
for element in self for element in &render_elements {
.windows
.iter()
.map(|w| w as &SpaceElem<R>)
.chain(window_popups.iter().map(|p| p as &SpaceElem<R>))
.chain(layer_map.layers().map(|l| l as &SpaceElem<R>))
.chain(layer_popups.iter().map(|p| p as &SpaceElem<R>))
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
{
let geo = element.geometry(self.id); let geo = element.geometry(self.id);
let old_geo = state.last_state.get(&ToplevelId::from(element)).cloned(); let old_geo = state.last_state.get(&ToplevelId::from(*element)).cloned();
// window was moved or resized // window was moved or resized
if old_geo.map(|old_geo| old_geo != geo).unwrap_or(false) { if old_geo.map(|old_geo| old_geo != geo).unwrap_or(false) {
@ -551,22 +543,9 @@ impl Space {
.map(|geo| geo.to_f64().to_physical(state.render_scale).to_i32_round()) .map(|geo| geo.to_f64().to_physical(state.render_scale).to_i32_round())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
)?; )?;
// Then re-draw all windows & layers overlapping with a damage rect. // Then re-draw all windows & layers overlapping with a damage rect.
for element in layer_map for element in &render_elements {
.layers_on(WlrLayer::Background)
.chain(layer_map.layers_on(WlrLayer::Bottom))
.map(|l| l as &SpaceElem<R>)
.chain(self.windows.iter().map(|w| w as &SpaceElem<R>))
.chain(
layer_map
.layers_on(WlrLayer::Top)
.chain(layer_map.layers_on(WlrLayer::Overlay))
.map(|l| l as &SpaceElem<R>),
)
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
{
let geo = element.geometry(self.id); let geo = element.geometry(self.id);
if damage.iter().any(|d| d.overlaps(geo)) { if damage.iter().any(|d| d.overlaps(geo)) {
let loc = element.location(self.id); let loc = element.location(self.id);
@ -607,17 +586,11 @@ impl Space {
} }
// If rendering was successful capture the state and add the damage // If rendering was successful capture the state and add the damage
state.last_state = self state.last_state = render_elements
.windows
.iter() .iter()
.map(|w| w as &SpaceElem<R>)
.chain(window_popups.iter().map(|p| p as &SpaceElem<R>))
.chain(layer_map.layers().map(|l| l as &SpaceElem<R>))
.chain(layer_popups.iter().map(|p| p as &SpaceElem<R>))
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
.map(|elem| { .map(|elem| {
let geo = elem.geometry(self.id); let geo = elem.geometry(self.id);
(ToplevelId::from(elem), geo) (ToplevelId::from(*elem), geo)
}) })
.collect(); .collect();
state.old_damage.push_front(new_damage.clone()); state.old_damage.push_front(new_damage.clone());

View File

@ -8,14 +8,17 @@ use crate::{
window::Window, window::Window,
}, },
utils::{Logical, Point, Rectangle}, utils::{Logical, Point, Rectangle},
wayland::output::Output, wayland::{output::Output, shell::wlr_layer::Layer},
}; };
use std::any::TypeId; use std::any::TypeId;
use super::RenderZindex;
#[derive(Debug)] #[derive(Debug)]
pub struct RenderPopup { pub struct RenderPopup {
location: Point<i32, Logical>, location: Point<i32, Logical>,
popup: PopupKind, popup: PopupKind,
z_index: u8,
} }
impl Window { impl Window {
@ -39,6 +42,7 @@ impl Window {
RenderPopup { RenderPopup {
location: offset, location: offset,
popup, popup,
z_index: RenderZindex::Popups as u8,
} }
}) })
}) })
@ -48,7 +52,7 @@ impl Window {
} }
impl LayerSurface { impl LayerSurface {
pub(super) fn popup_elements<R>(&self, space_id: usize) -> impl Iterator<Item = RenderPopup> pub(super) fn popup_elements<R>(&self, space_id: usize) -> impl Iterator<Item = RenderPopup> + '_
where where
R: Renderer + ImportAll + 'static, R: Renderer + ImportAll + 'static,
R::TextureId: 'static, R::TextureId: 'static,
@ -67,9 +71,20 @@ impl LayerSurface {
.flatten() .flatten()
.map(move |(popup, location)| { .map(move |(popup, location)| {
let offset = loc + location - popup.geometry().loc; let offset = loc + location - popup.geometry().loc;
let z_index = if let Some(layer) = self.layer() {
if layer == Layer::Overlay {
RenderZindex::PopupsOverlay as u8
} else {
RenderZindex::Popups as u8
}
} else {
0
};
RenderPopup { RenderPopup {
location: offset, location: offset,
popup, popup,
z_index,
} }
}) })
}) })
@ -126,4 +141,8 @@ where
// popups are special, we track them, but they render with their parents // popups are special, we track them, but they render with their parents
Ok(()) Ok(())
} }
fn z_index(&self) -> u8 {
self.z_index
}
} }

View File

@ -13,6 +13,8 @@ use std::{
collections::HashMap, collections::HashMap,
}; };
use super::RenderZindex;
#[derive(Default)] #[derive(Default)]
pub struct WindowState { pub struct WindowState {
pub location: Point<i32, Logical>, pub location: Point<i32, Logical>,
@ -103,4 +105,8 @@ where
} }
res res
} }
fn z_index(&self) -> u8 {
RenderZindex::Shell as u8
}
} }