iced: Handle blur internally

This commit is contained in:
Victoria Brekenfeld 2026-04-21 18:16:43 +02:00 committed by Victoria Brekenfeld
parent 5ee2fa911a
commit ab9f13b36f
3 changed files with 74 additions and 15 deletions

View file

@ -1,6 +1,7 @@
use crate::{ use crate::{
backend::render::{GlMultiError, wayland::SurfaceRenderElement}, backend::render::{GlMultiError, wayland::SurfaceRenderElement},
shell::{CosmicMappedRenderElement, WorkspaceRenderElement}, shell::{CosmicMappedRenderElement, WorkspaceRenderElement},
utils::iced::IcedRenderElement,
}; };
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
@ -12,7 +13,6 @@ use smithay::{
Bind, Blit, ExportMem, ImportAll, ImportMem, Offscreen, Renderer, Bind, Blit, ExportMem, ImportAll, ImportMem, Offscreen, Renderer,
element::{ element::{
Element, Id, Kind, RenderElement, UnderlyingStorage, Element, Id, Kind, RenderElement, UnderlyingStorage,
memory::MemoryRenderBufferRenderElement,
utils::{CropRenderElement, Relocate, RelocateRenderElement, RescaleRenderElement}, utils::{CropRenderElement, Relocate, RelocateRenderElement, RescaleRenderElement},
}, },
gles::{GlesError, GlesRenderbuffer, GlesTexture, element::TextureShaderElement}, gles::{GlesError, GlesRenderbuffer, GlesTexture, element::TextureShaderElement},
@ -42,7 +42,7 @@ where
Postprocess( Postprocess(
CropRenderElement<RelocateRenderElement<RescaleRenderElement<TextureShaderElement>>>, CropRenderElement<RelocateRenderElement<RescaleRenderElement<TextureShaderElement>>>,
), ),
Zoom(MemoryRenderBufferRenderElement<R>), Zoom(IcedRenderElement<R>),
Damage(DamageElement), Damage(DamageElement),
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
Egui(TextureRenderElement<GlesTexture>), Egui(TextureRenderElement<GlesTexture>),
@ -344,13 +344,13 @@ where
} }
} }
impl<R> From<MemoryRenderBufferRenderElement<R>> for CosmicElement<R> impl<R> From<IcedRenderElement<R>> for CosmicElement<R>
where where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: 'static, R::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
{ {
fn from(value: MemoryRenderBufferRenderElement<R>) -> Self { fn from(value: IcedRenderElement<R>) -> Self {
Self::Zoom(value) Self::Zoom(value)
} }
} }

View file

@ -1,7 +1,10 @@
use crate::{ use crate::{
backend::render::element::AsGlowRenderer, backend::render::element::AsGlowRenderer,
state::State, state::State,
utils::{iced::IcedElementInternal, prelude::*}, utils::{
iced::{IcedElementInternal, IcedRenderElement},
prelude::*,
},
}; };
use calloop::LoopHandle; use calloop::LoopHandle;
use cosmic_comp_config::AppearanceConfig; use cosmic_comp_config::AppearanceConfig;
@ -13,7 +16,6 @@ use smithay::{
renderer::{ renderer::{
element::{ element::{
Element, Kind, RenderElement, UnderlyingStorage, Element, Kind, RenderElement, UnderlyingStorage,
memory::MemoryRenderBufferRenderElement,
utils::{CropRenderElement, RelocateRenderElement, RescaleRenderElement}, utils::{CropRenderElement, RelocateRenderElement, RescaleRenderElement},
}, },
gles::element::PixelShaderElement, gles::element::PixelShaderElement,
@ -1127,7 +1129,7 @@ where
GrabbedWindow(RescaleRenderElement<self::window::CosmicWindowRenderElement<R>>), GrabbedWindow(RescaleRenderElement<self::window::CosmicWindowRenderElement<R>>),
FocusIndicator(PixelShaderElement), FocusIndicator(PixelShaderElement),
Overlay(PixelShaderElement), Overlay(PixelShaderElement),
StackHoverIndicator(MemoryRenderBufferRenderElement<R>), StackHoverIndicator(IcedRenderElement<R>),
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
Egui(TextureRenderElement<GlesTexture>), Egui(TextureRenderElement<GlesTexture>),
} }
@ -1581,13 +1583,13 @@ where
} }
} }
impl<R> From<MemoryRenderBufferRenderElement<R>> for CosmicMappedRenderElement<R> impl<R> From<IcedRenderElement<R>> for CosmicMappedRenderElement<R>
where where
R: AsGlowRenderer, R: AsGlowRenderer,
R::TextureId: 'static, R::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>, CosmicMappedRenderElement<R>: RenderElement<R>,
{ {
fn from(elem: MemoryRenderBufferRenderElement<R>) -> Self { fn from(elem: IcedRenderElement<R>) -> Self {
CosmicMappedRenderElement::StackHoverIndicator(elem) CosmicMappedRenderElement::StackHoverIndicator(elem)
} }
} }

View file

@ -33,7 +33,7 @@ use smithay::{
allocator::Fourcc, allocator::Fourcc,
input::{ButtonState, KeyState}, input::{ButtonState, KeyState},
renderer::{ renderer::{
ImportMem, Renderer, ImportMem,
element::{ element::{
Kind, Kind,
memory::{MemoryRenderBuffer, MemoryRenderBufferRenderElement}, memory::{MemoryRenderBuffer, MemoryRenderBufferRenderElement},
@ -57,13 +57,20 @@ use smithay::{
}, },
output::Output, output::Output,
reexports::calloop::{self, LoopHandle, RegistrationToken, futures::Scheduler}, reexports::calloop::{self, LoopHandle, RegistrationToken, futures::Scheduler},
render_elements,
utils::{ utils::{
Buffer as BufferCoords, IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial, Size, Buffer as BufferCoords, IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial, Size,
Transform, Transform,
}, },
}; };
use crate::utils::iced::state::State; use crate::{
backend::render::{
element::AsGlowRenderer,
wayland::blur_effect::{BlurElement, BlurState},
},
utils::iced::state::State,
};
static ID: LazyLock<Id> = LazyLock::new(|| Id::new("Program")); static ID: LazyLock<Id> = LazyLock::new(|| Id::new("Program"));
@ -173,6 +180,7 @@ pub(crate) struct IcedElementInternal<P: Program + Send + 'static> {
outputs: HashSet<Output>, outputs: HashSet<Output>,
buffers: HashMap<OrderedFloat<f64>, (MemoryRenderBuffer, Option<(Vec<Layer>, Color)>)>, buffers: HashMap<OrderedFloat<f64>, (MemoryRenderBuffer, Option<(Vec<Layer>, Color)>)>,
pending_realloc: bool, pending_realloc: bool,
blur: BlurState,
// state // state
size: Size<i32, Logical>, size: Size<i32, Logical>,
@ -225,6 +233,7 @@ impl<P: Program + Send + Clone + 'static> Clone for IcedElementInternal<P> {
outputs: self.outputs.clone(), outputs: self.outputs.clone(),
buffers: self.buffers.clone(), buffers: self.buffers.clone(),
pending_realloc: self.pending_realloc, pending_realloc: self.pending_realloc,
blur: BlurState::default(),
size: self.size, size: self.size,
last_seat: self.last_seat.clone(), last_seat: self.last_seat.clone(),
cursor_pos: self.cursor_pos, cursor_pos: self.cursor_pos,
@ -310,6 +319,7 @@ impl<P: Program + Send + 'static> IcedElement<P> {
outputs: HashSet::new(), outputs: HashSet::new(),
buffers: HashMap::new(), buffers: HashMap::new(),
pending_realloc: false, pending_realloc: false,
blur: BlurState::default(),
size, size,
cursor_pos: None, cursor_pos: None,
last_seat, last_seat,
@ -342,7 +352,6 @@ impl<P: Program + Send + 'static> IcedElement<P> {
let node = element let node = element
.as_widget_mut() .as_widget_mut()
.layout( .layout(
// TODO Avoid creating a new tree here?
&mut tree, &mut tree,
&internal.renderer, &internal.renderer,
&Limits::new(IcedSize::ZERO, IcedSize::INFINITE) &Limits::new(IcedSize::ZERO, IcedSize::INFINITE)
@ -386,6 +395,11 @@ impl<P: Program + Send + 'static> IcedElement<P> {
self.0.lock().unwrap().update(true); self.0.lock().unwrap().update(true);
} }
pub fn with_theme<R: 'static>(&self, f: impl FnOnce(&Theme) -> R) -> R {
let guard = self.0.lock().unwrap();
f(&guard.theme)
}
pub fn set_theme(&self, theme: cosmic::Theme) { pub fn set_theme(&self, theme: cosmic::Theme) {
let mut guard = self.0.lock().unwrap(); let mut guard = self.0.lock().unwrap();
guard.theme = theme.clone(); guard.theme = theme.clone();
@ -917,9 +931,11 @@ impl<P: Program + Send + 'static> IcedElement<P> {
location: Point<i32, Physical>, location: Point<i32, Physical>,
mut scale: Scale<f64>, mut scale: Scale<f64>,
alpha: f32, alpha: f32,
push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>), mut radii: [u8; 4],
push_above: &mut dyn FnMut(IcedRenderElement<R>),
push_below: Option<&mut dyn FnMut(IcedRenderElement<R>)>,
) where ) where
R: Renderer + ImportMem, R: AsGlowRenderer + ImportMem,
R::TextureId: Send + Clone + 'static, R::TextureId: Send + Clone + 'static,
{ {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
@ -1052,10 +1068,51 @@ impl<P: Program + Send + 'static> IcedElement<P> {
Kind::Unspecified, Kind::Unspecified,
) { ) {
Ok(buffer) => { Ok(buffer) => {
push(buffer); push_above(buffer.into());
} }
Err(err) => tracing::warn!("What? {:?}", err), Err(err) => tracing::warn!("What? {:?}", err),
} }
if internal_ref.theme.transparent {
for radius in radii.iter_mut() {
*radius = ((*radius as f64) * internal_ref.additional_scale).round() as u8;
}
match BlurElement::from_state(
renderer,
&mut internal_ref.blur,
Rectangle::new(
location
.to_f64()
.to_logical(scale)
.upscale(internal_ref.additional_scale),
internal_ref
.size
.to_f64()
.upscale(internal_ref.additional_scale)
.to_i32_round(),
),
scale.x,
radii,
(internal_ref.theme.cosmic().frosted as u8 + 1) as usize,
) {
Ok(Some(elem)) => {
if let Some(push_below) = push_below {
push_below(elem.into())
} else {
push_above(elem.into())
}
}
Ok(None) => {}
Err(err) => tracing::warn!("Blur elem error: {:?}", err),
}
}
} }
} }
} }
render_elements! {
pub IcedRenderElement<R> where R: ImportMem + AsGlowRenderer;
UI=MemoryRenderBufferRenderElement<R>,
Blur=BlurElement,
}