From acc03e0d9817ceaef17457f0300cef9afccdc89d Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Mon, 10 Mar 2025 12:54:26 +0100 Subject: [PATCH 1/2] renderer/gl{es, ow}: Provide `with_context_bound_fb` --- src/backend/renderer/gles/mod.rs | 18 ++++++++++++++++++ src/backend/renderer/glow.rs | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/backend/renderer/gles/mod.rs b/src/backend/renderer/gles/mod.rs index efbfe1d9fe8c..1c633df6680b 100644 --- a/src/backend/renderer/gles/mod.rs +++ b/src/backend/renderer/gles/mod.rs @@ -1788,6 +1788,24 @@ impl GlesRenderer { Ok(func(&self.gl)) } + /// Run custom code in the GL context owned by this renderer after turning + /// the given target into the current framebuffer. + /// + /// The OpenGL state of the renderer is considered an implementation detail + /// and no guarantee is made about what can or cannot be changed, + /// as such you should reset everything you change back to its previous value + /// or check the source code of the version of Smithay you are using to ensure + /// your changes don't interfere with the renderer's behavior. + /// Doing otherwise can lead to rendering errors while using other functions of this renderer. + #[instrument(level = "trace", parent = &self.span, skip_all)] + pub fn with_context_bound_fb(&mut self, fb: &GlesTarget<'_>, func: F) -> Result + where + F: FnOnce(&ffi::Gles2) -> R, + { + fb.0.make_current(&self.gl, &self.egl)?; + Ok(func(&self.gl)) + } + /// Compile a custom pixel shader for rendering with [`GlesFrame::render_pixel_shader_to`]. /// /// Pixel shaders can be used for completely shader-driven drawing into a given region. diff --git a/src/backend/renderer/glow.rs b/src/backend/renderer/glow.rs index 85d66f89d64e..c19dbeeda897 100644 --- a/src/backend/renderer/glow.rs +++ b/src/backend/renderer/glow.rs @@ -134,6 +134,23 @@ impl GlowRenderer { } Ok(func(&self.glow)) } + + /// Run custom code in the GL context owned by this renderer after turning + /// the given target into the current framebuffer. + /// + /// The OpenGL state of the renderer is considered an implementation detail + /// and no guarantee is made about what can or cannot be changed, + /// as such you should reset everything you change back to its previous value + /// or check the source code of the version of Smithay you are using to ensure + /// your changes don't interfere with the renderer's behavior. + /// Doing otherwise can lead to rendering errors while using other functions of this renderer. + pub fn with_context_bound_fb(&mut self, fb: &GlesTarget<'_>, func: F) -> Result + where + F: FnOnce(&Arc) -> R, + { + fb.0.make_current(&self.gl.gl, &self.gl.egl_context()); + Ok(func(&self.glow)) + } } impl GlowFrame<'_, '_> { From 56bb09a012a4ea094446d2f8ce1068b24de4c27e Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Mon, 10 Mar 2025 12:54:45 +0100 Subject: [PATCH 2/2] winit: Fix `buffer_age` to work with new bind api --- src/backend/winit/mod.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/backend/winit/mod.rs b/src/backend/winit/mod.rs index a226576624f4..b175759c1c29 100644 --- a/src/backend/winit/mod.rs +++ b/src/backend/winit/mod.rs @@ -18,6 +18,7 @@ //! The other types in this module are the instances of the associated types of these //! two traits for the winit backend. +use std::borrow::BorrowMut; use std::io::Error as IoError; use std::sync::Arc; use std::time::Duration; @@ -251,7 +252,7 @@ pub struct WinitGraphicsBackend { impl WinitGraphicsBackend where - R: Bind, + R: Bind + BorrowMut, crate::backend::SwapBuffersError: From, { /// Window size of the underlying window @@ -304,15 +305,24 @@ where /// Retrieve the buffer age of the current backbuffer of the window. /// - /// This will only return a meaningful value, if this `WinitGraphicsBackend` - /// is currently bound (by previously calling [`WinitGraphicsBackend::bind`]). - /// - /// Otherwise and on error this function returns `None`. + /// On error this function returns `None`. /// If you are using this value actively e.g. for damage-tracking you should /// likely interpret an error just as if "0" was returned. #[instrument(level = "trace", parent = &self.span, skip(self))] - pub fn buffer_age(&self) -> Option { + pub fn buffer_age(&mut self) -> Option { if self.damage_tracking { + { + let window_size = self.window_size(); + if Some(window_size) != self.bind_size { + self.egl_surface.resize(window_size.w, window_size.h, 0, 0); + } + self.bind_size = Some(window_size); + + let gles = self.renderer.borrow_mut(); + let fb = gles.bind(&mut self.egl_surface).ok()?; + gles.with_context_bound_fb(&fb, |_| {}).ok()?; + // We know the gles renderer doesn't unbind the framebuffer from dropping + } self.egl_surface.buffer_age().map(|x| x as usize) } else { Some(0)