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
This commit is contained in:
Ian Douglas Scott 2024-08-04 18:04:06 -07:00 committed by Victoria Brekenfeld
parent 3dd3460ee0
commit 4748916ff9
3 changed files with 63 additions and 222 deletions

View file

@ -11,12 +11,12 @@ use smithay::{
gles::{GlesError, GlesTexture}, gles::{GlesError, GlesTexture},
glow::{GlowFrame, GlowRenderer}, glow::{GlowFrame, GlowRenderer},
utils::{CommitCounter, DamageSet, OpaqueRegions}, utils::{CommitCounter, DamageSet, OpaqueRegions},
Frame, ImportAll, ImportMem, Renderer, ImportAll, ImportMem, Renderer,
}, },
utils::{Buffer as BufferCoords, Logical, Physical, Point, Rectangle, Scale}, utils::{Buffer as BufferCoords, Logical, Physical, Point, Rectangle, Scale},
}; };
use super::{cursor::CursorRenderElement, GlMultiError, GlMultiFrame, GlMultiRenderer}; use super::{cursor::CursorRenderElement, GlMultiRenderer};
pub enum CosmicElement<R> pub enum CosmicElement<R>
where where
@ -179,72 +179,32 @@ where
} }
} }
impl RenderElement<GlowRenderer> for CosmicElement<GlowRenderer> { impl<R> RenderElement<R> for CosmicElement<R>
where
R: AsGlowRenderer + Renderer + ImportAll + ImportMem,
<R as Renderer>::TextureId: 'static,
<R as Renderer>::Error: FromGlesError,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn draw<'frame>( fn draw<'frame>(
&self, &self,
frame: &mut <GlowRenderer as Renderer>::Frame<'frame>, frame: &mut R::Frame<'frame>,
src: Rectangle<f64, BufferCoords>, src: Rectangle<f64, BufferCoords>,
dst: Rectangle<i32, Physical>, dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>], damage: &[Rectangle<i32, Physical>],
opaque_regions: &[Rectangle<i32, Physical>], opaque_regions: &[Rectangle<i32, Physical>],
) -> Result<(), <GlowRenderer as Renderer>::Error> { ) -> Result<(), R::Error> {
match self { match self {
CosmicElement::Workspace(elem) => elem.draw(frame, src, dst, damage, opaque_regions), CosmicElement::Workspace(elem) => elem.draw(frame, src, dst, damage, opaque_regions),
CosmicElement::Cursor(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::Dnd(elem) => elem.draw(frame, src, dst, damage, opaque_regions),
CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage, opaque_regions), CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage, opaque_regions),
CosmicElement::AdditionalDamage(elem) => { CosmicElement::AdditionalDamage(elem) => {
RenderElement::<GlowRenderer>::draw(elem, frame, src, dst, damage, opaque_regions) RenderElement::<R>::draw(elem, frame, src, dst, damage, opaque_regions)
} }
CosmicElement::Mirror(elem) => {
RenderElement::<GlowRenderer>::draw(elem, frame, src, dst, damage, opaque_regions)
}
#[cfg(feature = "debug")]
CosmicElement::Egui(elem) => {
RenderElement::<GlowRenderer>::draw(elem, frame, src, dst, damage, opaque_regions)
}
}
}
fn underlying_storage(&self, renderer: &mut GlowRenderer) -> Option<UnderlyingStorage> {
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<GlMultiRenderer<'a>> for CosmicElement<GlMultiRenderer<'a>> {
fn draw<'frame>(
&self,
frame: &mut GlMultiFrame<'a, 'frame>,
src: Rectangle<f64, BufferCoords>,
dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>],
opaque_regions: &[Rectangle<i32, Physical>],
) -> 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::<GlMultiRenderer<'a>>::draw(
elem,
frame,
src,
dst,
damage,
opaque_regions,
),
CosmicElement::Mirror(elem) => { CosmicElement::Mirror(elem) => {
let elem = { let elem = {
let glow_frame = frame.glow_frame_mut(); let glow_frame = R::glow_frame_mut(frame);
RenderElement::<GlowRenderer>::draw( RenderElement::<GlowRenderer>::draw(
elem, elem,
glow_frame, glow_frame,
@ -253,14 +213,14 @@ impl<'a> RenderElement<GlMultiRenderer<'a>> for CosmicElement<GlMultiRenderer<'a
damage, damage,
opaque_regions, opaque_regions,
) )
.map_err(|err| GlMultiError::Render(err)) .map_err(FromGlesError::from_gles_error)
}; };
elem elem
} }
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
CosmicElement::Egui(elem) => { CosmicElement::Egui(elem) => {
let elem = { let elem = {
let glow_frame = frame.glow_frame_mut(); let glow_frame = R::glow_frame_mut(frame);
RenderElement::<GlowRenderer>::draw( RenderElement::<GlowRenderer>::draw(
elem, elem,
glow_frame, glow_frame,
@ -269,14 +229,14 @@ impl<'a> RenderElement<GlMultiRenderer<'a>> for CosmicElement<GlMultiRenderer<'a
damage, damage,
opaque_regions, opaque_regions,
) )
.map_err(|err| GlMultiError::Render(err)) .map_err(FromGlesError::from_gles_error)
}; };
elem elem
} }
} }
} }
fn underlying_storage(&self, renderer: &mut GlMultiRenderer<'a>) -> Option<UnderlyingStorage> { fn underlying_storage(&self, renderer: &mut R) -> Option<UnderlyingStorage> {
match self { match self {
CosmicElement::Workspace(elem) => elem.underlying_storage(renderer), CosmicElement::Workspace(elem) => elem.underlying_storage(renderer),
CosmicElement::Cursor(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(&self) -> &GlowRenderer;
fn glow_renderer_mut(&mut self) -> &mut 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 { impl AsGlowRenderer for GlowRenderer {
@ -370,6 +332,12 @@ impl AsGlowRenderer for GlowRenderer {
fn glow_renderer_mut(&mut self) -> &mut GlowRenderer { fn glow_renderer_mut(&mut self) -> &mut GlowRenderer {
self 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> { impl<'a> AsGlowRenderer for GlMultiRenderer<'a> {
@ -379,31 +347,11 @@ impl<'a> AsGlowRenderer for GlMultiRenderer<'a> {
fn glow_renderer_mut(&mut self) -> &mut GlowRenderer { fn glow_renderer_mut(&mut self) -> &mut GlowRenderer {
self.as_mut() self.as_mut()
} }
} fn glow_frame<'b, 'frame>(frame: &'b Self::Frame<'frame>) -> &'b GlowFrame<'frame> {
frame.as_ref()
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> { fn glow_frame_mut<'b, 'frame>(frame: &'b mut Self::Frame<'frame>) -> &'b mut GlowFrame<'frame> {
self frame.as_mut()
}
}
impl<'renderer, 'frame> AsGlowFrame<'frame> for GlMultiFrame<'renderer, 'frame> {
fn glow_frame(&self) -> &GlowFrame<'frame> {
self.as_ref()
}
fn glow_frame_mut(&mut self) -> &mut GlowFrame<'frame> {
self.as_mut()
} }
} }

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
backend::render::{ backend::render::{
element::{AsGlowFrame, AsGlowRenderer}, element::{AsGlowRenderer, FromGlesError},
GlMultiError, GlMultiFrame, GlMultiRenderer, SplitRenderElements, SplitRenderElements,
}, },
state::State, state::State,
utils::{iced::IcedElementInternal, prelude::*}, utils::{iced::IcedElementInternal, prelude::*},
@ -1270,90 +1270,20 @@ where
} }
} }
impl RenderElement<GlowRenderer> for CosmicMappedRenderElement<GlowRenderer> { impl<R> RenderElement<R> for CosmicMappedRenderElement<R>
where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
<R as Renderer>::TextureId: 'static,
<R as Renderer>::Error: FromGlesError,
{
fn draw<'frame>( fn draw<'frame>(
&self, &self,
frame: &mut <GlowRenderer as Renderer>::Frame<'frame>, frame: &mut R::Frame<'frame>,
src: Rectangle<f64, BufferCoords>, src: Rectangle<f64, BufferCoords>,
dst: Rectangle<i32, Physical>, dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>], damage: &[Rectangle<i32, Physical>],
opaque_regions: &[Rectangle<i32, Physical>], opaque_regions: &[Rectangle<i32, Physical>],
) -> Result<(), <GlowRenderer as Renderer>::Error> { ) -> Result<(), R::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::<GlowRenderer>::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::<GlowRenderer>::draw(elem, frame, src, dst, damage, opaque_regions)
}
CosmicMappedRenderElement::Overlay(elem) => {
RenderElement::<GlowRenderer>::draw(elem, frame, src, dst, damage, opaque_regions)
}
CosmicMappedRenderElement::StackHoverIndicator(elem) => {
RenderElement::<GlowRenderer>::draw(elem, frame, src, dst, damage, opaque_regions)
}
#[cfg(feature = "debug")]
CosmicMappedRenderElement::Egui(elem) => {
RenderElement::<GlowRenderer>::draw(elem, frame, src, dst, damage, opaque_regions)
}
}
}
fn underlying_storage(&self, renderer: &mut GlowRenderer) -> Option<UnderlyingStorage> {
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<GlMultiRenderer<'a>> for CosmicMappedRenderElement<GlMultiRenderer<'a>> {
fn draw<'frame>(
&self,
frame: &mut GlMultiFrame<'a, 'frame>,
src: Rectangle<f64, BufferCoords>,
dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>],
opaque_regions: &[Rectangle<i32, Physical>],
) -> Result<(), GlMultiError> {
match self { match self {
CosmicMappedRenderElement::Stack(elem) => { CosmicMappedRenderElement::Stack(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions) elem.draw(frame, src, dst, damage, opaque_regions)
@ -1369,13 +1299,13 @@ impl<'a> RenderElement<GlMultiRenderer<'a>> for CosmicMappedRenderElement<GlMult
} }
CosmicMappedRenderElement::TiledOverlay(elem) => RenderElement::<GlowRenderer>::draw( CosmicMappedRenderElement::TiledOverlay(elem) => RenderElement::<GlowRenderer>::draw(
elem, elem,
frame.glow_frame_mut(), R::glow_frame_mut(frame),
src, src,
dst, dst,
damage, damage,
opaque_regions, opaque_regions,
) )
.map_err(|err| GlMultiError::Render(err)), .map_err(FromGlesError::from_gles_error),
CosmicMappedRenderElement::MovingStack(elem) => { CosmicMappedRenderElement::MovingStack(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions) elem.draw(frame, src, dst, damage, opaque_regions)
} }
@ -1390,28 +1320,28 @@ impl<'a> RenderElement<GlMultiRenderer<'a>> for CosmicMappedRenderElement<GlMult
} }
CosmicMappedRenderElement::FocusIndicator(elem) => RenderElement::<GlowRenderer>::draw( CosmicMappedRenderElement::FocusIndicator(elem) => RenderElement::<GlowRenderer>::draw(
elem, elem,
frame.glow_frame_mut(), R::glow_frame_mut(frame),
src, src,
dst, dst,
damage, damage,
opaque_regions, opaque_regions,
) )
.map_err(|err| GlMultiError::Render(err)), .map_err(FromGlesError::from_gles_error),
CosmicMappedRenderElement::Overlay(elem) => RenderElement::<GlowRenderer>::draw( CosmicMappedRenderElement::Overlay(elem) => RenderElement::<GlowRenderer>::draw(
elem, elem,
frame.glow_frame_mut(), R::glow_frame_mut(frame),
src, src,
dst, dst,
damage, damage,
opaque_regions, opaque_regions,
) )
.map_err(|err| GlMultiError::Render(err)), .map_err(FromGlesError::from_gles_error),
CosmicMappedRenderElement::StackHoverIndicator(elem) => { CosmicMappedRenderElement::StackHoverIndicator(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions) elem.draw(frame, src, dst, damage, opaque_regions)
} }
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
CosmicMappedRenderElement::Egui(elem) => { CosmicMappedRenderElement::Egui(elem) => {
let glow_frame = frame.glow_frame_mut(); let glow_frame = R::glow_frame_mut(frame);
RenderElement::<GlowRenderer>::draw( RenderElement::<GlowRenderer>::draw(
elem, elem,
glow_frame, glow_frame,
@ -1420,12 +1350,12 @@ impl<'a> RenderElement<GlMultiRenderer<'a>> for CosmicMappedRenderElement<GlMult
damage, damage,
opaque_regions, opaque_regions,
) )
.map_err(|err| GlMultiError::Render(err)) .map_err(FromGlesError::from_gles_error)
} }
} }
} }
fn underlying_storage(&self, renderer: &mut GlMultiRenderer<'a>) -> Option<UnderlyingStorage> { fn underlying_storage(&self, renderer: &mut R) -> Option<UnderlyingStorage> {
match self { match self {
CosmicMappedRenderElement::Stack(elem) => elem.underlying_storage(renderer), CosmicMappedRenderElement::Stack(elem) => elem.underlying_storage(renderer),
CosmicMappedRenderElement::Window(elem) => elem.underlying_storage(renderer), CosmicMappedRenderElement::Window(elem) => elem.underlying_storage(renderer),

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
backend::render::{ backend::render::{
element::{AsGlowFrame, AsGlowRenderer}, element::{AsGlowRenderer, FromGlesError},
BackdropShader, GlMultiError, GlMultiFrame, GlMultiRenderer, SplitRenderElements, BackdropShader, SplitRenderElements,
}, },
shell::{ shell::{
layout::{floating::FloatingLayout, tiling::TilingLayout}, layout::{floating::FloatingLayout, tiling::TilingLayout},
@ -29,8 +29,8 @@ use smithay::{
surface::WaylandSurfaceRenderElement, texture::TextureRenderElement, surface::WaylandSurfaceRenderElement, texture::TextureRenderElement,
utils::RescaleRenderElement, Element, Id, RenderElement, utils::RescaleRenderElement, Element, Id, RenderElement,
}, },
gles::{GlesError, GlesTexture}, gles::GlesTexture,
glow::{GlowFrame, GlowRenderer}, glow::GlowRenderer,
utils::{DamageSet, OpaqueRegions}, utils::{DamageSet, OpaqueRegions},
ImportAll, ImportMem, Renderer, ImportAll, ImportMem, Renderer,
}, },
@ -1333,57 +1333,20 @@ where
} }
} }
impl RenderElement<GlowRenderer> for WorkspaceRenderElement<GlowRenderer> { impl<R> RenderElement<R> for WorkspaceRenderElement<R>
where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
<R as Renderer>::TextureId: 'static,
<R as Renderer>::Error: FromGlesError,
{
fn draw<'frame>( fn draw<'frame>(
&self, &self,
frame: &mut GlowFrame<'frame>, frame: &mut R::Frame<'frame>,
src: Rectangle<f64, BufferCoords>, src: Rectangle<f64, BufferCoords>,
dst: Rectangle<i32, Physical>, dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, smithay::utils::Physical>], damage: &[Rectangle<i32, smithay::utils::Physical>],
opaque_regions: &[Rectangle<i32, Physical>], opaque_regions: &[Rectangle<i32, Physical>],
) -> Result<(), GlesError> { ) -> Result<(), R::Error> {
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::<GlowRenderer>::draw(elem, frame, src, dst, damage, opaque_regions)
}
}
}
fn underlying_storage(
&self,
renderer: &mut GlowRenderer,
) -> Option<smithay::backend::renderer::element::UnderlyingStorage> {
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<GlMultiRenderer<'a>> for WorkspaceRenderElement<GlMultiRenderer<'a>> {
fn draw<'frame>(
&self,
frame: &mut GlMultiFrame<'a, 'frame>,
src: Rectangle<f64, BufferCoords>,
dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, smithay::utils::Physical>],
opaque_regions: &[Rectangle<i32, Physical>],
) -> Result<(), GlMultiError> {
match self { match self {
WorkspaceRenderElement::OverrideRedirect(elem) => { WorkspaceRenderElement::OverrideRedirect(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions) elem.draw(frame, src, dst, damage, opaque_regions)
@ -1399,19 +1362,19 @@ impl<'a> RenderElement<GlMultiRenderer<'a>> for WorkspaceRenderElement<GlMultiRe
} }
WorkspaceRenderElement::Backdrop(elem) => RenderElement::<GlowRenderer>::draw( WorkspaceRenderElement::Backdrop(elem) => RenderElement::<GlowRenderer>::draw(
elem, elem,
frame.glow_frame_mut(), R::glow_frame_mut(frame),
src, src,
dst, dst,
damage, damage,
opaque_regions, opaque_regions,
) )
.map_err(GlMultiError::Render), .map_err(FromGlesError::from_gles_error),
} }
} }
fn underlying_storage( fn underlying_storage(
&self, &self,
renderer: &mut GlMultiRenderer<'a>, renderer: &mut R,
) -> Option<smithay::backend::renderer::element::UnderlyingStorage> { ) -> Option<smithay::backend::renderer::element::UnderlyingStorage> {
match self { match self {
WorkspaceRenderElement::OverrideRedirect(elem) => elem.underlying_storage(renderer), WorkspaceRenderElement::OverrideRedirect(elem) => elem.underlying_storage(renderer),