From 3680fb9b90a165f5e23ae7219f38ecdf99233b4b Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Fri, 21 Oct 2022 20:21:45 +0200 Subject: [PATCH] egl: Allow both EXT/KHR impls for SwapBuffers to be used --- build.rs | 1 + src/backend/egl/display.rs | 47 ++++++++++++++++++++++++++++++++++++++ src/backend/egl/native.rs | 27 ++++++++++++++++------ src/backend/egl/surface.rs | 7 ++++-- src/backend/winit/mod.rs | 5 +--- 5 files changed, 74 insertions(+), 13 deletions(-) diff --git a/build.rs b/build.rs index e8f8c3b5d9..eed09751a2 100644 --- a/build.rs +++ b/build.rs @@ -40,6 +40,7 @@ fn gl_generate() { "EGL_KHR_gl_image", "EGL_EXT_buffer_age", "EGL_EXT_swap_buffers_with_damage", + "EGL_KHR_swap_buffers_with_damage", ], ) .write_bindings(gl_generator::GlobalGenerator, &mut file) diff --git a/src/backend/egl/display.rs b/src/backend/egl/display.rs index eb572bae35..6335ae56cf 100644 --- a/src/backend/egl/display.rs +++ b/src/backend/egl/display.rs @@ -517,6 +517,32 @@ impl EGLDisplay { &self.dmabuf_import_formats } + /// Returns when the display supports extensions required for smithays + /// damage tracking helpers. + pub fn supports_damage(&self) -> bool { + self.supports_damage_impl().supported() + } + + pub(super) fn supports_damage_impl(&self) -> DamageSupport { + if self.extensions.iter().any(|ext| ext == "EGL_EXT_buffer_age") { + if self + .extensions + .iter() + .any(|ext| ext == "EGL_KHR_swap_buffers_with_damage") + { + return DamageSupport::KHR; + } else if self + .extensions + .iter() + .any(|ext| ext == "EGL_EXT_swap_buffers_with_damage") + { + return DamageSupport::EXT; + } + } + + DamageSupport::No + } + /// Exports an [`EGLImage`] as a [`Dmabuf`] #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn create_dmabuf_from_image( @@ -1110,3 +1136,24 @@ pub struct PixelFormat { /// is srgb enabled pub srgb: bool, } + +/// Denotes if damage tracking is supported. +/// +/// Additionally notes which variant of the `EGL_*_swap_buffers_with_damage` extension was found. +/// Prefers `KHR` over `EXT`, if both are available. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum DamageSupport { + /// `EGL_KHR_swap_buffers_with_damage` + KHR, + /// `EGL_EXT_swap_buffers_with_damage` + EXT, + /// Some required extensions are missing + No, +} + +impl DamageSupport { + /// Returns true, if any valid combination of required extensions was found. + pub fn supported(&self) -> bool { + self != &DamageSupport::No + } +} diff --git a/src/backend/egl/native.rs b/src/backend/egl/native.rs index d575476cb0..d7b0d8fc47 100644 --- a/src/backend/egl/native.rs +++ b/src/backend/egl/native.rs @@ -1,6 +1,9 @@ //! Type safe native types for safe context/surface creation -use super::{display::EGLDisplayHandle, ffi, wrap_egl_call, EGLDevice, SwapBuffersError}; +use super::{ + display::{DamageSupport, EGLDisplayHandle}, + ffi, wrap_egl_call, EGLDevice, SwapBuffersError, +}; use crate::utils::{Physical, Rectangle}; #[cfg(feature = "backend_winit")] use std::os::raw::c_int; @@ -248,15 +251,25 @@ pub unsafe trait EGLNativeSurface: Send { display: &Arc, surface: ffi::egl::types::EGLSurface, damage: Option<&mut [Rectangle]>, + damage_impl: DamageSupport, ) -> Result<(), SwapBuffersError> { wrap_egl_call(|| unsafe { if let Some(damage) = damage { - ffi::egl::SwapBuffersWithDamageEXT( - ***display, - surface as *const _, - damage.as_mut_ptr() as *mut _, - damage.len() as i32, - ); + match damage_impl { + DamageSupport::KHR => ffi::egl::SwapBuffersWithDamageKHR( + ***display, + surface as *const _, + damage.as_mut_ptr() as *mut _, + damage.len() as i32, + ), + DamageSupport::EXT => ffi::egl::SwapBuffersWithDamageEXT( + ***display, + surface as *const _, + damage.as_mut_ptr() as *mut _, + damage.len() as i32, + ), + DamageSupport::No => ffi::egl::SwapBuffers(***display, surface as *const _), + }; } else { ffi::egl::SwapBuffers(***display, surface as *const _); } diff --git a/src/backend/egl/surface.rs b/src/backend/egl/surface.rs index f139fff180..fb0f8b8150 100644 --- a/src/backend/egl/surface.rs +++ b/src/backend/egl/surface.rs @@ -7,7 +7,7 @@ use std::sync::{ }; use crate::backend::egl::{ - display::{EGLDisplay, EGLDisplayHandle, PixelFormat}, + display::{DamageSupport, EGLDisplay, EGLDisplayHandle, PixelFormat}, ffi, native::EGLNativeSurface, EGLError, SwapBuffersError, @@ -23,6 +23,7 @@ pub struct EGLSurface { pub(crate) surface: AtomicPtr, config_id: ffi::egl::types::EGLConfig, pixel_format: PixelFormat, + damage_impl: DamageSupport, logger: ::slog::Logger, } @@ -76,6 +77,7 @@ impl EGLSurface { surface: AtomicPtr::new(surface as *mut _), config_id: config, pixel_format, + damage_impl: display.supports_damage_impl(), logger: log, }) } @@ -147,7 +149,8 @@ impl EGLSurface { let surface = self.surface.load(Ordering::SeqCst); let result = if !surface.is_null() { - self.native.swap_buffers(&self.display, surface, damage) + self.native + .swap_buffers(&self.display, surface, damage, self.damage_impl) } else { Err(SwapBuffersError::EGLSwapBuffers(EGLError::BadSurface)) }; diff --git a/src/backend/winit/mod.rs b/src/backend/winit/mod.rs index c0b2088ae1..b79b0d3240 100644 --- a/src/backend/winit/mod.rs +++ b/src/backend/winit/mod.rs @@ -229,10 +229,7 @@ where let egl = Rc::new(surface); let renderer = unsafe { Gles2Renderer::new(context, log.clone())? }; let resize_notification = Rc::new(Cell::new(None)); - let damage_tracking = display.extensions().iter().any(|ext| ext == "EGL_EXT_buffer_age") - && display.extensions().iter().any(|ext| { - ext == "EGL_KHR_swap_buffers_with_damage" || ext == "EGL_EXT_swap_buffers_with_damage" - }); + let damage_tracking = display.supports_damage(); Ok(( WinitGraphicsBackend {