winit: Support damage-tracking
This commit is contained in:
parent
f423244864
commit
7ae79fcba5
|
@ -27,11 +27,11 @@ use crate::{
|
||||||
},
|
},
|
||||||
input::InputEvent,
|
input::InputEvent,
|
||||||
renderer::{
|
renderer::{
|
||||||
gles2::{Gles2Error, Gles2Frame, Gles2Renderer},
|
gles2::{Gles2Error, Gles2Renderer},
|
||||||
Bind, Renderer, Transform, Unbind,
|
Bind,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
utils::{Logical, Physical, Size},
|
utils::{Logical, Physical, Rectangle, Size},
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, rc::Rc, time::Instant};
|
use std::{cell::RefCell, rc::Rc, time::Instant};
|
||||||
use wayland_egl as wegl;
|
use wayland_egl as wegl;
|
||||||
|
@ -90,6 +90,7 @@ pub struct WinitGraphicsBackend {
|
||||||
egl: Rc<EGLSurface>,
|
egl: Rc<EGLSurface>,
|
||||||
window: Rc<WinitWindow>,
|
window: Rc<WinitWindow>,
|
||||||
size: Rc<RefCell<WindowSize>>,
|
size: Rc<RefCell<WindowSize>>,
|
||||||
|
damage_tracking: bool,
|
||||||
resize_notification: Rc<Cell<Option<Size<i32, Physical>>>>,
|
resize_notification: Rc<Cell<Option<Size<i32, Physical>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,6 +221,10 @@ where
|
||||||
let egl = Rc::new(surface);
|
let egl = Rc::new(surface);
|
||||||
let renderer = unsafe { Gles2Renderer::new(context, log.clone())? };
|
let renderer = unsafe { Gles2Renderer::new(context, log.clone())? };
|
||||||
let resize_notification = Rc::new(Cell::new(None));
|
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((
|
Ok((
|
||||||
WinitGraphicsBackend {
|
WinitGraphicsBackend {
|
||||||
|
@ -227,6 +232,7 @@ where
|
||||||
_display: display,
|
_display: display,
|
||||||
egl,
|
egl,
|
||||||
renderer,
|
renderer,
|
||||||
|
damage_tracking,
|
||||||
size: size.clone(),
|
size: size.clone(),
|
||||||
resize_notification: resize_notification.clone(),
|
resize_notification: resize_notification.clone(),
|
||||||
},
|
},
|
||||||
|
@ -281,28 +287,56 @@ impl WinitGraphicsBackend {
|
||||||
&mut self.renderer
|
&mut self.renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shortcut to `Renderer::render` with the current window dimensions
|
/// Bind the underlying window to the underlying renderer
|
||||||
/// and this window set as the rendering target.
|
pub fn bind(&mut self) -> Result<(), crate::backend::SwapBuffersError> {
|
||||||
pub fn render<F, R>(&mut self, rendering: F) -> Result<R, crate::backend::SwapBuffersError>
|
|
||||||
where
|
|
||||||
F: FnOnce(&mut Gles2Renderer, &mut Gles2Frame) -> R,
|
|
||||||
{
|
|
||||||
// Were we told to resize?
|
// Were we told to resize?
|
||||||
if let Some(size) = self.resize_notification.take() {
|
if let Some(size) = self.resize_notification.take() {
|
||||||
self.egl.resize(size.w, size.h, 0, 0);
|
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())?;
|
self.renderer.bind(self.egl.clone())?;
|
||||||
// Why is winit falling out of place with the coordinate system?
|
Ok(())
|
||||||
let result = self.renderer.render(size, Transform::Flipped180, rendering)?;
|
}
|
||||||
self.egl.swap_buffers()?;
|
|
||||||
self.renderer.unbind()?;
|
/// Retrieve the buffer age of the current backbuffer of the window
|
||||||
Ok(result)
|
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