Add a SplitRenderElements type, with useful methods

`(w_elements, p_elements)` tuples are used in a bunch of places. A
struct with named fields is generally an improvement just due to the
fact the order is non-obvious.

But we can also add methods. In particular,
`extend_from_workspace_elements` abstracts out some of the more
redundant code in `workspace_elements`.

It would be nice to avoid allocation everywhere, but iterators would
complicate lifetimes, run into issues with needing multiple mutable
borrows to things like the `Renderer`, and be awkward in certain
functions without generator syntax. In any case, cosmic-comp already
relies on allocating vectors here.

If this abstraction is commonly useful in compositors, perhaps it could
be moved to Smithay.
This commit is contained in:
Ian Douglas Scott 2024-07-09 15:21:16 -07:00 committed by Victoria Brekenfeld
parent c506d94ac8
commit 94fecec9cb
9 changed files with 374 additions and 379 deletions

View file

@ -58,7 +58,7 @@ use smithay::{
desktop::{layer_map_for_output, PopupManager}, desktop::{layer_map_for_output, PopupManager},
input::Seat, input::Seat,
output::{Output, OutputNoMode}, output::{Output, OutputNoMode},
utils::{IsAlive, Logical, Monotonic, Point, Rectangle, Scale, Time, Transform}, utils::{IsAlive, Logical, Monotonic, Physical, Point, Rectangle, Scale, Time, Transform},
wayland::{ wayland::{
dmabuf::get_dmabuf, dmabuf::get_dmabuf,
shell::wlr_layer::Layer, shell::wlr_layer::Layer,
@ -464,6 +464,60 @@ where
#[cfg(not(feature = "debug"))] #[cfg(not(feature = "debug"))]
pub type EguiState = (); pub type EguiState = ();
#[derive(Clone, Debug)]
pub struct SplitRenderElements<E> {
pub w_elements: Vec<E>,
pub p_elements: Vec<E>,
}
impl<E> Default for SplitRenderElements<E> {
fn default() -> Self {
Self {
w_elements: Vec::new(),
p_elements: Vec::new(),
}
}
}
impl<E> SplitRenderElements<E> {
pub fn extend(&mut self, other: Self) {
self.w_elements.extend(other.w_elements);
self.p_elements.extend(other.p_elements);
}
pub fn extend_map<E2, F: FnMut(E2) -> E>(&mut self, other: SplitRenderElements<E2>, mut f: F) {
self.w_elements
.extend(other.w_elements.into_iter().map(&mut f));
self.p_elements
.extend(other.p_elements.into_iter().map(&mut f));
}
pub fn join(mut self) -> Vec<E> {
self.p_elements.extend(self.w_elements);
self.p_elements
}
}
impl<R> SplitRenderElements<CosmicElement<R>>
where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn extend_from_workspace_elements<E: Into<WorkspaceRenderElement<R>>>(
&mut self,
other: SplitRenderElements<E>,
offset: Point<i32, Physical>,
) {
self.extend_map(other, |element| {
CosmicElement::Workspace(RelocateRenderElement::from_element(
element.into(),
offset,
Relocate::Relative,
))
})
}
}
#[profiling::function] #[profiling::function]
pub fn workspace_elements<R>( pub fn workspace_elements<R>(
_gpu: Option<&DrmNode>, _gpu: Option<&DrmNode>,
@ -484,6 +538,8 @@ where
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
WorkspaceRenderElement<R>: RenderElement<R>, WorkspaceRenderElement<R>: RenderElement<R>,
{ {
let mut elements = SplitRenderElements::default();
let theme = shell.read().unwrap().theme().clone(); let theme = shell.read().unwrap().theme().clone();
let seats = shell let seats = shell
.read() .read()
@ -493,7 +549,7 @@ where
.cloned() .cloned()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut elements = cursor_elements( elements.p_elements.extend(cursor_elements(
renderer, renderer,
seats.iter(), seats.iter(),
&theme, &theme,
@ -501,7 +557,7 @@ where
output, output,
cursor_mode, cursor_mode,
exclude_workspace_overview, exclude_workspace_overview,
); ));
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
{ {
@ -525,7 +581,7 @@ where
) )
.map_err(FromGlesError::from_gles_error) .map_err(FromGlesError::from_gles_error)
.map_err(RenderError::Rendering)?; .map_err(RenderError::Rendering)?;
elements.push(fps_overlay.into()); elements.p_elements.push(fps_overlay.into());
} }
} }
@ -533,12 +589,12 @@ where
// If session locked, only show session lock surfaces // If session locked, only show session lock surfaces
if let Some(session_lock) = &shell.session_lock { if let Some(session_lock) = &shell.session_lock {
elements.extend( elements.p_elements.extend(
session_lock_elements(renderer, output, session_lock) session_lock_elements(renderer, output, session_lock)
.into_iter() .into_iter()
.map(|x| WorkspaceRenderElement::from(x).into()), .map(|x| WorkspaceRenderElement::from(x).into()),
); );
return Ok(elements); return Ok(elements.join());
} }
let theme = theme.cosmic(); let theme = theme.cosmic();
@ -586,20 +642,22 @@ where
.as_ref() .as_ref()
.filter(|f| !f.is_animating()) .filter(|f| !f.is_animating())
.is_some(); .is_some();
let (overlay_elements, overlay_popups) = let overlay_elements =
split_layer_elements(renderer, output, Layer::Overlay, exclude_workspace_overview); split_layer_elements(renderer, output, Layer::Overlay, exclude_workspace_overview);
// overlay is above everything // overlay is above everything
elements.extend(overlay_popups.into_iter().map(Into::into)); elements
elements.extend(overlay_elements.into_iter().map(Into::into)); .p_elements
.extend(overlay_elements.p_elements.into_iter().map(Into::into));
elements
.p_elements
.extend(overlay_elements.w_elements.into_iter().map(Into::into));
let mut window_elements = if !has_fullscreen { if !has_fullscreen {
let (top_elements, top_popups) = elements.extend_from_workspace_elements(
split_layer_elements(renderer, output, Layer::Top, exclude_workspace_overview); split_layer_elements(renderer, output, Layer::Top, exclude_workspace_overview),
elements.extend(top_popups.into_iter().map(Into::into)); (0, 0).into(),
top_elements.into_iter().map(Into::into).collect() );
} else {
Vec::new()
}; };
let active_hint = if shell.active_hint { let active_hint = if shell.active_hint {
@ -611,7 +669,7 @@ where
// overlay redirect windows // overlay redirect windows
// they need to be over sticky windows, because they could be popups of sticky windows, // they need to be over sticky windows, because they could be popups of sticky windows,
// and we can't differenciate that. // and we can't differenciate that.
elements.extend( elements.p_elements.extend(
shell shell
.override_redirect_windows .override_redirect_windows
.iter() .iter()
@ -632,13 +690,7 @@ where
1.0, 1.0,
) )
}) })
.map(|p_element| { .map(|p_element| p_element.into()),
CosmicElement::Workspace(RelocateRenderElement::from_element(
p_element,
(0, 0),
Relocate::Relative,
))
}),
); );
// sticky windows // sticky windows
@ -665,29 +717,17 @@ where
.then_some(last_active_seat) .then_some(last_active_seat)
.map(|seat| workspace.focus_stack.get(seat)); .map(|seat| workspace.focus_stack.get(seat));
let (w_elements, p_elements) = set.sticky_layer.render( elements.extend_from_workspace_elements(
renderer, set.sticky_layer.render(
current_focus.as_ref().and_then(|stack| stack.last()), renderer,
resize_indicator.clone(), current_focus.as_ref().and_then(|stack| stack.last()),
active_hint, resize_indicator.clone(),
alpha, active_hint,
theme, alpha,
theme,
),
(0, 0).into(),
); );
elements.extend(p_elements.into_iter().map(|p_element| {
CosmicElement::Workspace(RelocateRenderElement::from_element(
WorkspaceRenderElement::Window(p_element),
(0, 0),
Relocate::Relative,
))
}));
window_elements.extend(w_elements.into_iter().map(|w_element| {
CosmicElement::Workspace(RelocateRenderElement::from_element(
WorkspaceRenderElement::Window(w_element),
(0, 0),
Relocate::Relative,
))
}));
} }
let offset = match previous.as_ref() { let offset = match previous.as_ref() {
@ -729,48 +769,25 @@ where
} }
}); });
let (w_elements, p_elements) = workspace elements.extend_from_workspace_elements(
.render::<R>( workspace
renderer, .render::<R>(
(!move_active && is_active_space).then_some(last_active_seat), renderer,
overview.clone(), (!move_active && is_active_space).then_some(last_active_seat),
resize_indicator.clone(), overview.clone(),
active_hint, resize_indicator.clone(),
theme, active_hint,
) theme,
.map_err(|_| OutputNoMode)?; )
elements.extend(p_elements.into_iter().map(|p_element| { .map_err(|_| OutputNoMode)?,
CosmicElement::Workspace(RelocateRenderElement::from_element( offset.to_physical_precise_round(output_scale),
p_element, );
offset.to_physical_precise_round(output_scale),
Relocate::Relative,
))
}));
window_elements.extend(w_elements.into_iter().map(|w_element| {
CosmicElement::Workspace(RelocateRenderElement::from_element(
w_element,
offset.to_physical_precise_round(output_scale),
Relocate::Relative,
))
}));
if !has_fullscreen { if !has_fullscreen {
let (w_elements, p_elements) = elements.extend_from_workspace_elements(
background_layer_elements(renderer, output, exclude_workspace_overview); background_layer_elements(renderer, output, exclude_workspace_overview),
elements.extend(p_elements.into_iter().map(|p_element| { offset.to_physical_precise_round(output_scale),
CosmicElement::Workspace(RelocateRenderElement::from_element( );
p_element,
offset.to_physical_precise_round(output_scale),
Relocate::Relative,
))
}));
window_elements.extend(w_elements.into_iter().map(|w_element| {
CosmicElement::Workspace(RelocateRenderElement::from_element(
w_element,
offset.to_physical_precise_round(output_scale),
Relocate::Relative,
))
}));
} }
Point::<i32, Logical>::from(match (layout, *previous_idx < current.1) { Point::<i32, Logical>::from(match (layout, *previous_idx < current.1) {
@ -783,55 +800,28 @@ where
None => (0, 0).into(), None => (0, 0).into(),
}; };
let (w_elements, p_elements) = workspace elements.extend_from_workspace_elements(
.render::<R>( workspace
renderer, .render::<R>(
(!move_active && is_active_space).then_some(&last_active_seat), renderer,
overview, (!move_active && is_active_space).then_some(&last_active_seat),
resize_indicator, overview,
active_hint, resize_indicator,
theme, active_hint,
) theme,
.map_err(|_| OutputNoMode)?; )
elements.extend(p_elements.into_iter().map(|p_element| { .map_err(|_| OutputNoMode)?,
CosmicElement::Workspace(RelocateRenderElement::from_element( offset.to_physical_precise_round(output_scale),
p_element, );
offset.to_physical_precise_round(output_scale),
Relocate::Relative,
))
}));
window_elements.extend(w_elements.into_iter().map(|w_element| {
CosmicElement::Workspace(RelocateRenderElement::from_element(
w_element,
offset.to_physical_precise_round(output_scale),
Relocate::Relative,
))
}));
if !has_fullscreen { if !has_fullscreen {
let (w_elements, p_elements) = elements.extend_from_workspace_elements(
background_layer_elements(renderer, output, exclude_workspace_overview); background_layer_elements(renderer, output, exclude_workspace_overview),
offset.to_physical_precise_round(output_scale),
elements.extend(p_elements.into_iter().map(|p_element| { );
CosmicElement::Workspace(RelocateRenderElement::from_element(
p_element,
offset.to_physical_precise_round(output_scale),
Relocate::Relative,
))
}));
window_elements.extend(w_elements.into_iter().map(|w_element| {
CosmicElement::Workspace(RelocateRenderElement::from_element(
w_element,
offset.to_physical_precise_round(output_scale),
Relocate::Relative,
))
}));
} }
elements.extend(window_elements); Ok(elements.join())
Ok(elements)
} }
pub fn split_layer_elements<R>( pub fn split_layer_elements<R>(
@ -839,10 +829,7 @@ pub fn split_layer_elements<R>(
output: &Output, output: &Output,
layer: Layer, layer: Layer,
exclude_workspace_overview: bool, exclude_workspace_overview: bool,
) -> ( ) -> SplitRenderElements<WorkspaceRenderElement<R>>
Vec<WorkspaceRenderElement<R>>,
Vec<WorkspaceRenderElement<R>>,
)
where where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
<R as Renderer>::TextureId: Clone + 'static, <R as Renderer>::TextureId: Clone + 'static,
@ -853,8 +840,7 @@ where
let layer_map = layer_map_for_output(output); let layer_map = layer_map_for_output(output);
let output_scale = output.current_scale().fractional_scale(); let output_scale = output.current_scale().fractional_scale();
let mut popup_elements = Vec::new(); let mut elements = SplitRenderElements::default();
let mut layer_elements = Vec::new();
layer_map layer_map
.layers_on(layer) .layers_on(layer)
@ -870,35 +856,39 @@ where
let surface = surface.wl_surface(); let surface = surface.wl_surface();
let scale = Scale::from(output_scale); let scale = Scale::from(output_scale);
popup_elements.extend(PopupManager::popups_for_surface(surface).flat_map( elements
|(popup, popup_offset)| { .p_elements
let offset = (popup_offset - popup.geometry().loc) .extend(PopupManager::popups_for_surface(surface).flat_map(
.to_f64() |(popup, popup_offset)| {
.to_physical(scale) let offset = (popup_offset - popup.geometry().loc)
.to_i32_round(); .to_f64()
.to_physical(scale)
.to_i32_round();
render_elements_from_surface_tree( render_elements_from_surface_tree(
renderer, renderer,
popup.wl_surface(), popup.wl_surface(),
location + offset, location + offset,
scale, scale,
1.0, 1.0,
Kind::Unspecified, Kind::Unspecified,
) )
}, },
)); ));
layer_elements.extend(render_elements_from_surface_tree( elements
renderer, .w_elements
surface, .extend(render_elements_from_surface_tree(
location, renderer,
scale, surface,
1.0, location,
Kind::Unspecified, scale,
)); 1.0,
Kind::Unspecified,
));
}); });
(layer_elements, popup_elements) elements
} }
// bottom and background layer surfaces // bottom and background layer surfaces
@ -906,10 +896,7 @@ pub fn background_layer_elements<R>(
renderer: &mut R, renderer: &mut R,
output: &Output, output: &Output,
exclude_workspace_overview: bool, exclude_workspace_overview: bool,
) -> ( ) -> SplitRenderElements<WorkspaceRenderElement<R>>
Vec<WorkspaceRenderElement<R>>,
Vec<WorkspaceRenderElement<R>>,
)
where where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
<R as Renderer>::TextureId: Clone + 'static, <R as Renderer>::TextureId: Clone + 'static,
@ -917,17 +904,15 @@ where
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
WorkspaceRenderElement<R>: RenderElement<R>, WorkspaceRenderElement<R>: RenderElement<R>,
{ {
let (mut layer_elements, mut popup_elements) = let mut elements =
split_layer_elements(renderer, output, Layer::Bottom, exclude_workspace_overview); split_layer_elements(renderer, output, Layer::Bottom, exclude_workspace_overview);
let more = split_layer_elements( elements.extend(split_layer_elements(
renderer, renderer,
output, output,
Layer::Background, Layer::Background,
exclude_workspace_overview, exclude_workspace_overview,
); ));
layer_elements.extend(more.0); elements
popup_elements.extend(more.1);
(layer_elements, popup_elements)
} }
fn session_lock_elements<R>( fn session_lock_elements<R>(

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
backend::render::{ backend::render::{
element::{AsGlowFrame, AsGlowRenderer}, element::{AsGlowFrame, AsGlowRenderer},
GlMultiError, GlMultiFrame, GlMultiRenderer, GlMultiError, GlMultiFrame, GlMultiRenderer, SplitRenderElements,
}, },
state::State, state::State,
utils::{iced::IcedElementInternal, prelude::*}, utils::{iced::IcedElementInternal, prelude::*},
@ -663,7 +663,7 @@ impl CosmicMapped {
location: smithay::utils::Point<i32, smithay::utils::Physical>, location: smithay::utils::Point<i32, smithay::utils::Physical>,
scale: smithay::utils::Scale<f64>, scale: smithay::utils::Scale<f64>,
alpha: f32, alpha: f32,
) -> (Vec<C>, Vec<C>) ) -> SplitRenderElements<C>
where where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
<R as Renderer>::TextureId: Send + Clone + 'static, <R as Renderer>::TextureId: Send + Clone + 'static,
@ -842,27 +842,28 @@ impl CosmicMapped {
#[cfg(not(feature = "debug"))] #[cfg(not(feature = "debug"))]
let debug_elements = Vec::new(); let debug_elements = Vec::new();
#[cfg_attr(not(feature = "debug"), allow(unused_mut))] let mut elements = SplitRenderElements {
let (window_elements, popup_elements) = match &self.element { w_elements: debug_elements,
CosmicMappedInternal::Stack(s) => s p_elements: Vec::new(),
.split_render_elements::<R, CosmicMappedRenderElement<R>>(
renderer, location, scale, alpha,
),
CosmicMappedInternal::Window(w) => w
.split_render_elements::<R, CosmicMappedRenderElement<R>>(
renderer, location, scale, alpha,
),
_ => unreachable!(),
}; };
( #[cfg_attr(not(feature = "debug"), allow(unused_mut))]
debug_elements elements.extend_map(
.into_iter() match &self.element {
.map(C::from) CosmicMappedInternal::Stack(s) => s
.chain(window_elements.into_iter().map(C::from)) .split_render_elements::<R, CosmicMappedRenderElement<R>>(
.collect(), renderer, location, scale, alpha,
popup_elements.into_iter().map(C::from).collect(), ),
) CosmicMappedInternal::Window(w) => w
.split_render_elements::<R, CosmicMappedRenderElement<R>>(
renderer, location, scale, alpha,
),
_ => unreachable!(),
},
C::from,
);
elements
} }
pub(crate) fn update_theme(&self, theme: cosmic::Theme) { pub(crate) fn update_theme(&self, theme: cosmic::Theme) {

View file

@ -1,6 +1,9 @@
use super::{surface::RESIZE_BORDER, window::Focus, CosmicSurface}; use super::{surface::RESIZE_BORDER, window::Focus, CosmicSurface};
use crate::{ use crate::{
backend::render::cursor::{CursorShape, CursorState}, backend::render::{
cursor::{CursorShape, CursorState},
SplitRenderElements,
},
shell::{ shell::{
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{ReleaseMode, ResizeEdge}, grabs::{ReleaseMode, ResizeEdge},
@ -547,7 +550,7 @@ impl CosmicStack {
location: Point<i32, Physical>, location: Point<i32, Physical>,
scale: Scale<f64>, scale: Scale<f64>,
alpha: f32, alpha: f32,
) -> (Vec<C>, Vec<C>) ) -> SplitRenderElements<C>
where where
R: Renderer + ImportAll + ImportMem, R: Renderer + ImportAll + ImportMem,
<R as Renderer>::TextureId: Send + Clone + 'static, <R as Renderer>::TextureId: Send + Clone + 'static,
@ -564,30 +567,28 @@ impl CosmicStack {
let stack_loc = location + offset; let stack_loc = location + offset;
let window_loc = location + Point::from((0, (TAB_HEIGHT as f64 * scale.y) as i32)); let window_loc = location + Point::from((0, (TAB_HEIGHT as f64 * scale.y) as i32));
let elements = AsRenderElements::<R>::render_elements::<CosmicStackRenderElement<R>>( let w_elements = AsRenderElements::<R>::render_elements::<CosmicStackRenderElement<R>>(
&self.0, renderer, stack_loc, scale, alpha, &self.0, renderer, stack_loc, scale, alpha,
); );
let (window_elements, popup_elements) = self.0.with_program(|p| { let mut elements = SplitRenderElements {
let windows = p.windows.lock().unwrap(); w_elements: w_elements.into_iter().map(C::from).collect(),
let active = p.active.load(Ordering::SeqCst); p_elements: Vec::new(),
};
let (window_elements, popup_elements) = windows[active] elements.extend_map(
.split_render_elements::<R, CosmicStackRenderElement<R>>( self.0.with_program(|p| {
let windows = p.windows.lock().unwrap();
let active = p.active.load(Ordering::SeqCst);
windows[active].split_render_elements::<R, CosmicStackRenderElement<R>>(
renderer, window_loc, scale, alpha, renderer, window_loc, scale, alpha,
); )
}),
C::from,
);
(window_elements, popup_elements) elements
});
(
elements
.into_iter()
.map(C::from)
.chain(window_elements.into_iter().map(C::from))
.collect(),
popup_elements.into_iter().map(C::from).collect(),
)
} }
pub(crate) fn set_theme(&self, theme: cosmic::Theme) { pub(crate) fn set_theme(&self, theme: cosmic::Theme) {

View file

@ -42,6 +42,7 @@ use smithay::{
}; };
use crate::{ use crate::{
backend::render::SplitRenderElements,
state::{State, SurfaceDmabufFeedback}, state::{State, SurfaceDmabufFeedback},
utils::prelude::*, utils::prelude::*,
wayland::handlers::decoration::PreferredDecorationMode, wayland::handlers::decoration::PreferredDecorationMode,
@ -563,7 +564,7 @@ impl CosmicSurface {
location: smithay::utils::Point<i32, smithay::utils::Physical>, location: smithay::utils::Point<i32, smithay::utils::Physical>,
scale: smithay::utils::Scale<f64>, scale: smithay::utils::Scale<f64>,
alpha: f32, alpha: f32,
) -> (Vec<C>, Vec<C>) ) -> SplitRenderElements<C>
where where
R: Renderer + ImportAll, R: Renderer + ImportAll,
<R as Renderer>::TextureId: Clone + 'static, <R as Renderer>::TextureId: Clone + 'static,
@ -573,7 +574,7 @@ impl CosmicSurface {
WindowSurface::Wayland(toplevel) => { WindowSurface::Wayland(toplevel) => {
let surface = toplevel.wl_surface(); let surface = toplevel.wl_surface();
let popup_render_elements = PopupManager::popups_for_surface(surface) let p_elements = PopupManager::popups_for_surface(surface)
.flat_map(|(popup, popup_offset)| { .flat_map(|(popup, popup_offset)| {
let offset = (self.0.geometry().loc + popup_offset - popup.geometry().loc) let offset = (self.0.geometry().loc + popup_offset - popup.geometry().loc)
.to_physical_precise_round(scale); .to_physical_precise_round(scale);
@ -589,7 +590,7 @@ impl CosmicSurface {
}) })
.collect(); .collect();
let window_render_elements = render_elements_from_surface_tree( let w_elements = render_elements_from_surface_tree(
renderer, renderer,
surface, surface,
location, location,
@ -598,12 +599,15 @@ impl CosmicSurface {
element::Kind::Unspecified, element::Kind::Unspecified,
); );
(window_render_elements, popup_render_elements) SplitRenderElements {
w_elements,
p_elements,
}
} }
WindowSurface::X11(surface) => ( WindowSurface::X11(surface) => SplitRenderElements {
surface.render_elements(renderer, location, scale, alpha), w_elements: surface.render_elements(renderer, location, scale, alpha),
Vec::new(), p_elements: Vec::new(),
), },
} }
} }

View file

@ -1,5 +1,8 @@
use crate::{ use crate::{
backend::render::cursor::{CursorShape, CursorState}, backend::render::{
cursor::{CursorShape, CursorState},
SplitRenderElements,
},
shell::{ shell::{
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{ReleaseMode, ResizeEdge}, grabs::{ReleaseMode, ResizeEdge},
@ -317,7 +320,7 @@ impl CosmicWindow {
location: smithay::utils::Point<i32, smithay::utils::Physical>, location: smithay::utils::Point<i32, smithay::utils::Physical>,
scale: smithay::utils::Scale<f64>, scale: smithay::utils::Scale<f64>,
alpha: f32, alpha: f32,
) -> (Vec<C>, Vec<C>) ) -> SplitRenderElements<C>
where where
R: Renderer + ImportAll + ImportMem, R: Renderer + ImportAll + ImportMem,
<R as Renderer>::TextureId: Send + Clone + 'static, <R as Renderer>::TextureId: Send + Clone + 'static,
@ -331,12 +334,17 @@ impl CosmicWindow {
location location
}; };
let (mut window_elements, popup_elements) = self.0.with_program(|p| { let mut elements = SplitRenderElements::default();
p.window
.split_render_elements::<R, CosmicWindowRenderElement<R>>( elements.extend_map(
renderer, window_loc, scale, alpha, self.0.with_program(|p| {
) p.window
}); .split_render_elements::<R, CosmicWindowRenderElement<R>>(
renderer, window_loc, scale, alpha,
)
}),
C::from,
);
if has_ssd { if has_ssd {
let ssd_loc = location let ssd_loc = location
@ -344,15 +352,16 @@ impl CosmicWindow {
.0 .0
.with_program(|p| p.window.geometry().loc) .with_program(|p| p.window.geometry().loc)
.to_physical_precise_round(scale); .to_physical_precise_round(scale);
window_elements.extend(AsRenderElements::<R>::render_elements::< elements.w_elements.extend(
CosmicWindowRenderElement<R>, AsRenderElements::<R>::render_elements::<CosmicWindowRenderElement<R>>(
>(&self.0, renderer, ssd_loc, scale, alpha)) &self.0, renderer, ssd_loc, scale, alpha,
)
.into_iter()
.map(C::from),
)
} }
( elements
window_elements.into_iter().map(C::from).collect(),
popup_elements.into_iter().map(C::from).collect(),
)
} }
pub(crate) fn set_theme(&self, theme: cosmic::Theme) { pub(crate) fn set_theme(&self, theme: cosmic::Theme) {

View file

@ -4,7 +4,7 @@ use crate::{
backend::render::{ backend::render::{
cursor::{CursorShape, CursorState}, cursor::{CursorShape, CursorState},
element::AsGlowRenderer, element::AsGlowRenderer,
BackdropShader, IndicatorShader, Key, Usage, BackdropShader, IndicatorShader, Key, SplitRenderElements, Usage,
}, },
shell::{ shell::{
element::{ element::{
@ -182,7 +182,10 @@ impl MoveGrabState {
_ => vec![], _ => vec![],
}; };
let (window_elements, popup_elements) = self let SplitRenderElements {
w_elements,
p_elements,
} = self
.window .window
.split_render_elements::<R, CosmicMappedRenderElement<R>>( .split_render_elements::<R, CosmicMappedRenderElement<R>>(
renderer, renderer,
@ -202,9 +205,9 @@ impl MoveGrabState {
1.0, 1.0,
) )
}) })
.chain(popup_elements) .chain(p_elements)
.chain(focus_element) .chain(focus_element)
.chain(window_elements.into_iter().map(|elem| match elem { .chain(w_elements.into_iter().map(|elem| match elem {
CosmicMappedRenderElement::Stack(stack) => { CosmicMappedRenderElement::Stack(stack) => {
CosmicMappedRenderElement::GrabbedStack( CosmicMappedRenderElement::GrabbedStack(
RescaleRenderElement::from_element( RescaleRenderElement::from_element(

View file

@ -24,7 +24,7 @@ use smithay::{
}; };
use crate::{ use crate::{
backend::render::{element::AsGlowRenderer, IndicatorShader, Key, Usage}, backend::render::{element::AsGlowRenderer, IndicatorShader, Key, SplitRenderElements, Usage},
shell::{ shell::{
element::{ element::{
resize_indicator::ResizeIndicator, resize_indicator::ResizeIndicator,
@ -1270,10 +1270,7 @@ impl FloatingLayout {
indicator_thickness: u8, indicator_thickness: u8,
alpha: f32, alpha: f32,
theme: &cosmic::theme::CosmicTheme, theme: &cosmic::theme::CosmicTheme,
) -> ( ) -> SplitRenderElements<CosmicMappedRenderElement<R>>
Vec<CosmicMappedRenderElement<R>>,
Vec<CosmicMappedRenderElement<R>>,
)
where where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
<R as Renderer>::TextureId: Send + Clone + 'static, <R as Renderer>::TextureId: Send + Clone + 'static,
@ -1288,8 +1285,7 @@ impl FloatingLayout {
}; };
let output_scale = output.current_scale().fractional_scale(); let output_scale = output.current_scale().fractional_scale();
let mut window_elements = Vec::new(); let mut elements = SplitRenderElements::default();
let mut popup_elements = Vec::new();
for elem in self for elem in self
.animations .animations
@ -1305,7 +1301,10 @@ impl FloatingLayout {
.unwrap_or_else(|| (self.space.element_geometry(elem).unwrap().as_local(), alpha)); .unwrap_or_else(|| (self.space.element_geometry(elem).unwrap().as_local(), alpha));
let render_location = geometry.loc - elem.geometry().loc.as_local(); let render_location = geometry.loc - elem.geometry().loc.as_local();
let (mut w_elements, p_elements) = elem.split_render_elements( let SplitRenderElements {
mut w_elements,
p_elements,
} = elem.split_render_elements(
renderer, renderer,
render_location render_location
.as_logical() .as_logical()
@ -1388,7 +1387,7 @@ impl FloatingLayout {
resize.resize(resize_geometry.size.as_logical()); resize.resize(resize_geometry.size.as_logical());
resize.output_enter(output, Rectangle::default() /* unused */); resize.output_enter(output, Rectangle::default() /* unused */);
window_elements.extend( elements.w_elements.extend(
resize resize
.render_elements::<CosmicWindowRenderElement<R>>( .render_elements::<CosmicWindowRenderElement<R>>(
renderer, renderer,
@ -1420,15 +1419,15 @@ impl FloatingLayout {
active_window_hint.blue, active_window_hint.blue,
], ],
); );
window_elements.push(element.into()); elements.w_elements.push(element.into());
} }
} }
window_elements.extend(w_elements); elements.w_elements.extend(w_elements);
popup_elements.extend(p_elements); elements.p_elements.extend(p_elements);
} }
(window_elements, popup_elements) elements
} }
fn gaps(&self) -> (i32, i32) { fn gaps(&self) -> (i32, i32) {

View file

@ -2,8 +2,8 @@
use crate::{ use crate::{
backend::render::{ backend::render::{
element::AsGlowRenderer, BackdropShader, IndicatorShader, Key, Usage, ACTIVE_GROUP_COLOR, element::AsGlowRenderer, BackdropShader, IndicatorShader, Key, SplitRenderElements, Usage,
GROUP_COLOR, ACTIVE_GROUP_COLOR, GROUP_COLOR,
}, },
shell::{ shell::{
element::{ element::{
@ -3849,13 +3849,7 @@ impl TilingLayout {
resize_indicator: Option<(ResizeMode, ResizeIndicator)>, resize_indicator: Option<(ResizeMode, ResizeIndicator)>,
indicator_thickness: u8, indicator_thickness: u8,
theme: &cosmic::theme::CosmicTheme, theme: &cosmic::theme::CosmicTheme,
) -> Result< ) -> Result<SplitRenderElements<CosmicMappedRenderElement<R>>, OutputNotMapped>
(
Vec<CosmicMappedRenderElement<R>>,
Vec<CosmicMappedRenderElement<R>>,
),
OutputNotMapped,
>
where where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
<R as Renderer>::TextureId: Send + Clone + 'static, <R as Renderer>::TextureId: Send + Clone + 'static,
@ -3888,8 +3882,7 @@ impl TilingLayout {
}; };
let draw_groups = overview.0.alpha(); let draw_groups = overview.0.alpha();
let mut window_elements = Vec::new(); let mut elements = SplitRenderElements::default();
let mut popup_elements = Vec::new();
let is_overview = !matches!(overview.0, OverviewMode::None); let is_overview = !matches!(overview.0, OverviewMode::None);
let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_))))
@ -3924,7 +3917,7 @@ impl TilingLayout {
.unzip(); .unzip();
// all old windows we want to fade out // all old windows we want to fade out
let (w_elements, p_elements) = render_old_tree( elements.extend(render_old_tree(
reference_tree, reference_tree,
target_tree, target_tree,
renderer, renderer,
@ -3934,9 +3927,7 @@ impl TilingLayout {
indicator_thickness, indicator_thickness,
swap_desc.is_some(), swap_desc.is_some(),
theme, theme,
); ));
window_elements.extend(w_elements);
popup_elements.extend(p_elements);
geometries geometries
} else { } else {
@ -3964,7 +3955,7 @@ impl TilingLayout {
.unzip(); .unzip();
// all alive windows // all alive windows
let (w_elements, p_elements) = render_new_tree( elements.extend(render_new_tree(
target_tree, target_tree,
reference_tree, reference_tree,
renderer, renderer,
@ -3992,16 +3983,14 @@ impl TilingLayout {
&self.swapping_stack_surface_id, &self.swapping_stack_surface_id,
&self.placeholder_id, &self.placeholder_id,
theme, theme,
); ));
window_elements.extend(w_elements);
popup_elements.extend(p_elements);
// tiling hints // tiling hints
if let Some(group_elements) = group_elements { if let Some(group_elements) = group_elements {
window_elements.extend(group_elements); elements.w_elements.extend(group_elements);
} }
Ok((window_elements, popup_elements)) Ok(elements)
} }
fn gaps(&self) -> (i32, i32) { fn gaps(&self) -> (i32, i32) {
@ -4697,10 +4686,7 @@ fn render_old_tree<R>(
indicator_thickness: u8, indicator_thickness: u8,
is_swap_mode: bool, is_swap_mode: bool,
theme: &cosmic::theme::CosmicTheme, theme: &cosmic::theme::CosmicTheme,
) -> ( ) -> SplitRenderElements<CosmicMappedRenderElement<R>>
Vec<CosmicMappedRenderElement<R>>,
Vec<CosmicMappedRenderElement<R>>,
)
where where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
<R as Renderer>::TextureId: Send + Clone + 'static, <R as Renderer>::TextureId: Send + Clone + 'static,
@ -4709,8 +4695,7 @@ where
CosmicStackRenderElement<R>: RenderElement<R>, CosmicStackRenderElement<R>: RenderElement<R>,
{ {
let window_hint = crate::theme::active_window_hint(theme); let window_hint = crate::theme::active_window_hint(theme);
let mut window_elements = Vec::new(); let mut elements = SplitRenderElements::default();
let mut popup_elements = Vec::new();
if let Some(root) = reference_tree.root_node_id() { if let Some(root) = reference_tree.root_node_id() {
let geometries = geometries.unwrap_or_default(); let geometries = geometries.unwrap_or_default();
@ -4780,62 +4765,68 @@ where
}; };
let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale); let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale);
let (w_elements, p_elements) = mapped let SplitRenderElements {
.split_render_elements::<R, CosmicMappedRenderElement<R>>( w_elements,
renderer, p_elements,
geo.loc.as_logical().to_physical_precise_round(output_scale) } = mapped.split_render_elements::<R, CosmicMappedRenderElement<R>>(
- elem_geometry.loc, renderer,
Scale::from(output_scale), geo.loc.as_logical().to_physical_precise_round(output_scale)
alpha, - elem_geometry.loc,
); Scale::from(output_scale),
alpha,
);
window_elements.extend(w_elements.into_iter().flat_map(|element| { elements
match element { .w_elements
CosmicMappedRenderElement::Stack(elem) => constrain_render_elements( .extend(w_elements.into_iter().flat_map(|element| {
std::iter::once(elem), match element {
geo.loc.as_logical().to_physical_precise_round(output_scale) CosmicMappedRenderElement::Stack(elem) => constrain_render_elements(
- elem_geometry.loc, std::iter::once(elem),
geo.as_logical().to_physical_precise_round(output_scale), geo.loc.as_logical().to_physical_precise_round(output_scale)
elem_geometry, - elem_geometry.loc,
ConstrainScaleBehavior::Stretch, geo.as_logical().to_physical_precise_round(output_scale),
ConstrainAlign::CENTER, elem_geometry,
output_scale, ConstrainScaleBehavior::Stretch,
) ConstrainAlign::CENTER,
.next() output_scale,
.map(CosmicMappedRenderElement::TiledStack), )
CosmicMappedRenderElement::Window(elem) => constrain_render_elements( .next()
std::iter::once(elem), .map(CosmicMappedRenderElement::TiledStack),
geo.loc.as_logical().to_physical_precise_round(output_scale) CosmicMappedRenderElement::Window(elem) => constrain_render_elements(
- elem_geometry.loc, std::iter::once(elem),
geo.as_logical().to_physical_precise_round(output_scale), geo.loc.as_logical().to_physical_precise_round(output_scale)
elem_geometry, - elem_geometry.loc,
ConstrainScaleBehavior::Stretch, geo.as_logical().to_physical_precise_round(output_scale),
ConstrainAlign::CENTER, elem_geometry,
output_scale, ConstrainScaleBehavior::Stretch,
) ConstrainAlign::CENTER,
.next() output_scale,
.map(CosmicMappedRenderElement::TiledWindow), )
x => Some(x), .next()
} .map(CosmicMappedRenderElement::TiledWindow),
})); x => Some(x),
}
}));
if minimize_geo.is_some() && indicator_thickness > 0 { if minimize_geo.is_some() && indicator_thickness > 0 {
window_elements.push(CosmicMappedRenderElement::FocusIndicator( elements
IndicatorShader::focus_element( .w_elements
renderer, .push(CosmicMappedRenderElement::FocusIndicator(
Key::Window(Usage::FocusIndicator, mapped.clone().key()), IndicatorShader::focus_element(
geo, renderer,
indicator_thickness, Key::Window(Usage::FocusIndicator, mapped.clone().key()),
output_scale, geo,
alpha, indicator_thickness,
[window_hint.red, window_hint.green, window_hint.blue], output_scale,
), alpha,
)); [window_hint.red, window_hint.green, window_hint.blue],
),
));
} }
popup_elements.extend(p_elements); elements.p_elements.extend(p_elements);
}); });
} }
(window_elements, popup_elements) elements
} }
fn render_new_tree<R>( fn render_new_tree<R>(
@ -4857,10 +4848,7 @@ fn render_new_tree<R>(
swapping_stack_surface_id: &Id, swapping_stack_surface_id: &Id,
placeholder_id: &Id, placeholder_id: &Id,
theme: &cosmic::theme::CosmicTheme, theme: &cosmic::theme::CosmicTheme,
) -> ( ) -> SplitRenderElements<CosmicMappedRenderElement<R>>
Vec<CosmicMappedRenderElement<R>>,
Vec<CosmicMappedRenderElement<R>>,
)
where where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
<R as Renderer>::TextureId: Send + Clone + 'static, <R as Renderer>::TextureId: Send + Clone + 'static,
@ -5249,15 +5237,17 @@ where
if let Data::Mapped { mapped, .. } = data { if let Data::Mapped { mapped, .. } = data {
let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale); let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale);
let (mut w_elements, p_elements) = mapped let SplitRenderElements {
.split_render_elements::<R, CosmicMappedRenderElement<R>>( mut w_elements,
renderer, p_elements,
//original_location, } = mapped.split_render_elements::<R, CosmicMappedRenderElement<R>>(
geo.loc.as_logical().to_physical_precise_round(output_scale) renderer,
- elem_geometry.loc, //original_location,
Scale::from(output_scale), geo.loc.as_logical().to_physical_precise_round(output_scale)
alpha, - elem_geometry.loc,
); Scale::from(output_scale),
alpha,
);
if swap_desc if swap_desc
.as_ref() .as_ref()
.filter(|swap_desc| swap_desc.node == node_id) .filter(|swap_desc| swap_desc.node == node_id)
@ -5376,7 +5366,10 @@ where
.chain(group_backdrop.into_iter().map(Into::into)) .chain(group_backdrop.into_iter().map(Into::into))
.collect(); .collect();
(window_elements, popup_elements) SplitRenderElements {
w_elements: window_elements,
p_elements: popup_elements,
}
} }
fn scale_to_center<C>( fn scale_to_center<C>(

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
backend::render::{ backend::render::{
element::{AsGlowFrame, AsGlowRenderer}, element::{AsGlowFrame, AsGlowRenderer},
BackdropShader, GlMultiError, GlMultiFrame, GlMultiRenderer, BackdropShader, GlMultiError, GlMultiFrame, GlMultiRenderer, SplitRenderElements,
}, },
shell::{ shell::{
layout::{floating::FloatingLayout, tiling::TilingLayout}, layout::{floating::FloatingLayout, tiling::TilingLayout},
@ -1005,13 +1005,7 @@ impl Workspace {
resize_indicator: Option<(ResizeMode, ResizeIndicator)>, resize_indicator: Option<(ResizeMode, ResizeIndicator)>,
indicator_thickness: u8, indicator_thickness: u8,
theme: &CosmicTheme, theme: &CosmicTheme,
) -> Result< ) -> Result<SplitRenderElements<WorkspaceRenderElement<R>>, OutputNotMapped>
(
Vec<WorkspaceRenderElement<R>>,
Vec<WorkspaceRenderElement<R>>,
),
OutputNotMapped,
>
where where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
<R as Renderer>::TextureId: Send + Clone + 'static, <R as Renderer>::TextureId: Send + Clone + 'static,
@ -1020,8 +1014,7 @@ impl Workspace {
CosmicStackRenderElement<R>: RenderElement<R>, CosmicStackRenderElement<R>: RenderElement<R>,
WorkspaceRenderElement<R>: RenderElement<R>, WorkspaceRenderElement<R>: RenderElement<R>,
{ {
let mut window_elements = Vec::new(); let mut elements = SplitRenderElements::default();
let mut popup_elements = Vec::new();
let output_scale = self.output.current_scale().fractional_scale(); let output_scale = self.output.current_scale().fractional_scale();
let zone = { let zone = {
@ -1104,7 +1097,10 @@ impl Workspace {
y: target_geo.size.h as f64 / bbox.size.h as f64, y: target_geo.size.h as f64 / bbox.size.h as f64,
}; };
let (w_elements, p_elements) = fullscreen let SplitRenderElements {
w_elements,
p_elements,
} = fullscreen
.surface .surface
.split_render_elements::<R, CosmicWindowRenderElement<R>>( .split_render_elements::<R, CosmicWindowRenderElement<R>>(
renderer, renderer,
@ -1112,13 +1108,15 @@ impl Workspace {
output_scale.into(), output_scale.into(),
alpha, alpha,
); );
window_elements.extend( elements.w_elements.extend(
w_elements w_elements
.into_iter() .into_iter()
.map(|elem| RescaleRenderElement::from_element(elem, render_loc, scale)) .map(|elem| RescaleRenderElement::from_element(elem, render_loc, scale))
.map(Into::into), .map(Into::into),
); );
popup_elements.extend(p_elements.into_iter().map(Into::into)); elements
.p_elements
.extend(p_elements.into_iter().map(Into::into))
} }
if self if self
@ -1150,16 +1148,17 @@ impl Workspace {
OverviewMode::None => 1.0, OverviewMode::None => 1.0,
}; };
let (w_elements, p_elements) = self.floating_layer.render::<R>( elements.extend_map(
renderer, self.floating_layer.render::<R>(
focused.as_ref(), renderer,
resize_indicator.clone(), focused.as_ref(),
indicator_thickness, resize_indicator.clone(),
alpha, indicator_thickness,
theme, alpha,
theme,
),
WorkspaceRenderElement::from,
); );
popup_elements.extend(p_elements.into_iter().map(WorkspaceRenderElement::from));
window_elements.extend(w_elements.into_iter().map(WorkspaceRenderElement::from));
let alpha = match &overview.0 { let alpha = match &overview.0 {
OverviewMode::Started(_, start) => Some( OverviewMode::Started(_, start) => Some(
@ -1175,20 +1174,21 @@ impl Workspace {
}; };
//tiling surfaces //tiling surfaces
let (w_elements, p_elements) = self.tiling_layer.render::<R>( elements.extend_map(
renderer, self.tiling_layer.render::<R>(
draw_focus_indicator, renderer,
zone, draw_focus_indicator,
overview, zone,
resize_indicator, overview,
indicator_thickness, resize_indicator,
theme, indicator_thickness,
)?; theme,
popup_elements.extend(p_elements.into_iter().map(WorkspaceRenderElement::from)); )?,
window_elements.extend(w_elements.into_iter().map(WorkspaceRenderElement::from)); WorkspaceRenderElement::from,
);
if let Some(alpha) = alpha { if let Some(alpha) = alpha {
window_elements.push( elements.w_elements.push(
Into::<CosmicMappedRenderElement<R>>::into(BackdropShader::element( Into::<CosmicMappedRenderElement<R>>::into(BackdropShader::element(
renderer, renderer,
self.backdrop_id.clone(), self.backdrop_id.clone(),
@ -1205,7 +1205,7 @@ impl Workspace {
} }
} }
Ok((window_elements, popup_elements)) Ok(elements)
} }
} }