From ccc91c24b4ab28a1315fe0e72bd2568b35447e4a Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Sun, 4 Aug 2024 18:04:06 -0700 Subject: [PATCH] Make `RenderElement` implementations generic to reduce duplication It would make sense to have a bound like `for<'frame> R::Frame<'frame>: AsGlowFrame<'frame>`. But that appears to not behave properly due to current limitations of the borrow checker: https://blog.rust-lang.org/2022/10/28/gats-stabilization.html#implied-static-requirement-from-higher-ranked-trait-bounds Instead, this makes `glow_frame` and `glow_frame_mut` associated functions of the `AsGlowRenderer` trait. Then it is pretty straightforward to make the `RenderElement` implementations generic using that and `FromGlesError`. It would make sense to make `Self::Error: FromGlessError` a requirement of the `AsGlowRenderer` trait, but due to the lack of implied bounds support, that produces a bunch of errors about missing bounds. If Rustc improves that eventually, some bounds could be cleaned up a bit: https://github.com/rust-lang/rust/issues/44491 --- src/backend/render/element.rs | 110 +++++++++------------------------- src/shell/element/mod.rs | 108 ++++++--------------------------- src/shell/workspace.rs | 67 +++++---------------- 3 files changed, 63 insertions(+), 222 deletions(-) diff --git a/src/backend/render/element.rs b/src/backend/render/element.rs index 93ea463b..26fca22c 100644 --- a/src/backend/render/element.rs +++ b/src/backend/render/element.rs @@ -11,12 +11,12 @@ use smithay::{ gles::{GlesError, GlesTexture}, glow::{GlowFrame, GlowRenderer}, utils::{CommitCounter, DamageSet, OpaqueRegions}, - Frame, ImportAll, ImportMem, Renderer, + ImportAll, ImportMem, Renderer, }, utils::{Buffer as BufferCoords, Logical, Physical, Point, Rectangle, Scale}, }; -use super::{cursor::CursorRenderElement, GlMultiError, GlMultiFrame, GlMultiRenderer}; +use super::{cursor::CursorRenderElement, GlMultiRenderer}; pub enum CosmicElement where @@ -179,72 +179,32 @@ where } } -impl RenderElement for CosmicElement { +impl RenderElement for CosmicElement +where + R: AsGlowRenderer + Renderer + ImportAll + ImportMem, + ::TextureId: 'static, + ::Error: FromGlesError, + CosmicMappedRenderElement: RenderElement, +{ fn draw<'frame>( &self, - frame: &mut ::Frame<'frame>, + frame: &mut R::Frame<'frame>, src: Rectangle, dst: Rectangle, damage: &[Rectangle], opaque_regions: &[Rectangle], - ) -> Result<(), ::Error> { + ) -> Result<(), R::Error> { match self { CosmicElement::Workspace(elem) => elem.draw(frame, src, dst, damage, opaque_regions), CosmicElement::Cursor(elem) => elem.draw(frame, src, dst, damage, opaque_regions), CosmicElement::Dnd(elem) => elem.draw(frame, src, dst, damage, opaque_regions), CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage, opaque_regions), CosmicElement::AdditionalDamage(elem) => { - RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) + RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) } - CosmicElement::Mirror(elem) => { - RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) - } - #[cfg(feature = "debug")] - CosmicElement::Egui(elem) => { - RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) - } - } - } - - 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::Dnd(elem) => elem.underlying_storage(renderer), - CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer), - CosmicElement::AdditionalDamage(elem) => elem.underlying_storage(renderer), - CosmicElement::Mirror(elem) => elem.underlying_storage(renderer), - #[cfg(feature = "debug")] - CosmicElement::Egui(elem) => elem.underlying_storage(renderer), - } - } -} - -impl<'a> RenderElement> for CosmicElement> { - fn draw<'frame>( - &self, - frame: &mut GlMultiFrame<'a, 'frame>, - src: Rectangle, - dst: Rectangle, - damage: &[Rectangle], - opaque_regions: &[Rectangle], - ) -> Result<(), GlMultiError> { - match self { - CosmicElement::Workspace(elem) => elem.draw(frame, src, dst, damage, opaque_regions), - CosmicElement::Cursor(elem) => elem.draw(frame, src, dst, damage, opaque_regions), - CosmicElement::Dnd(elem) => elem.draw(frame, src, dst, damage, opaque_regions), - CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage, opaque_regions), - CosmicElement::AdditionalDamage(elem) => RenderElement::>::draw( - elem, - frame, - src, - dst, - damage, - opaque_regions, - ), CosmicElement::Mirror(elem) => { let elem = { - let glow_frame = frame.glow_frame_mut(); + let glow_frame = R::glow_frame_mut(frame); RenderElement::::draw( elem, glow_frame, @@ -253,14 +213,14 @@ impl<'a> RenderElement> for CosmicElement { let elem = { - let glow_frame = frame.glow_frame_mut(); + let glow_frame = R::glow_frame_mut(frame); RenderElement::::draw( elem, glow_frame, @@ -269,14 +229,14 @@ impl<'a> RenderElement> for CosmicElement) -> Option { + fn underlying_storage(&self, renderer: &mut R) -> Option { match self { CosmicElement::Workspace(elem) => elem.underlying_storage(renderer), CosmicElement::Cursor(elem) => elem.underlying_storage(renderer), @@ -361,6 +321,8 @@ where { fn glow_renderer(&self) -> &GlowRenderer; fn glow_renderer_mut(&mut self) -> &mut GlowRenderer; + fn glow_frame<'a, 'frame>(frame: &'a Self::Frame<'frame>) -> &'a GlowFrame<'frame>; + fn glow_frame_mut<'a, 'frame>(frame: &'a mut Self::Frame<'frame>) -> &'a mut GlowFrame<'frame>; } impl AsGlowRenderer for GlowRenderer { @@ -370,6 +332,12 @@ impl AsGlowRenderer for GlowRenderer { fn glow_renderer_mut(&mut self) -> &mut GlowRenderer { self } + fn glow_frame<'a, 'frame>(frame: &'a Self::Frame<'frame>) -> &'a GlowFrame<'frame> { + frame + } + fn glow_frame_mut<'a, 'frame>(frame: &'a mut Self::Frame<'frame>) -> &'a mut GlowFrame<'frame> { + frame + } } impl<'a> AsGlowRenderer for GlMultiRenderer<'a> { @@ -379,31 +347,11 @@ impl<'a> AsGlowRenderer for GlMultiRenderer<'a> { 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, 'frame> AsGlowFrame<'frame> for GlMultiFrame<'renderer, 'frame> { - fn glow_frame(&self) -> &GlowFrame<'frame> { - self.as_ref() + fn glow_frame<'b, 'frame>(frame: &'b Self::Frame<'frame>) -> &'b GlowFrame<'frame> { + frame.as_ref() } - fn glow_frame_mut(&mut self) -> &mut GlowFrame<'frame> { - self.as_mut() + fn glow_frame_mut<'b, 'frame>(frame: &'b mut Self::Frame<'frame>) -> &'b mut GlowFrame<'frame> { + frame.as_mut() } } diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index 886cc772..f0e8b7b0 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -1,7 +1,7 @@ use crate::{ backend::render::{ - element::{AsGlowFrame, AsGlowRenderer}, - GlMultiError, GlMultiFrame, GlMultiRenderer, SplitRenderElements, + element::{AsGlowRenderer, FromGlesError}, + SplitRenderElements, }, state::State, utils::{iced::IcedElementInternal, prelude::*}, @@ -1270,90 +1270,20 @@ where } } -impl RenderElement for CosmicMappedRenderElement { - fn draw<'frame>( - &self, - frame: &mut ::Frame<'frame>, - src: Rectangle, - dst: Rectangle, - damage: &[Rectangle], - opaque_regions: &[Rectangle], - ) -> Result<(), ::Error> { - match self { - CosmicMappedRenderElement::Stack(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::Window(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::TiledStack(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::TiledWindow(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::TiledOverlay(elem) => { - RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::MovingStack(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::MovingWindow(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::GrabbedStack(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::GrabbedWindow(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::FocusIndicator(elem) => { - RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::Overlay(elem) => { - RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) - } - CosmicMappedRenderElement::StackHoverIndicator(elem) => { - RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) - } - #[cfg(feature = "debug")] - CosmicMappedRenderElement::Egui(elem) => { - RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) - } - } - } - - fn underlying_storage(&self, renderer: &mut GlowRenderer) -> Option { - match self { - CosmicMappedRenderElement::Stack(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::Window(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::TiledStack(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::TiledWindow(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::TiledOverlay(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::MovingStack(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::MovingWindow(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::GrabbedStack(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::GrabbedWindow(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::FocusIndicator(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::Overlay(elem) => elem.underlying_storage(renderer), - CosmicMappedRenderElement::StackHoverIndicator(elem) => { - elem.underlying_storage(renderer) - } - #[cfg(feature = "debug")] - CosmicMappedRenderElement::Egui(elem) => elem.underlying_storage(renderer), - } - } -} - -impl<'a> RenderElement> for CosmicMappedRenderElement> { +impl RenderElement for CosmicMappedRenderElement +where + R: Renderer + ImportAll + ImportMem + AsGlowRenderer, + ::TextureId: 'static, + ::Error: FromGlesError, +{ fn draw<'frame>( &self, - frame: &mut GlMultiFrame<'a, 'frame>, + frame: &mut R::Frame<'frame>, src: Rectangle, dst: Rectangle, damage: &[Rectangle], opaque_regions: &[Rectangle], - ) -> Result<(), GlMultiError> { + ) -> Result<(), R::Error> { match self { CosmicMappedRenderElement::Stack(elem) => { elem.draw(frame, src, dst, damage, opaque_regions) @@ -1369,13 +1299,13 @@ impl<'a> RenderElement> for CosmicMappedRenderElement RenderElement::::draw( elem, - frame.glow_frame_mut(), + R::glow_frame_mut(frame), src, dst, damage, opaque_regions, ) - .map_err(|err| GlMultiError::Render(err)), + .map_err(FromGlesError::from_gles_error), CosmicMappedRenderElement::MovingStack(elem) => { elem.draw(frame, src, dst, damage, opaque_regions) } @@ -1390,28 +1320,28 @@ impl<'a> RenderElement> for CosmicMappedRenderElement RenderElement::::draw( elem, - frame.glow_frame_mut(), + R::glow_frame_mut(frame), src, dst, damage, opaque_regions, ) - .map_err(|err| GlMultiError::Render(err)), + .map_err(FromGlesError::from_gles_error), CosmicMappedRenderElement::Overlay(elem) => RenderElement::::draw( elem, - frame.glow_frame_mut(), + R::glow_frame_mut(frame), src, dst, damage, opaque_regions, ) - .map_err(|err| GlMultiError::Render(err)), + .map_err(FromGlesError::from_gles_error), CosmicMappedRenderElement::StackHoverIndicator(elem) => { elem.draw(frame, src, dst, damage, opaque_regions) } #[cfg(feature = "debug")] CosmicMappedRenderElement::Egui(elem) => { - let glow_frame = frame.glow_frame_mut(); + let glow_frame = R::glow_frame_mut(frame); RenderElement::::draw( elem, glow_frame, @@ -1420,12 +1350,12 @@ impl<'a> RenderElement> for CosmicMappedRenderElement) -> Option { + fn underlying_storage(&self, renderer: &mut R) -> Option { match self { CosmicMappedRenderElement::Stack(elem) => elem.underlying_storage(renderer), CosmicMappedRenderElement::Window(elem) => elem.underlying_storage(renderer), diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index 4ec42b41..4037eed5 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -1,7 +1,7 @@ use crate::{ backend::render::{ - element::{AsGlowFrame, AsGlowRenderer}, - BackdropShader, GlMultiError, GlMultiFrame, GlMultiRenderer, SplitRenderElements, + element::{AsGlowRenderer, FromGlesError}, + BackdropShader, SplitRenderElements, }, shell::{ layout::{floating::FloatingLayout, tiling::TilingLayout}, @@ -29,8 +29,8 @@ use smithay::{ surface::WaylandSurfaceRenderElement, texture::TextureRenderElement, utils::RescaleRenderElement, Element, Id, RenderElement, }, - gles::{GlesError, GlesTexture}, - glow::{GlowFrame, GlowRenderer}, + gles::GlesTexture, + glow::GlowRenderer, utils::{DamageSet, OpaqueRegions}, ImportAll, ImportMem, Renderer, }, @@ -1333,57 +1333,20 @@ where } } -impl RenderElement for WorkspaceRenderElement { - fn draw<'frame>( - &self, - frame: &mut GlowFrame<'frame>, - src: Rectangle, - dst: Rectangle, - damage: &[Rectangle], - opaque_regions: &[Rectangle], - ) -> Result<(), GlesError> { - match self { - WorkspaceRenderElement::OverrideRedirect(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - WorkspaceRenderElement::Fullscreen(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - WorkspaceRenderElement::FullscreenPopup(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - WorkspaceRenderElement::Window(elem) => { - elem.draw(frame, src, dst, damage, opaque_regions) - } - WorkspaceRenderElement::Backdrop(elem) => { - RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) - } - } - } - - fn underlying_storage( - &self, - renderer: &mut GlowRenderer, - ) -> Option { - match self { - WorkspaceRenderElement::OverrideRedirect(elem) => elem.underlying_storage(renderer), - WorkspaceRenderElement::Fullscreen(elem) => elem.underlying_storage(renderer), - WorkspaceRenderElement::FullscreenPopup(elem) => elem.underlying_storage(renderer), - WorkspaceRenderElement::Window(elem) => elem.underlying_storage(renderer), - WorkspaceRenderElement::Backdrop(elem) => elem.underlying_storage(renderer), - } - } -} - -impl<'a> RenderElement> for WorkspaceRenderElement> { +impl RenderElement for WorkspaceRenderElement +where + R: Renderer + ImportAll + ImportMem + AsGlowRenderer, + ::TextureId: 'static, + ::Error: FromGlesError, +{ fn draw<'frame>( &self, - frame: &mut GlMultiFrame<'a, 'frame>, + frame: &mut R::Frame<'frame>, src: Rectangle, dst: Rectangle, damage: &[Rectangle], opaque_regions: &[Rectangle], - ) -> Result<(), GlMultiError> { + ) -> Result<(), R::Error> { match self { WorkspaceRenderElement::OverrideRedirect(elem) => { elem.draw(frame, src, dst, damage, opaque_regions) @@ -1399,19 +1362,19 @@ impl<'a> RenderElement> for WorkspaceRenderElement RenderElement::::draw( elem, - frame.glow_frame_mut(), + R::glow_frame_mut(frame), src, dst, damage, opaque_regions, ) - .map_err(GlMultiError::Render), + .map_err(FromGlesError::from_gles_error), } } fn underlying_storage( &self, - renderer: &mut GlMultiRenderer<'a>, + renderer: &mut R, ) -> Option { match self { WorkspaceRenderElement::OverrideRedirect(elem) => elem.underlying_storage(renderer),