winit: Support damage-tracking

This commit is contained in:
Victor Brekenfeld 2021-12-29 15:55:44 +01:00
parent f423244864
commit 7ae79fcba5
1 changed files with 53 additions and 19 deletions

View File

@ -27,11 +27,11 @@ use crate::{
},
input::InputEvent,
renderer::{
gles2::{Gles2Error, Gles2Frame, Gles2Renderer},
Bind, Renderer, Transform, Unbind,
gles2::{Gles2Error, Gles2Renderer},
Bind,
},
},
utils::{Logical, Physical, Size},
utils::{Logical, Physical, Rectangle, Size},
};
use std::{cell::RefCell, rc::Rc, time::Instant};
use wayland_egl as wegl;
@ -90,6 +90,7 @@ pub struct WinitGraphicsBackend {
egl: Rc<EGLSurface>,
window: Rc<WinitWindow>,
size: Rc<RefCell<WindowSize>>,
damage_tracking: bool,
resize_notification: Rc<Cell<Option<Size<i32, Physical>>>>,
}
@ -220,6 +221,10 @@ 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"
});
Ok((
WinitGraphicsBackend {
@ -227,6 +232,7 @@ where
_display: display,
egl,
renderer,
damage_tracking,
size: size.clone(),
resize_notification: resize_notification.clone(),
},
@ -281,28 +287,56 @@ impl WinitGraphicsBackend {
&mut self.renderer
}
/// Shortcut to `Renderer::render` with the current window dimensions
/// and this window set as the rendering target.
pub fn render<F, R>(&mut self, rendering: F) -> Result<R, crate::backend::SwapBuffersError>
where
F: FnOnce(&mut Gles2Renderer, &mut Gles2Frame) -> R,
{
/// Bind the underlying window to the underlying renderer
pub fn bind(&mut self) -> Result<(), crate::backend::SwapBuffersError> {
// Were we told to resize?
if let Some(size) = self.resize_notification.take() {
self.egl.resize(size.w, size.h, 0, 0);
}
let size = {
let size = self.size.borrow();
size.physical_size
};
self.renderer.bind(self.egl.clone())?;
// Why is winit falling out of place with the coordinate system?
let result = self.renderer.render(size, Transform::Flipped180, rendering)?;
self.egl.swap_buffers()?;
self.renderer.unbind()?;
Ok(result)
Ok(())
}
/// Retrieve the buffer age of the current backbuffer of the window
pub fn buffer_age(&self) -> usize {
if self.damage_tracking {
self.egl.buffer_age() as usize
} else {
0
}
}
/// Submits the back buffer to the window by swapping, requires the window to be previously bound (see [`WinitGraphicsBackend::bind`]).
pub fn submit(
&mut self,
damage: Option<&[Rectangle<i32, Logical>]>,
scale: f64,
) -> Result<(), crate::backend::SwapBuffersError> {
let mut damage = if self.damage_tracking && damage.is_some() && !damage.unwrap().is_empty() {
let size = self
.size
.borrow()
.physical_size
.to_f64()
.to_logical(scale)
.to_i32_round::<i32>();
let damage = damage
.unwrap()
.iter()
.map(|rect| {
Rectangle::from_loc_and_size((rect.loc.x, size.h - rect.loc.y - rect.size.h), rect.size)
.to_f64()
.to_physical(scale)
.to_i32_round::<i32>()
})
.collect::<Vec<_>>();
Some(damage)
} else {
None
};
self.egl.swap_buffers(damage.as_mut().map(|x| &mut **x))?;
Ok(())
}
}