element: Introduce SurfaceRenderElement

This commit is contained in:
Victoria Brekenfeld 2026-03-04 18:16:48 +01:00 committed by Victoria Brekenfeld
parent 8b990e5658
commit 178c6593dc
12 changed files with 254 additions and 213 deletions

View file

@ -1,6 +1,13 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::{utils::prelude::*, wayland::handlers::compositor::FRAME_TIME_FILTER}; use crate::{
backend::render::{
element::AsGlowRenderer,
wayland::{SurfaceRenderElement, render_elements_from_surface_tree},
},
utils::prelude::*,
wayland::handlers::compositor::FRAME_TIME_FILTER,
};
use smithay::{ use smithay::{
backend::{ backend::{
allocator::Fourcc, allocator::Fourcc,
@ -9,10 +16,10 @@ use smithay::{
element::{ element::{
Kind, Kind,
memory::{MemoryRenderBuffer, MemoryRenderBufferRenderElement}, memory::{MemoryRenderBuffer, MemoryRenderBufferRenderElement},
surface::{WaylandSurfaceRenderElement, render_elements_from_surface_tree},
}, },
}, },
}, },
desktop::utils::bbox_from_surface_tree,
input::{ input::{
Seat, Seat,
pointer::{CursorIcon, CursorImageAttributes, CursorImageStatus}, pointer::{CursorIcon, CursorImageAttributes, CursorImageStatus},
@ -168,9 +175,9 @@ fn load_icon(theme: &CursorTheme, shape: CursorIcon) -> Result<Vec<Image>, Error
} }
render_elements! { render_elements! {
pub CursorRenderElement<R> where R: ImportAll + ImportMem; pub CursorRenderElement<R> where R: ImportAll + ImportMem + AsGlowRenderer;
Static=MemoryRenderBufferRenderElement<R>, Static=MemoryRenderBufferRenderElement<R>,
Surface=WaylandSurfaceRenderElement<R>, Surface=SurfaceRenderElement<R>,
} }
pub fn draw_surface_cursor<R>( pub fn draw_surface_cursor<R>(
@ -180,7 +187,7 @@ pub fn draw_surface_cursor<R>(
scale: impl Into<Scale<f64>>, scale: impl Into<Scale<f64>>,
) -> Vec<(CursorRenderElement<R>, Point<i32, Physical>)> ) -> Vec<(CursorRenderElement<R>, Point<i32, Physical>)>
where where
R: Renderer + ImportAll, R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
{ {
let scale = scale.into(); let scale = scale.into();
@ -199,8 +206,11 @@ where
renderer, renderer,
surface, surface,
location.to_physical(scale).to_i32_round(), location.to_physical(scale).to_i32_round(),
bbox_from_surface_tree(surface, location.to_i32_round()).to_f64(),
scale, scale,
1.0, 1.0,
false,
[0; 4],
Kind::Cursor, Kind::Cursor,
) )
.into_iter() .into_iter()
@ -214,9 +224,9 @@ pub fn draw_dnd_icon<R>(
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
location: Point<f64, Logical>, location: Point<f64, Logical>,
scale: impl Into<Scale<f64>>, scale: impl Into<Scale<f64>>,
) -> Vec<WaylandSurfaceRenderElement<R>> ) -> Vec<SurfaceRenderElement<R>>
where where
R: Renderer + ImportAll, R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
{ {
if get_role(surface) != Some("dnd_icon") { if get_role(surface) != Some("dnd_icon") {
@ -230,8 +240,11 @@ where
renderer, renderer,
surface, surface,
location.to_physical(scale).to_i32_round(), location.to_physical(scale).to_i32_round(),
bbox_from_surface_tree(surface, location.to_i32_round()).to_f64(),
scale, scale,
1.0, 1.0,
false,
[0; 4],
FRAME_TIME_FILTER, FRAME_TIME_FILTER,
) )
} }
@ -319,7 +332,7 @@ pub fn draw_cursor<R>(
draw_default: bool, draw_default: bool,
) -> Vec<(CursorRenderElement<R>, Point<i32, Physical>)> ) -> Vec<(CursorRenderElement<R>, Point<i32, Physical>)>
where where
R: Renderer + ImportMem + ImportAll, R: Renderer + ImportMem + ImportAll + AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
{ {
// draw the cursor as relevant // draw the cursor as relevant

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
backend::render::GlMultiError, backend::render::{GlMultiError, wayland::SurfaceRenderElement},
shell::{CosmicMappedRenderElement, WorkspaceRenderElement}, shell::{CosmicMappedRenderElement, WorkspaceRenderElement},
}; };
@ -13,7 +13,6 @@ use smithay::{
element::{ element::{
Element, Id, Kind, RenderElement, UnderlyingStorage, Element, Id, Kind, RenderElement, UnderlyingStorage,
memory::MemoryRenderBufferRenderElement, memory::MemoryRenderBufferRenderElement,
surface::WaylandSurfaceRenderElement,
utils::{CropRenderElement, Relocate, RelocateRenderElement, RescaleRenderElement}, utils::{CropRenderElement, Relocate, RelocateRenderElement, RescaleRenderElement},
}, },
gles::{GlesError, GlesRenderbuffer, GlesTexture, element::TextureShaderElement}, gles::{GlesError, GlesRenderbuffer, GlesTexture, element::TextureShaderElement},
@ -38,7 +37,7 @@ where
RelocateRenderElement<CropRenderElement<RescaleRenderElement<WorkspaceRenderElement<R>>>>, RelocateRenderElement<CropRenderElement<RescaleRenderElement<WorkspaceRenderElement<R>>>>,
), ),
Cursor(RescaleRenderElement<RelocateRenderElement<CursorRenderElement<R>>>), Cursor(RescaleRenderElement<RelocateRenderElement<CursorRenderElement<R>>>),
Dnd(WaylandSurfaceRenderElement<R>), Dnd(SurfaceRenderElement<R>),
MoveGrab(RescaleRenderElement<CosmicMappedRenderElement<R>>), MoveGrab(RescaleRenderElement<CosmicMappedRenderElement<R>>),
Postprocess( Postprocess(
CropRenderElement<RelocateRenderElement<RescaleRenderElement<TextureShaderElement>>>, CropRenderElement<RelocateRenderElement<RescaleRenderElement<TextureShaderElement>>>,

View file

@ -15,9 +15,9 @@ use crate::{
backend::{ backend::{
kms::render::gles::GbmGlowBackend, kms::render::gles::GbmGlowBackend,
render::{ render::{
clipped_surface::{CLIPPING_SHADER, ClippingShader},
element::DamageElement, element::DamageElement,
shadow::{SHADOW_SHADER, ShadowShader}, shadow::{SHADOW_SHADER, ShadowShader},
wayland::clipped_surface::{CLIPPING_SHADER, ClippingShader},
}, },
}, },
config::ScreenFilter, config::ScreenFilter,
@ -80,10 +80,10 @@ use smithay::{
use smithay_egui::EguiState; use smithay_egui::EguiState;
pub mod animations; pub mod animations;
pub mod clipped_surface;
pub mod cursor; pub mod cursor;
pub mod element; pub mod element;
pub mod shadow; pub mod shadow;
pub mod wayland;
use self::element::{AsGlowRenderer, CosmicElement}; use self::element::{AsGlowRenderer, CosmicElement};
use super::kms::Timings; use super::kms::Timings;

View file

@ -6,7 +6,7 @@ use cgmath::{Matrix3, Vector2};
use smithay::utils::{Buffer, Logical, Physical, Point, Rectangle, Scale, Size, Transform}; use smithay::utils::{Buffer, Logical, Physical, Point, Rectangle, Scale, Size, Transform};
use smithay::{ use smithay::{
backend::renderer::{ backend::renderer::{
ImportAll, ImportMem, Renderer, ImportAll, Renderer,
element::{ element::{
Element, Id, Kind, RenderElement, UnderlyingStorage, Element, Id, Kind, RenderElement, UnderlyingStorage,
surface::WaylandSurfaceRenderElement, surface::WaylandSurfaceRenderElement,
@ -19,7 +19,7 @@ use smithay::{
use crate::backend::render::element::AsGlowRenderer; use crate::backend::render::element::AsGlowRenderer;
pub static CLIPPING_SHADER: &str = include_str!("./shaders/clipped_surface.frag"); pub static CLIPPING_SHADER: &str = include_str!("../shaders/clipped_surface.frag");
pub struct ClippingShader(pub GlesTexProgram); pub struct ClippingShader(pub GlesTexProgram);
impl ClippingShader { impl ClippingShader {
@ -35,10 +35,7 @@ impl ClippingShader {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct ClippedSurfaceRenderElement<R> pub struct ClippedSurfaceRenderElement<R: Renderer> {
where
R: Renderer + ImportAll + ImportMem,
{
inner: WaylandSurfaceRenderElement<R>, inner: WaylandSurfaceRenderElement<R>,
program: GlesTexProgram, program: GlesTexProgram,
radius: [u8; 4], radius: [u8; 4],
@ -48,7 +45,7 @@ where
impl<R> ClippedSurfaceRenderElement<R> impl<R> ClippedSurfaceRenderElement<R>
where where
R: Renderer + ImportAll + ImportMem, R: Renderer + ImportAll,
{ {
pub fn new( pub fn new(
renderer: &mut R, renderer: &mut R,
@ -174,7 +171,8 @@ where
impl<R> Element for ClippedSurfaceRenderElement<R> impl<R> Element for ClippedSurfaceRenderElement<R>
where where
R: Renderer + ImportAll + ImportMem, R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: 'static,
{ {
fn id(&self) -> &Id { fn id(&self) -> &Id {
self.inner.id() self.inner.id()
@ -247,7 +245,7 @@ where
impl<R> RenderElement<R> for ClippedSurfaceRenderElement<R> impl<R> RenderElement<R> for ClippedSurfaceRenderElement<R>
where where
R: AsGlowRenderer + Renderer + ImportAll + ImportMem, R: AsGlowRenderer + Renderer + ImportAll,
R::TextureId: 'static, R::TextureId: 'static,
{ {
fn draw( fn draw(

View file

@ -0,0 +1,111 @@
use smithay::{
backend::renderer::{
ImportAll, Renderer,
element::surface::{KindEvaluation, WaylandSurfaceRenderElement},
utils::RendererSurfaceStateUserData,
},
reexports::wayland_server::protocol::wl_surface,
render_elements,
utils::{Logical, Physical, Point, Rectangle, Scale},
wayland::compositor::{self, TraversalAction},
};
use tracing::warn;
use crate::backend::render::{
element::AsGlowRenderer, wayland::clipped_surface::ClippedSurfaceRenderElement,
};
pub mod clipped_surface;
render_elements! {
pub SurfaceRenderElement<R> where R: AsGlowRenderer + ImportAll;
Clipped=ClippedSurfaceRenderElement<R>,
Wayland=WaylandSurfaceRenderElement<R>,
}
pub fn render_elements_from_surface_tree<R, E>(
renderer: &mut R,
main_surface: &wl_surface::WlSurface,
location: impl Into<Point<i32, Physical>>,
geometry: impl Into<Rectangle<f64, Logical>>,
scale: impl Into<Scale<f64>>,
alpha: f32,
should_clip: bool,
radii: [u8; 4],
kind: impl Into<KindEvaluation>,
) -> Vec<E>
where
R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static,
E: From<SurfaceRenderElement<R>>,
{
let location = location.into().to_f64();
let geometry = geometry.into().to_f64();
let scale = scale.into();
let kind = kind.into();
let mut surfaces: Vec<E> = Vec::new();
compositor::with_surface_tree_downward(
main_surface,
location,
|_, states, location| {
let mut location = *location;
let data = states.data_map.get::<RendererSurfaceStateUserData>();
if let Some(data) = data {
if let Some(view) = data.lock().unwrap().view() {
location += view.offset.to_f64().to_physical(scale);
TraversalAction::DoChildren(location)
} else {
TraversalAction::SkipChildren
}
} else {
TraversalAction::SkipChildren
}
},
|surface, states, location| {
let mut location = *location;
let kind = kind.eval(states);
let data = states.data_map.get::<RendererSurfaceStateUserData>();
if let Some(data) = data {
let has_view = if let Some(view) = data.lock().unwrap().view() {
location += view.offset.to_f64().to_physical(scale);
true
} else {
false
};
if has_view {
match WaylandSurfaceRenderElement::from_surface(
renderer, surface, states, location, alpha, kind,
) {
Ok(Some(surface)) => {
let elem: SurfaceRenderElement<R> = if radii.iter().any(|r| *r != 0)
&& should_clip
&& ClippedSurfaceRenderElement::will_clip(
&surface, scale, geometry, radii,
) {
ClippedSurfaceRenderElement::new(
renderer, surface, scale, geometry, radii,
)
.into()
} else {
surface.into()
};
surfaces.push(elem.into());
}
Ok(None) => {} // surface is not mapped
Err(err) => {
warn!("Failed to import surface: {}", err);
}
};
}
}
},
|_, _, _| true,
);
surfaces
}

View file

@ -4,8 +4,8 @@ use super::{
}; };
use crate::{ use crate::{
backend::render::{ backend::render::{
IndicatorShader, Key, Usage, clipped_surface::ClippedSurfaceRenderElement, IndicatorShader, Key, Usage, cursor::CursorState, element::AsGlowRenderer,
cursor::CursorState, element::AsGlowRenderer, shadow::ShadowShader, shadow::ShadowShader, wayland::SurfaceRenderElement,
}, },
hooks::{Decorations, HOOKS}, hooks::{Decorations, HOOKS},
shell::{ shell::{
@ -41,7 +41,6 @@ use smithay::{
element::{ element::{
AsRenderElements, Element, Id as RendererId, Kind, RenderElement, AsRenderElements, Element, Id as RendererId, Kind, RenderElement,
UnderlyingStorage, memory::MemoryRenderBufferRenderElement, UnderlyingStorage, memory::MemoryRenderBufferRenderElement,
surface::WaylandSurfaceRenderElement,
}, },
gles::element::PixelShaderElement, gles::element::PixelShaderElement,
glow::GlowRenderer, glow::GlowRenderer,
@ -820,32 +819,16 @@ impl CosmicStack {
}); });
border.into_iter().chain( border.into_iter().chain(
windows[active] windows[active].render_elements::<R, CosmicStackRenderElement<R>>(
.render_elements::<R, WaylandSurfaceRenderElement<R>>( renderer,
renderer, window_loc,
window_loc, scale,
scale, alpha,
alpha, scanout_override,
scanout_override, scanout_node,
scanout_node, radii.is_some(),
) radii.unwrap_or([0; 4]),
.into_iter() ),
.map(move |elem| {
let radii = radii.map(|[a, _, c, _]| [a, 0, c, 0]);
if radii.is_some_and(|radii| {
ClippedSurfaceRenderElement::will_clip(&elem, scale, geo, radii)
}) {
CosmicStackRenderElement::Clipped(ClippedSurfaceRenderElement::new(
renderer,
elem,
scale,
geo,
radii.unwrap(),
))
} else {
CosmicStackRenderElement::Window(elem)
}
}),
) )
})); }));
@ -1885,8 +1868,7 @@ pub enum CosmicStackRenderElement<R: Renderer + ImportAll + ImportMem> {
Header(MemoryRenderBufferRenderElement<R>), Header(MemoryRenderBufferRenderElement<R>),
Shadow(PixelShaderElement), Shadow(PixelShaderElement),
Border(PixelShaderElement), Border(PixelShaderElement),
Window(WaylandSurfaceRenderElement<R>), Window(SurfaceRenderElement<R>),
Clipped(ClippedSurfaceRenderElement<R>),
} }
impl<R: Renderer + ImportAll + ImportMem> From<MemoryRenderBufferRenderElement<R>> impl<R: Renderer + ImportAll + ImportMem> From<MemoryRenderBufferRenderElement<R>>
@ -1897,25 +1879,18 @@ impl<R: Renderer + ImportAll + ImportMem> From<MemoryRenderBufferRenderElement<R
} }
} }
impl<R: Renderer + ImportAll + ImportMem> From<WaylandSurfaceRenderElement<R>> impl<R: Renderer + ImportAll + ImportMem> From<SurfaceRenderElement<R>>
for CosmicStackRenderElement<R> for CosmicStackRenderElement<R>
{ {
fn from(value: WaylandSurfaceRenderElement<R>) -> Self { fn from(value: SurfaceRenderElement<R>) -> Self {
Self::Window(value) Self::Window(value)
} }
} }
impl<R: Renderer + ImportAll + ImportMem> From<ClippedSurfaceRenderElement<R>>
for CosmicStackRenderElement<R>
{
fn from(value: ClippedSurfaceRenderElement<R>) -> Self {
Self::Clipped(value)
}
}
impl<R> Element for CosmicStackRenderElement<R> impl<R> Element for CosmicStackRenderElement<R>
where where
R: Renderer + ImportAll + ImportMem, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
R::TextureId: 'static,
{ {
fn id(&self) -> &RendererId { fn id(&self) -> &RendererId {
match self { match self {
@ -1923,7 +1898,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.id(), CosmicStackRenderElement::Shadow(elem) => elem.id(),
CosmicStackRenderElement::Border(elem) => elem.id(), CosmicStackRenderElement::Border(elem) => elem.id(),
CosmicStackRenderElement::Window(elem) => elem.id(), CosmicStackRenderElement::Window(elem) => elem.id(),
CosmicStackRenderElement::Clipped(elem) => elem.id(),
} }
} }
@ -1933,7 +1907,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.current_commit(), CosmicStackRenderElement::Shadow(elem) => elem.current_commit(),
CosmicStackRenderElement::Border(elem) => elem.current_commit(), CosmicStackRenderElement::Border(elem) => elem.current_commit(),
CosmicStackRenderElement::Window(elem) => elem.current_commit(), CosmicStackRenderElement::Window(elem) => elem.current_commit(),
CosmicStackRenderElement::Clipped(elem) => elem.current_commit(),
} }
} }
@ -1943,7 +1916,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.src(), CosmicStackRenderElement::Shadow(elem) => elem.src(),
CosmicStackRenderElement::Border(elem) => elem.src(), CosmicStackRenderElement::Border(elem) => elem.src(),
CosmicStackRenderElement::Window(elem) => elem.src(), CosmicStackRenderElement::Window(elem) => elem.src(),
CosmicStackRenderElement::Clipped(elem) => elem.src(),
} }
} }
@ -1953,7 +1925,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.geometry(scale), CosmicStackRenderElement::Shadow(elem) => elem.geometry(scale),
CosmicStackRenderElement::Border(elem) => elem.geometry(scale), CosmicStackRenderElement::Border(elem) => elem.geometry(scale),
CosmicStackRenderElement::Window(elem) => elem.geometry(scale), CosmicStackRenderElement::Window(elem) => elem.geometry(scale),
CosmicStackRenderElement::Clipped(elem) => elem.geometry(scale),
} }
} }
@ -1963,7 +1934,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.location(scale), CosmicStackRenderElement::Shadow(elem) => elem.location(scale),
CosmicStackRenderElement::Border(elem) => elem.location(scale), CosmicStackRenderElement::Border(elem) => elem.location(scale),
CosmicStackRenderElement::Window(elem) => elem.location(scale), CosmicStackRenderElement::Window(elem) => elem.location(scale),
CosmicStackRenderElement::Clipped(elem) => elem.location(scale),
} }
} }
@ -1973,7 +1943,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.transform(), CosmicStackRenderElement::Shadow(elem) => elem.transform(),
CosmicStackRenderElement::Border(elem) => elem.transform(), CosmicStackRenderElement::Border(elem) => elem.transform(),
CosmicStackRenderElement::Window(elem) => elem.transform(), CosmicStackRenderElement::Window(elem) => elem.transform(),
CosmicStackRenderElement::Clipped(elem) => elem.transform(),
} }
} }
@ -1987,7 +1956,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.damage_since(scale, commit), CosmicStackRenderElement::Shadow(elem) => elem.damage_since(scale, commit),
CosmicStackRenderElement::Border(elem) => elem.damage_since(scale, commit), CosmicStackRenderElement::Border(elem) => elem.damage_since(scale, commit),
CosmicStackRenderElement::Window(elem) => elem.damage_since(scale, commit), CosmicStackRenderElement::Window(elem) => elem.damage_since(scale, commit),
CosmicStackRenderElement::Clipped(elem) => elem.damage_since(scale, commit),
} }
} }
@ -1997,7 +1965,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.opaque_regions(scale), CosmicStackRenderElement::Shadow(elem) => elem.opaque_regions(scale),
CosmicStackRenderElement::Border(elem) => elem.opaque_regions(scale), CosmicStackRenderElement::Border(elem) => elem.opaque_regions(scale),
CosmicStackRenderElement::Window(elem) => elem.opaque_regions(scale), CosmicStackRenderElement::Window(elem) => elem.opaque_regions(scale),
CosmicStackRenderElement::Clipped(elem) => elem.opaque_regions(scale),
} }
} }
@ -2007,7 +1974,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.alpha(), CosmicStackRenderElement::Shadow(elem) => elem.alpha(),
CosmicStackRenderElement::Border(elem) => elem.alpha(), CosmicStackRenderElement::Border(elem) => elem.alpha(),
CosmicStackRenderElement::Window(elem) => elem.alpha(), CosmicStackRenderElement::Window(elem) => elem.alpha(),
CosmicStackRenderElement::Clipped(elem) => elem.alpha(),
} }
} }
@ -2017,7 +1983,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.kind(), CosmicStackRenderElement::Shadow(elem) => elem.kind(),
CosmicStackRenderElement::Border(elem) => elem.kind(), CosmicStackRenderElement::Border(elem) => elem.kind(),
CosmicStackRenderElement::Window(elem) => elem.kind(), CosmicStackRenderElement::Window(elem) => elem.kind(),
CosmicStackRenderElement::Clipped(elem) => elem.kind(),
} }
} }
@ -2027,7 +1992,6 @@ where
CosmicStackRenderElement::Shadow(elem) => elem.is_framebuffer_effect(), CosmicStackRenderElement::Shadow(elem) => elem.is_framebuffer_effect(),
CosmicStackRenderElement::Border(elem) => elem.is_framebuffer_effect(), CosmicStackRenderElement::Border(elem) => elem.is_framebuffer_effect(),
CosmicStackRenderElement::Window(elem) => elem.is_framebuffer_effect(), CosmicStackRenderElement::Window(elem) => elem.is_framebuffer_effect(),
CosmicStackRenderElement::Clipped(elem) => elem.is_framebuffer_effect(),
} }
} }
} }
@ -2039,7 +2003,7 @@ where
{ {
fn draw( fn draw(
&self, &self,
frame: &mut <R>::Frame<'_, '_>, frame: &mut R::Frame<'_, '_>,
src: Rectangle<f64, Buffer>, src: Rectangle<f64, Buffer>,
dst: Rectangle<i32, Physical>, dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>], damage: &[Rectangle<i32, Physical>],
@ -2065,9 +2029,6 @@ where
CosmicStackRenderElement::Window(elem) => { CosmicStackRenderElement::Window(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions, cache) elem.draw(frame, src, dst, damage, opaque_regions, cache)
} }
CosmicStackRenderElement::Clipped(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions, cache)
}
} }
} }
@ -2078,7 +2039,6 @@ where
elem.underlying_storage(renderer.glow_renderer_mut()) elem.underlying_storage(renderer.glow_renderer_mut())
} }
CosmicStackRenderElement::Window(elem) => elem.underlying_storage(renderer), CosmicStackRenderElement::Window(elem) => elem.underlying_storage(renderer),
CosmicStackRenderElement::Clipped(elem) => elem.underlying_storage(renderer),
} }
} }
@ -2106,9 +2066,6 @@ where
CosmicStackRenderElement::Window(elem) => { CosmicStackRenderElement::Window(elem) => {
elem.capture_framebuffer(frame, src, dst, cache) elem.capture_framebuffer(frame, src, dst, cache)
} }
CosmicStackRenderElement::Clipped(elem) => {
elem.capture_framebuffer(frame, src, dst, cache)
}
} }
} }
} }

View file

@ -1,4 +1,8 @@
use crate::{ use crate::{
backend::render::{
element::AsGlowRenderer,
wayland::{SurfaceRenderElement, render_elements_from_surface_tree},
},
shell::focus::target::PointerFocusTarget, shell::focus::target::PointerFocusTarget,
wayland::{ wayland::{
handlers::compositor::frame_time_filter_fn, protocols::corner_radius::CacheableCorners, handlers::compositor::frame_time_filter_fn, protocols::corner_radius::CacheableCorners,
@ -18,12 +22,7 @@ use smithay::{
drm::DrmNode, drm::DrmNode,
renderer::{ renderer::{
ImportAll, Renderer, ImportAll, Renderer,
element::{ element::{Kind, RenderElementStates, surface::KindEvaluation},
AsRenderElements, Kind, RenderElementStates,
surface::{
KindEvaluation, WaylandSurfaceRenderElement, render_elements_from_surface_tree,
},
},
utils::RendererSurfaceStateUserData, utils::RendererSurfaceStateUserData,
}, },
}, },
@ -869,9 +868,9 @@ impl CosmicSurface {
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<C> ) -> Vec<C>
where where
R: Renderer + ImportAll, R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
C: From<WaylandSurfaceRenderElement<R>>, C: From<SurfaceRenderElement<R>>,
{ {
match self.0.underlying_surface() { match self.0.underlying_surface() {
WindowSurface::Wayland(toplevel) => { WindowSurface::Wayland(toplevel) => {
@ -880,13 +879,18 @@ impl CosmicSurface {
.flat_map(move |(popup, popup_offset)| { .flat_map(move |(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);
let mut geometry = popup.geometry().to_f64();
geometry.loc += location.to_f64().to_logical(scale) + popup_offset.to_f64();
render_elements_from_surface_tree( render_elements_from_surface_tree(
renderer, renderer,
popup.wl_surface(), popup.wl_surface(),
location + offset, location + offset,
geometry,
scale, scale,
alpha, alpha,
false,
[0; 4],
scanout_kind_eval(None, scanout_node), scanout_kind_eval(None, scanout_node),
) )
}) })
@ -904,12 +908,17 @@ impl CosmicSurface {
alpha: f32, alpha: f32,
scanout_override: Option<bool>, scanout_override: Option<bool>,
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
should_clip: bool,
radii: [u8; 4],
) -> Vec<C> ) -> Vec<C>
where where
R: Renderer + ImportAll, R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
C: From<WaylandSurfaceRenderElement<R>>, C: From<SurfaceRenderElement<R>>,
{ {
let mut geometry = self.0.geometry().to_f64();
geometry.loc += location.to_f64().to_logical(scale);
match self.0.underlying_surface() { match self.0.underlying_surface() {
WindowSurface::Wayland(toplevel) => { WindowSurface::Wayland(toplevel) => {
let surface = toplevel.wl_surface(); let surface = toplevel.wl_surface();
@ -918,8 +927,11 @@ impl CosmicSurface {
renderer, renderer,
surface, surface,
location, location,
geometry,
scale, scale,
alpha, alpha,
should_clip,
radii,
scanout_kind_eval(scanout_override, scanout_node), scanout_kind_eval(scanout_override, scanout_node),
) )
} }
@ -932,8 +944,11 @@ impl CosmicSurface {
renderer, renderer,
&surface, &surface,
location, location,
geometry,
scale, scale,
alpha, alpha,
should_clip,
radii,
scanout_kind_eval(scanout_override, scanout_node), scanout_kind_eval(scanout_override, scanout_node),
) )
} }
@ -1078,24 +1093,6 @@ impl X11Relatable for CosmicSurface {
} }
} }
impl<R> AsRenderElements<R> for CosmicSurface
where
R: Renderer + ImportAll,
R::TextureId: Clone + 'static,
{
type RenderElement = WaylandSurfaceRenderElement<R>;
fn render_elements<C: From<Self::RenderElement>>(
&self,
renderer: &mut R,
location: Point<i32, Physical>,
scale: Scale<f64>,
alpha: f32,
) -> Vec<C> {
self.0.render_elements(renderer, location, scale, alpha)
}
}
fn with_toplevel_state<T, F: FnOnce(Option<&smithay::wayland::shell::xdg::ToplevelState>) -> T>( fn with_toplevel_state<T, F: FnOnce(Option<&smithay::wayland::shell::xdg::ToplevelState>) -> T>(
toplevel: &ToplevelSurface, toplevel: &ToplevelSurface,
pending: bool, pending: bool,

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
backend::render::{ backend::render::{
IndicatorShader, Key, Usage, clipped_surface::ClippedSurfaceRenderElement, IndicatorShader, Key, Usage, cursor::CursorState, element::AsGlowRenderer,
cursor::CursorState, element::AsGlowRenderer, shadow::ShadowShader, shadow::ShadowShader, wayland::SurfaceRenderElement,
}, },
hooks::{Decorations, HOOKS}, hooks::{Decorations, HOOKS},
shell::{ shell::{
@ -27,7 +27,6 @@ use smithay::{
element::{ element::{
AsRenderElements, Element, Id as RendererId, Kind, RenderElement, AsRenderElements, Element, Id as RendererId, Kind, RenderElement,
UnderlyingStorage, memory::MemoryRenderBufferRenderElement, UnderlyingStorage, memory::MemoryRenderBufferRenderElement,
surface::WaylandSurfaceRenderElement,
}, },
gles::element::PixelShaderElement, gles::element::PixelShaderElement,
glow::GlowRenderer, glow::GlowRenderer,
@ -358,7 +357,7 @@ impl CosmicWindow {
scanout_node: Option<DrmNode>, scanout_node: Option<DrmNode>,
) -> Vec<C> ) -> Vec<C>
where where
R: Renderer + ImportAll + ImportMem, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
C: From<CosmicWindowRenderElement<R>>, C: From<CosmicWindowRenderElement<R>>,
{ {
@ -549,36 +548,21 @@ impl CosmicWindow {
elements.push(elem); elements.push(elem);
} }
let window_elements = self.0.with_program(|p| { if has_ssd {
p.window radii[1] = 0;
.render_elements::<R, WaylandSurfaceRenderElement<R>>( radii[3] = 0;
renderer,
window_loc,
scale,
alpha,
scanout_override,
scanout_node,
)
});
if window_elements.is_empty() {
return Vec::new();
} }
elements.extend(self.0.with_program(|p| {
elements.extend(window_elements.into_iter().map(|elem| { p.window.render_elements::<R, CosmicWindowRenderElement<R>>(
if has_ssd { renderer,
radii[1] = 0; window_loc,
radii[3] = 0; scale,
} alpha,
if radii.iter().any(|x| *x != 0) scanout_override,
&& clip scanout_node,
&& ClippedSurfaceRenderElement::will_clip(&elem, scale, geo, radii) clip,
{ radii,
CosmicWindowRenderElement::Clipped(ClippedSurfaceRenderElement::new( )
renderer, elem, scale, geo, radii,
))
} else {
CosmicWindowRenderElement::Window(elem)
}
})); }));
if has_ssd { if has_ssd {
@ -1252,8 +1236,7 @@ pub enum CosmicWindowRenderElement<R: Renderer + ImportAll + ImportMem> {
Header(MemoryRenderBufferRenderElement<R>), Header(MemoryRenderBufferRenderElement<R>),
Shadow(PixelShaderElement), Shadow(PixelShaderElement),
Border(PixelShaderElement), Border(PixelShaderElement),
Window(WaylandSurfaceRenderElement<R>), Window(SurfaceRenderElement<R>),
Clipped(ClippedSurfaceRenderElement<R>),
} }
impl<R: Renderer + ImportAll + ImportMem> From<MemoryRenderBufferRenderElement<R>> impl<R: Renderer + ImportAll + ImportMem> From<MemoryRenderBufferRenderElement<R>>
@ -1264,25 +1247,18 @@ impl<R: Renderer + ImportAll + ImportMem> From<MemoryRenderBufferRenderElement<R
} }
} }
impl<R: Renderer + ImportAll + ImportMem> From<WaylandSurfaceRenderElement<R>> impl<R: Renderer + ImportAll + ImportMem> From<SurfaceRenderElement<R>>
for CosmicWindowRenderElement<R> for CosmicWindowRenderElement<R>
{ {
fn from(value: WaylandSurfaceRenderElement<R>) -> Self { fn from(value: SurfaceRenderElement<R>) -> Self {
Self::Window(value) Self::Window(value)
} }
} }
impl<R: Renderer + ImportAll + ImportMem> From<ClippedSurfaceRenderElement<R>>
for CosmicWindowRenderElement<R>
{
fn from(value: ClippedSurfaceRenderElement<R>) -> Self {
Self::Clipped(value)
}
}
impl<R> Element for CosmicWindowRenderElement<R> impl<R> Element for CosmicWindowRenderElement<R>
where where
R: Renderer + ImportAll + ImportMem, R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
R::TextureId: 'static,
{ {
fn id(&self) -> &RendererId { fn id(&self) -> &RendererId {
match self { match self {
@ -1290,7 +1266,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.id(), CosmicWindowRenderElement::Shadow(elem) => elem.id(),
CosmicWindowRenderElement::Border(elem) => elem.id(), CosmicWindowRenderElement::Border(elem) => elem.id(),
CosmicWindowRenderElement::Window(elem) => elem.id(), CosmicWindowRenderElement::Window(elem) => elem.id(),
CosmicWindowRenderElement::Clipped(elem) => elem.id(),
} }
} }
@ -1300,7 +1275,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.current_commit(), CosmicWindowRenderElement::Shadow(elem) => elem.current_commit(),
CosmicWindowRenderElement::Border(elem) => elem.current_commit(), CosmicWindowRenderElement::Border(elem) => elem.current_commit(),
CosmicWindowRenderElement::Window(elem) => elem.current_commit(), CosmicWindowRenderElement::Window(elem) => elem.current_commit(),
CosmicWindowRenderElement::Clipped(elem) => elem.current_commit(),
} }
} }
@ -1310,7 +1284,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.src(), CosmicWindowRenderElement::Shadow(elem) => elem.src(),
CosmicWindowRenderElement::Border(elem) => elem.src(), CosmicWindowRenderElement::Border(elem) => elem.src(),
CosmicWindowRenderElement::Window(elem) => elem.src(), CosmicWindowRenderElement::Window(elem) => elem.src(),
CosmicWindowRenderElement::Clipped(elem) => elem.src(),
} }
} }
@ -1320,7 +1293,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.geometry(scale), CosmicWindowRenderElement::Shadow(elem) => elem.geometry(scale),
CosmicWindowRenderElement::Border(elem) => elem.geometry(scale), CosmicWindowRenderElement::Border(elem) => elem.geometry(scale),
CosmicWindowRenderElement::Window(elem) => elem.geometry(scale), CosmicWindowRenderElement::Window(elem) => elem.geometry(scale),
CosmicWindowRenderElement::Clipped(elem) => elem.geometry(scale),
} }
} }
@ -1330,7 +1302,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.location(scale), CosmicWindowRenderElement::Shadow(elem) => elem.location(scale),
CosmicWindowRenderElement::Border(elem) => elem.location(scale), CosmicWindowRenderElement::Border(elem) => elem.location(scale),
CosmicWindowRenderElement::Window(elem) => elem.location(scale), CosmicWindowRenderElement::Window(elem) => elem.location(scale),
CosmicWindowRenderElement::Clipped(elem) => elem.location(scale),
} }
} }
@ -1340,7 +1311,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.transform(), CosmicWindowRenderElement::Shadow(elem) => elem.transform(),
CosmicWindowRenderElement::Border(elem) => elem.transform(), CosmicWindowRenderElement::Border(elem) => elem.transform(),
CosmicWindowRenderElement::Window(elem) => elem.transform(), CosmicWindowRenderElement::Window(elem) => elem.transform(),
CosmicWindowRenderElement::Clipped(elem) => elem.transform(),
} }
} }
@ -1354,7 +1324,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.damage_since(scale, commit), CosmicWindowRenderElement::Shadow(elem) => elem.damage_since(scale, commit),
CosmicWindowRenderElement::Border(elem) => elem.damage_since(scale, commit), CosmicWindowRenderElement::Border(elem) => elem.damage_since(scale, commit),
CosmicWindowRenderElement::Window(elem) => elem.damage_since(scale, commit), CosmicWindowRenderElement::Window(elem) => elem.damage_since(scale, commit),
CosmicWindowRenderElement::Clipped(elem) => elem.damage_since(scale, commit),
} }
} }
@ -1364,7 +1333,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.opaque_regions(scale), CosmicWindowRenderElement::Shadow(elem) => elem.opaque_regions(scale),
CosmicWindowRenderElement::Border(elem) => elem.opaque_regions(scale), CosmicWindowRenderElement::Border(elem) => elem.opaque_regions(scale),
CosmicWindowRenderElement::Window(elem) => elem.opaque_regions(scale), CosmicWindowRenderElement::Window(elem) => elem.opaque_regions(scale),
CosmicWindowRenderElement::Clipped(elem) => elem.opaque_regions(scale),
} }
} }
@ -1374,7 +1342,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.alpha(), CosmicWindowRenderElement::Shadow(elem) => elem.alpha(),
CosmicWindowRenderElement::Border(elem) => elem.alpha(), CosmicWindowRenderElement::Border(elem) => elem.alpha(),
CosmicWindowRenderElement::Window(elem) => elem.alpha(), CosmicWindowRenderElement::Window(elem) => elem.alpha(),
CosmicWindowRenderElement::Clipped(elem) => elem.alpha(),
} }
} }
@ -1384,7 +1351,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.kind(), CosmicWindowRenderElement::Shadow(elem) => elem.kind(),
CosmicWindowRenderElement::Border(elem) => elem.kind(), CosmicWindowRenderElement::Border(elem) => elem.kind(),
CosmicWindowRenderElement::Window(elem) => elem.kind(), CosmicWindowRenderElement::Window(elem) => elem.kind(),
CosmicWindowRenderElement::Clipped(elem) => elem.kind(),
} }
} }
@ -1394,7 +1360,6 @@ where
CosmicWindowRenderElement::Shadow(elem) => elem.is_framebuffer_effect(), CosmicWindowRenderElement::Shadow(elem) => elem.is_framebuffer_effect(),
CosmicWindowRenderElement::Border(elem) => elem.is_framebuffer_effect(), CosmicWindowRenderElement::Border(elem) => elem.is_framebuffer_effect(),
CosmicWindowRenderElement::Window(elem) => elem.is_framebuffer_effect(), CosmicWindowRenderElement::Window(elem) => elem.is_framebuffer_effect(),
CosmicWindowRenderElement::Clipped(elem) => elem.is_framebuffer_effect(),
} }
} }
} }
@ -1432,9 +1397,6 @@ where
CosmicWindowRenderElement::Window(elem) => { CosmicWindowRenderElement::Window(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions, cache) elem.draw(frame, src, dst, damage, opaque_regions, cache)
} }
CosmicWindowRenderElement::Clipped(elem) => {
elem.draw(frame, src, dst, damage, opaque_regions, cache)
}
} }
} }
@ -1445,7 +1407,6 @@ where
elem.underlying_storage(renderer.glow_renderer_mut()) elem.underlying_storage(renderer.glow_renderer_mut())
} }
CosmicWindowRenderElement::Window(elem) => elem.underlying_storage(renderer), CosmicWindowRenderElement::Window(elem) => elem.underlying_storage(renderer),
CosmicWindowRenderElement::Clipped(elem) => elem.underlying_storage(renderer),
} }
} }
@ -1473,9 +1434,6 @@ where
CosmicWindowRenderElement::Window(elem) => { CosmicWindowRenderElement::Window(elem) => {
elem.capture_framebuffer(frame, src, dst, cache) elem.capture_framebuffer(frame, src, dst, cache)
} }
CosmicWindowRenderElement::Clipped(elem) => {
elem.capture_framebuffer(frame, src, dst, cache)
}
} }
} }
} }

View file

@ -5395,29 +5395,33 @@ where
(swap_geo.loc.as_logical() - window_geo.loc).to_physical_precise_round(output_scale); (swap_geo.loc.as_logical() - window_geo.loc).to_physical_precise_round(output_scale);
swap_elements.extend( swap_elements.extend(
AsRenderElements::render_elements::<CosmicWindowRenderElement<R>>( window
&window, .render_elements(
renderer, renderer,
render_loc, render_loc,
output_scale.into(), output_scale.into(),
1.0, 1.0,
) None,
.into_iter() scanout_node,
.map(|window| { false,
CosmicMappedRenderElement::GrabbedWindow(RescaleRenderElement::from_element( [0; 4],
window, )
swap_geo .into_iter()
.loc .map(|window| {
.as_logical() CosmicMappedRenderElement::GrabbedWindow(RescaleRenderElement::from_element(
.to_physical_precise_round(output_scale), window,
ease( swap_geo
Linear, .loc
1.0, .as_logical()
swap_factor(window_geo.size), .to_physical_precise_round(output_scale),
transition.unwrap_or(1.0), ease(
), Linear,
)) 1.0,
}), swap_factor(window_geo.size),
transition.unwrap_or(1.0),
),
))
}),
) )
} }

View file

@ -1711,6 +1711,8 @@ impl Workspace {
alpha, alpha,
Some(true), Some(true),
scanout_node, scanout_node,
false,
[0; 4],
) )
.into_iter() .into_iter()
.map(animation_rescale) .map(animation_rescale)

View file

@ -3,9 +3,7 @@ use smithay::{
backend::{ backend::{
allocator::Fourcc, allocator::Fourcc,
renderer::{ renderer::{
ExportMem, ImportAll, Offscreen, Renderer, ExportMem, ImportAll, Offscreen, Renderer, damage::OutputDamageTracker,
damage::OutputDamageTracker,
element::{AsRenderElements, surface::WaylandSurfaceRenderElement},
gles::GlesRenderbuffer, gles::GlesRenderbuffer,
}, },
}, },
@ -16,7 +14,7 @@ use smithay::{
use tracing::warn; use tracing::warn;
use crate::{ use crate::{
backend::render::RendererRef, backend::render::{RendererRef, element::AsGlowRenderer, wayland::SurfaceRenderElement},
shell::element::CosmicSurface, shell::element::CosmicSurface,
state::{State, advertised_node_for_surface}, state::{State, advertised_node_for_surface},
}; };
@ -24,17 +22,20 @@ use crate::{
pub fn screenshot_window(state: &mut State, surface: &CosmicSurface) { pub fn screenshot_window(state: &mut State, surface: &CosmicSurface) {
fn render_window<R>(renderer: &mut R, window: &CosmicSurface) -> anyhow::Result<()> fn render_window<R>(renderer: &mut R, window: &CosmicSurface) -> anyhow::Result<()>
where where
R: Renderer + ImportAll + Offscreen<GlesRenderbuffer> + ExportMem, R: Renderer + ImportAll + Offscreen<GlesRenderbuffer> + ExportMem + AsGlowRenderer,
R::TextureId: Clone + 'static, R::TextureId: Clone + 'static,
R::Error: Send + Sync + 'static, R::Error: Send + Sync + 'static,
{ {
let bbox = bbox_from_surface_tree(&window.wl_surface().unwrap(), (0, 0)); let bbox = bbox_from_surface_tree(&window.wl_surface().unwrap(), (0, 0));
let elements = AsRenderElements::<R>::render_elements::<WaylandSurfaceRenderElement<R>>( let elements = window.render_elements::<R, SurfaceRenderElement<R>>(
window,
renderer, renderer,
(-bbox.loc.x, -bbox.loc.y).into(), (-bbox.loc.x, -bbox.loc.y).into(),
Scale::from(1.0), Scale::from(1.0),
1.0, 1.0,
None,
None,
false,
[0; 4],
); );
// TODO: 10-bit // TODO: 10-bit

View file

@ -9,8 +9,7 @@ use smithay::{
buffer_dimensions, buffer_type, buffer_dimensions, buffer_type,
damage::{Error as DTError, OutputDamageTracker, RenderOutputResult}, damage::{Error as DTError, OutputDamageTracker, RenderOutputResult},
element::{ element::{
AsRenderElements, RenderElement, RenderElement,
surface::WaylandSurfaceRenderElement,
utils::{Relocate, RelocateRenderElement}, utils::{Relocate, RelocateRenderElement},
}, },
gles::{GlesError, GlesRenderbuffer}, gles::{GlesError, GlesRenderbuffer},
@ -43,6 +42,7 @@ use crate::{
CursorMode, ElementFilter, RendererRef, cursor, CursorMode, ElementFilter, RendererRef, cursor,
element::{AsGlowRenderer, CosmicElement, DamageElement}, element::{AsGlowRenderer, CosmicElement, DamageElement},
render_workspace, render_workspace,
wayland::SurfaceRenderElement,
}, },
shell::{CosmicMappedRenderElement, CosmicSurface, WorkspaceRenderElement}, shell::{CosmicMappedRenderElement, CosmicSurface, WorkspaceRenderElement},
state::{Common, KmsNodes, State}, state::{Common, KmsNodes, State},
@ -501,8 +501,8 @@ pub fn render_workspace_to_buffer(
} }
smithay::render_elements! { smithay::render_elements! {
pub WindowCaptureElement<R> where R: ImportAll + ImportMem; pub WindowCaptureElement<R> where R: ImportAll + ImportMem + AsGlowRenderer;
WaylandElement=WaylandSurfaceRenderElement<R>, WaylandElement=SurfaceRenderElement<R>,
CursorElement=RelocateRenderElement<cursor::CursorRenderElement<R>>, CursorElement=RelocateRenderElement<cursor::CursorRenderElement<R>>,
} }
@ -628,14 +628,15 @@ pub fn render_window_to_buffer(
} }
} }
elements.extend(AsRenderElements::<R>::render_elements::< elements.extend(toplevel.render_elements::<R, WindowCaptureElement<R>>(
WindowCaptureElement<R>,
>(
toplevel,
renderer, renderer,
(-geometry.loc.x, -geometry.loc.y).into(), (-geometry.loc.x, -geometry.loc.y).into(),
Scale::from(1.0), Scale::from(1.0),
1.0, 1.0,
None,
None,
false,
[0; 4],
)); ));
if let Ok(dmabuf) = get_dmabuf(buffer) { if let Ok(dmabuf) = get_dmabuf(buffer) {