render/blur: Cache native texture type

This commit is contained in:
Victoria Brekenfeld 2026-06-11 13:18:41 +02:00 committed by Victoria Brekenfeld
parent c92b91221c
commit f6cb4519a0
11 changed files with 74 additions and 61 deletions

View file

@ -175,7 +175,7 @@ fn load_icon(theme: &CursorTheme, shape: CursorIcon) -> Result<Vec<Image>, Error
}
render_elements! {
pub CursorRenderElement<R> where R: ImportAll + ImportMem + AsGlowRenderer;
pub CursorRenderElement<R> where R: ImportAll + ImportMem + AsGlowRenderer, R::TextureId: Send;
Static=MemoryRenderBufferRenderElement<R>,
Surface=SurfaceRenderElement<R>,
}

View file

@ -1,5 +1,8 @@
use crate::{
backend::render::{GlMultiError, wayland::SurfaceRenderElement},
backend::{
kms::render::gles::GbmGlowBackend,
render::{GlMultiError, wayland::SurfaceRenderElement},
},
shell::{CosmicMappedRenderElement, WorkspaceRenderElement},
utils::iced::IcedRenderElement,
};
@ -37,7 +40,7 @@ use super::{GlMultiRenderer, cursor::CursorRenderElement};
pub enum CosmicElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
Workspace(
@ -58,7 +61,7 @@ where
impl<R> Element for CosmicElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn id(&self) -> &Id {
@ -223,7 +226,7 @@ where
impl<R> RenderElement<R> for CosmicElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn draw(
@ -339,7 +342,7 @@ impl<R> From<CropRenderElement<RescaleRenderElement<WorkspaceRenderElement<R>>>>
for CosmicElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(elem: CropRenderElement<RescaleRenderElement<WorkspaceRenderElement<R>>>) -> Self {
@ -354,7 +357,7 @@ where
impl<R> From<IcedRenderElement<R>> for CosmicElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(value: IcedRenderElement<R>) -> Self {
@ -365,7 +368,7 @@ where
impl<R> From<DamageElement> for CosmicElement<R>
where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(value: DamageElement) -> Self {
@ -377,7 +380,7 @@ where
impl<R> From<TextureRenderElement<GlesTexture>> for CosmicElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(elem: TextureRenderElement<GlesTexture>) -> Self {

View file

@ -9,7 +9,7 @@ use smithay::{
allocator::Fourcc,
renderer::{
Bind, BlitFrame, Color32F, ContextId, Frame, FrameContext, ImportAll, Offscreen,
Renderer, Texture, TextureFilter,
Renderer, RendererSuper, Texture, TextureFilter,
element::{Element, Id, Kind, RenderElement},
gles::{
GlesError, GlesFrame, GlesRenderer, GlesTexProgram, GlesTexture, Uniform,
@ -115,7 +115,7 @@ impl BlurShaders {
}
}
type BlurTexture = Mutex<Option<GlesTexture>>;
type BlurTexture<T: Texture> = Mutex<Option<T>>;
#[derive(Debug)]
pub struct BlurState {
@ -369,7 +369,10 @@ impl Element for BlurElement {
}
}
impl<R: Renderer + AsGlowRenderer> RenderElement<R> for BlurElement {
impl<R: Renderer + AsGlowRenderer> RenderElement<R> for BlurElement
where
R::TextureId: Send + 'static,
{
fn capture_framebuffer(
&self,
frame: &mut <R>::Frame<'_, '_>,
@ -377,41 +380,48 @@ impl<R: Renderer + AsGlowRenderer> RenderElement<R> for BlurElement {
dst: Rectangle<i32, Physical>,
cache: &UserDataMap,
) -> Result<(), <R>::Error> {
let transform = frame.transformation();
let tex_size = self.src.to_i32_round();
let glow_frame = <R as AsGlowRenderer>::glow_frame_mut(frame);
let gles_frame = BorrowMut::<GlesFrame<'_, '_>>::borrow_mut(glow_frame);
let transform = gles_frame.transformation();
let tex_size = self.src.to_i32_round();
let mut renderer = gles_frame.renderer();
let texture_ref = cache.get_or_insert_threadsafe(BlurTexture::default);
let texture_ref = cache.get_or_insert_threadsafe(BlurTexture::<R::TextureId>::default);
let mut texture_entry = texture_ref.lock().unwrap();
if texture_entry
.as_ref()
.is_some_and(|tex| tex.size() != tex_size)
{
if texture_entry.as_ref().is_some_and(|tex| {
tex.size() != tex_size
|| R::tex_to_gl(
&renderer.as_ref().context_id(),
texture_entry.as_ref().unwrap(),
)
.is_none()
}) {
texture_entry.take();
}
let mut renderer = gles_frame.renderer();
if texture_entry.is_none() {
*texture_entry = Some(
renderer
let gl_texture = renderer
.as_mut()
.create_buffer(Fourcc::Abgr8888, tex_size)
.map_err(R::from_gles_error)?,
);
.map_err(R::from_gles_error)?;
*texture_entry = Some(R::tex_from_gl(&renderer.as_ref().context_id(), gl_texture));
}
let texture = texture_entry.as_mut().unwrap();
let mut texture = R::tex_to_gl(
&renderer.as_ref().context_id(),
texture_entry.as_ref().unwrap(),
)
.unwrap();
let mut off_texture = renderer
.as_mut()
.create_buffer(Fourcc::Abgr8888, tex_size)
.map_err(R::from_gles_error)?;
std::mem::drop(renderer);
let sync = blit_from_active_fb(gles_frame, src, dst, transform, texture)
let sync = blit_from_active_fb(gles_frame, src, dst, transform, &mut texture)
.map_err(R::from_gles_error)?;
gles_frame.wait(&sync).map_err(R::from_gles_error)?;
let mut textures = [texture, &mut off_texture];
let mut textures = [&mut texture, &mut off_texture];
render_blur(
gles_frame.renderer().as_mut(),
&self.scaling_shaders,
@ -433,7 +443,6 @@ impl<R: Renderer + AsGlowRenderer> RenderElement<R> for BlurElement {
opaque_regions: &[Rectangle<i32, Physical>],
cache: Option<&UserDataMap>,
) -> Result<(), R::Error> {
let glow_frame = <R as AsGlowRenderer>::glow_frame_mut(frame);
let src_to_geo = self.geometry.size / self.src;
let src_log = src
.upscale(src_to_geo)
@ -451,26 +460,27 @@ impl<R: Renderer + AsGlowRenderer> RenderElement<R> for BlurElement {
.flat_map(|rect| damage.iter().flat_map(move |r| r.intersection(rect)))
.collect::<Vec<_>>();
let cache = cache.expect("Framebuffer element without cache?");
let Some(texture) = cache.get::<BlurTexture>() else {
let Some(texture) = cache.get::<BlurTexture<R::TextureId>>() else {
return Err(R::from_gles_error(GlesError::BlitError));
};
let texture_ref = texture.lock().unwrap();
BorrowMut::<GlesFrame<'_, '_>>::borrow_mut(glow_frame)
.render_texture_from_to(
texture_ref
.as_ref()
.ok_or(R::from_gles_error(GlesError::BlitError))?,
if let Some(tex) = texture_ref.as_ref() {
BorrowMut::<GlesFrame>::borrow_mut(<R as AsGlowRenderer>::glow_frame_mut(frame))
.override_default_tex_program(self.render_shader.clone(), self.uniforms.clone());
frame.render_texture_from_to(
tex,
src,
dst,
&damage,
opaque_regions,
&opaque_regions,
Transform::Normal,
1.0,
Some(&self.render_shader),
&self.uniforms,
)
.map_err(R::from_gles_error)
)?;
BorrowMut::<GlesFrame>::borrow_mut(<R as AsGlowRenderer>::glow_frame_mut(frame))
.clear_tex_program_override();
}
Ok(())
}
}

View file

@ -20,7 +20,7 @@ pub mod blur_effect;
pub mod clipped_surface;
render_elements! {
pub SurfaceRenderElement<R> where R: AsGlowRenderer + ImportAll;
pub SurfaceRenderElement<R> where R: AsGlowRenderer + ImportAll, R::TextureId: Send;
Blur=BlurElement,
Clipped=ClippedSurfaceRenderElement<R>,
Wayland=WaylandSurfaceRenderElement<R>,

View file

@ -1137,7 +1137,7 @@ where
impl<R> Element for CosmicMappedRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
{
fn id(&self) -> &smithay::backend::renderer::element::Id {
match self {
@ -1358,7 +1358,7 @@ where
impl<R> RenderElement<R> for CosmicMappedRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
{
fn draw(
&self,

View file

@ -1927,7 +1927,7 @@ impl<R: Renderer + ImportAll + ImportMem> From<SurfaceRenderElement<R>>
impl<R> Element for CosmicStackRenderElement<R>
where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
{
fn id(&self) -> &RendererId {
match self {
@ -2036,7 +2036,7 @@ where
impl<R> RenderElement<R> for CosmicStackRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
{
fn draw(
&self,

View file

@ -1275,7 +1275,7 @@ impl<R: AsGlowRenderer + ImportAll + ImportMem> From<SurfaceRenderElement<R>>
impl<R> Element for CosmicWindowRenderElement<R>
where
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
{
fn id(&self) -> &RendererId {
match self {
@ -1384,7 +1384,7 @@ where
impl<R> RenderElement<R> for CosmicWindowRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
{
fn draw(
&self,

View file

@ -1973,7 +1973,7 @@ pub struct OutputNotMapped;
pub enum WorkspaceRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
{
OverrideRedirect(SurfaceRenderElement<R>),
LowerLayerShell(NamespacedElement<SurfaceRenderElement<R>>),
@ -1986,7 +1986,7 @@ where
impl<R> Element for WorkspaceRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
{
fn id(&self) -> &smithay::backend::renderer::element::Id {
match self {
@ -2117,7 +2117,7 @@ where
impl<R> RenderElement<R> for WorkspaceRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
{
fn draw(
&self,
@ -2213,7 +2213,7 @@ where
impl<R> From<RescaleRenderElement<CosmicWindowRenderElement<R>>> for WorkspaceRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(elem: RescaleRenderElement<CosmicWindowRenderElement<R>>) -> Self {
@ -2224,7 +2224,7 @@ where
impl<R> From<CosmicWindowRenderElement<R>> for WorkspaceRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(elem: CosmicWindowRenderElement<R>) -> Self {
@ -2235,7 +2235,7 @@ where
impl<R> From<SurfaceRenderElement<R>> for WorkspaceRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(elem: SurfaceRenderElement<R>) -> Self {
@ -2246,7 +2246,7 @@ where
impl<R> From<NamespacedElement<SurfaceRenderElement<R>>> for WorkspaceRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(elem: NamespacedElement<SurfaceRenderElement<R>>) -> Self {
@ -2257,7 +2257,7 @@ where
impl<R> From<CosmicMappedRenderElement<R>> for WorkspaceRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(elem: CosmicMappedRenderElement<R>) -> Self {
@ -2268,7 +2268,7 @@ where
impl<R> From<TextureRenderElement<GlesTexture>> for WorkspaceRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
R::TextureId: Send + 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(elem: TextureRenderElement<GlesTexture>) -> Self {

View file

@ -1112,7 +1112,7 @@ impl<P: Program + Send + 'static> IcedElement<P> {
}
render_elements! {
pub IcedRenderElement<R> where R: ImportMem + AsGlowRenderer;
pub IcedRenderElement<R> where R: ImportMem + AsGlowRenderer, R::TextureId: Send;
UI=MemoryRenderBufferRenderElement<R>,
Blur=BlurElement,
}

View file

@ -23,7 +23,7 @@ pub fn screenshot_window(state: &mut State, surface: &CosmicSurface) {
fn render_window<R>(renderer: &mut R, window: &CosmicSurface) -> anyhow::Result<()>
where
R: Renderer + ImportAll + Offscreen<GlesRenderbuffer> + ExportMem + AsGlowRenderer,
R::TextureId: Clone + 'static,
R::TextureId: Send + Clone + 'static,
R::Error: Send + Sync + 'static,
{
let bbox = bbox_from_surface_tree(&window.wl_surface().unwrap(), (0, 0));

View file

@ -502,7 +502,7 @@ pub fn render_workspace_to_buffer(
}
smithay::render_elements! {
pub WindowCaptureElement<R> where R: ImportAll + ImportMem + AsGlowRenderer;
pub WindowCaptureElement<R> where R: ImportAll + ImportMem + AsGlowRenderer, R::TextureId: Send;
WaylandElement=SurfaceRenderElement<R>,
CursorElement=RelocateRenderElement<cursor::CursorRenderElement<R>>,
DamageElement=DamageElement,