winit: Support damage-tracking
This commit is contained in:
parent
f423244864
commit
7ae79fcba5
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue