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

View file

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

View file

@ -15,9 +15,9 @@ use crate::{
backend::{
kms::render::gles::GbmGlowBackend,
render::{
clipped_surface::{CLIPPING_SHADER, ClippingShader},
element::DamageElement,
shadow::{SHADOW_SHADER, ShadowShader},
wayland::clipped_surface::{CLIPPING_SHADER, ClippingShader},
},
},
config::ScreenFilter,
@ -80,10 +80,10 @@ use smithay::{
use smithay_egui::EguiState;
pub mod animations;
pub mod clipped_surface;
pub mod cursor;
pub mod element;
pub mod shadow;
pub mod wayland;
use self::element::{AsGlowRenderer, CosmicElement};
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::{
backend::renderer::{
ImportAll, ImportMem, Renderer,
ImportAll, Renderer,
element::{
Element, Id, Kind, RenderElement, UnderlyingStorage,
surface::WaylandSurfaceRenderElement,
@ -19,7 +19,7 @@ use smithay::{
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);
impl ClippingShader {
@ -35,10 +35,7 @@ impl ClippingShader {
}
#[derive(Debug)]
pub struct ClippedSurfaceRenderElement<R>
where
R: Renderer + ImportAll + ImportMem,
{
pub struct ClippedSurfaceRenderElement<R: Renderer> {
inner: WaylandSurfaceRenderElement<R>,
program: GlesTexProgram,
radius: [u8; 4],
@ -48,7 +45,7 @@ where
impl<R> ClippedSurfaceRenderElement<R>
where
R: Renderer + ImportAll + ImportMem,
R: Renderer + ImportAll,
{
pub fn new(
renderer: &mut R,
@ -174,7 +171,8 @@ where
impl<R> Element for ClippedSurfaceRenderElement<R>
where
R: Renderer + ImportAll + ImportMem,
R: Renderer + ImportAll + AsGlowRenderer,
R::TextureId: 'static,
{
fn id(&self) -> &Id {
self.inner.id()
@ -247,7 +245,7 @@ where
impl<R> RenderElement<R> for ClippedSurfaceRenderElement<R>
where
R: AsGlowRenderer + Renderer + ImportAll + ImportMem,
R: AsGlowRenderer + Renderer + ImportAll,
R::TextureId: 'static,
{
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
}