use crate::shell::{CosmicMappedRenderElement, WorkspaceRenderElement}; use smithay::{ backend::renderer::{ element::{Element, RenderElement, UnderlyingStorage}, glow::{GlowFrame, GlowRenderer}, Frame, ImportAll, ImportMem, Renderer, }, utils::{Buffer as BufferCoords, Physical, Point, Rectangle, Scale}, }; #[cfg(feature = "debug")] use smithay::backend::renderer::{ element::texture::TextureRenderElement, gles::GlesTexture, multigpu::Error as MultiError, }; use super::{cursor::CursorRenderElement, GlMultiFrame, GlMultiRenderer}; pub enum CosmicElement where R: AsGlowRenderer + Renderer + ImportAll + ImportMem, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { Workspace(WorkspaceRenderElement), Cursor(CursorRenderElement), MoveGrab(CosmicMappedRenderElement), #[cfg(feature = "debug")] Egui(TextureRenderElement), } impl Element for CosmicElement where R: AsGlowRenderer + Renderer + ImportAll + ImportMem, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { fn id(&self) -> &smithay::backend::renderer::element::Id { match self { CosmicElement::Workspace(elem) => elem.id(), CosmicElement::Cursor(elem) => elem.id(), CosmicElement::MoveGrab(elem) => elem.id(), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.id(), } } fn current_commit(&self) -> smithay::backend::renderer::utils::CommitCounter { match self { CosmicElement::Workspace(elem) => elem.current_commit(), CosmicElement::Cursor(elem) => elem.current_commit(), CosmicElement::MoveGrab(elem) => elem.current_commit(), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.current_commit(), } } fn src(&self) -> Rectangle { match self { CosmicElement::Workspace(elem) => elem.src(), CosmicElement::Cursor(elem) => elem.src(), CosmicElement::MoveGrab(elem) => elem.src(), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.src(), } } fn geometry(&self, scale: Scale) -> Rectangle { match self { CosmicElement::Workspace(elem) => elem.geometry(scale), CosmicElement::Cursor(elem) => elem.geometry(scale), CosmicElement::MoveGrab(elem) => elem.geometry(scale), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.geometry(scale), } } fn location(&self, scale: Scale) -> Point { match self { CosmicElement::Workspace(elem) => elem.location(scale), CosmicElement::Cursor(elem) => elem.location(scale), CosmicElement::MoveGrab(elem) => elem.location(scale), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.location(scale), } } fn transform(&self) -> smithay::utils::Transform { match self { CosmicElement::Workspace(elem) => elem.transform(), CosmicElement::Cursor(elem) => elem.transform(), CosmicElement::MoveGrab(elem) => elem.transform(), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.transform(), } } fn damage_since( &self, scale: Scale, commit: Option, ) -> Vec> { match self { CosmicElement::Workspace(elem) => elem.damage_since(scale, commit), CosmicElement::Cursor(elem) => elem.damage_since(scale, commit), CosmicElement::MoveGrab(elem) => elem.damage_since(scale, commit), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.damage_since(scale, commit), } } fn opaque_regions(&self, scale: Scale) -> Vec> { match self { CosmicElement::Workspace(elem) => elem.opaque_regions(scale), CosmicElement::Cursor(elem) => elem.opaque_regions(scale), CosmicElement::MoveGrab(elem) => elem.opaque_regions(scale), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.opaque_regions(scale), } } } impl RenderElement for CosmicElement { fn draw<'frame>( &self, frame: &mut ::Frame<'frame>, src: Rectangle, dst: Rectangle, damage: &[Rectangle], ) -> Result<(), ::Error> { match self { CosmicElement::Workspace(elem) => elem.draw(frame, src, dst, damage), CosmicElement::Cursor(elem) => elem.draw(frame, src, dst, damage), CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => { RenderElement::::draw(elem, frame, src, dst, damage) } } } fn underlying_storage(&self, renderer: &mut GlowRenderer) -> Option { match self { CosmicElement::Workspace(elem) => elem.underlying_storage(renderer), CosmicElement::Cursor(elem) => elem.underlying_storage(renderer), CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.underlying_storage(renderer), } } } impl<'a, 'b> RenderElement> for CosmicElement> { fn draw<'frame>( &self, frame: &mut GlMultiFrame<'a, 'b, 'frame>, src: Rectangle, dst: Rectangle, damage: &[Rectangle], ) -> Result<(), as Renderer>::Error> { match self { CosmicElement::Workspace(elem) => elem.draw(frame, src, dst, damage), CosmicElement::Cursor(elem) => elem.draw(frame, src, dst, damage), CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => { let elem = { let glow_frame = frame.glow_frame_mut(); RenderElement::::draw(elem, glow_frame, src, dst, damage) .map_err(|err| MultiError::Render(err)) }; elem } } } fn underlying_storage( &self, renderer: &mut GlMultiRenderer<'a, 'b>, ) -> Option { match self { CosmicElement::Workspace(elem) => elem.underlying_storage(renderer), CosmicElement::Cursor(elem) => elem.underlying_storage(renderer), CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => { let glow_renderer = renderer.glow_renderer_mut(); match elem.underlying_storage(glow_renderer) { Some(UnderlyingStorage::Wayland(buffer)) => { Some(UnderlyingStorage::Wayland(buffer)) } _ => None, } } } } } impl From> for CosmicElement where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { fn from(elem: WorkspaceRenderElement) -> Self { Self::Workspace(elem) } } impl From> for CosmicElement where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { fn from(elem: CursorRenderElement) -> Self { Self::Cursor(elem) } } impl From> for CosmicElement where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { fn from(elem: CosmicMappedRenderElement) -> Self { Self::MoveGrab(elem) } } #[cfg(feature = "debug")] impl From> for CosmicElement where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { fn from(elem: TextureRenderElement) -> Self { Self::Egui(elem) } } pub trait AsGlowRenderer where Self: Renderer, { fn glow_renderer(&self) -> &GlowRenderer; fn glow_renderer_mut(&mut self) -> &mut GlowRenderer; } impl AsGlowRenderer for GlowRenderer { fn glow_renderer(&self) -> &GlowRenderer { self } fn glow_renderer_mut(&mut self) -> &mut GlowRenderer { self } } impl<'a, 'b> AsGlowRenderer for GlMultiRenderer<'a, 'b> { fn glow_renderer(&self) -> &GlowRenderer { self.as_ref() } fn glow_renderer_mut(&mut self) -> &mut GlowRenderer { self.as_mut() } } pub trait AsGlowFrame<'a> where Self: Frame, { fn glow_frame(&self) -> &GlowFrame<'a>; fn glow_frame_mut(&mut self) -> &mut GlowFrame<'a>; } impl<'frame> AsGlowFrame<'frame> for GlowFrame<'frame> { fn glow_frame(&self) -> &GlowFrame<'frame> { self } fn glow_frame_mut(&mut self) -> &mut GlowFrame<'frame> { self } } impl<'renderer, 'alloc, 'frame> AsGlowFrame<'frame> for GlMultiFrame<'renderer, 'alloc, 'frame> { fn glow_frame(&self) -> &GlowFrame<'frame> { self.as_ref() } fn glow_frame_mut(&mut self) -> &mut GlowFrame<'frame> { self.as_mut() } }