|
| 1 | +//! Signals that control when/if the editor redraws |
| 2 | +
|
| 3 | +use std::future::Future; |
| 4 | + |
| 5 | +use parking_lot::{RwLock, RwLockReadGuard}; |
| 6 | +use tokio::sync::Notify; |
| 7 | + |
| 8 | +/// A `Notify` instance that can be used to (asynchronously) request |
| 9 | +/// the editor the render a new frame. |
| 10 | +static REDRAW_NOTIFY: Notify = Notify::const_new(); |
| 11 | + |
| 12 | +/// A `RwLock` that prevents the next frame from being |
| 13 | +/// drawn until an exclusive (write) lock can be acquired. |
| 14 | +/// This allows asynchsonous tasks to acquire `non-exclusive` |
| 15 | +/// locks (read) to prevent the next frame from being drawn |
| 16 | +/// until a certain computation has finished. |
| 17 | +static RENDER_LOCK: RwLock<()> = RwLock::new(()); |
| 18 | + |
| 19 | +pub type RenderLockGuard = RwLockReadGuard<'static, ()>; |
| 20 | + |
| 21 | +/// Requests that the editor is redrawn. The redraws are debounced (currently to |
| 22 | +/// 30FPS) so this can be called many times without causing a ton of frames to |
| 23 | +/// be rendered. |
| 24 | +pub fn request_redraw() { |
| 25 | + REDRAW_NOTIFY.notify_one(); |
| 26 | +} |
| 27 | + |
| 28 | +/// Returns a future that will yield once a redraw has been asynchronously |
| 29 | +/// requested using [`request_redraw`]. |
| 30 | +pub fn redraw_requested() -> impl Future<Output = ()> { |
| 31 | + REDRAW_NOTIFY.notified() |
| 32 | +} |
| 33 | + |
| 34 | +/// Wait until all locks acquired with [`lock_frame`] have been released. |
| 35 | +/// This function is called before rendering and is intended to allow the frame |
| 36 | +/// to wait for async computations that should be included in the current frame. |
| 37 | +pub fn start_frame() { |
| 38 | + drop(RENDER_LOCK.write()); |
| 39 | + // exhaust any leftover redraw notifications |
| 40 | + let notify = REDRAW_NOTIFY.notified(); |
| 41 | + tokio::pin!(notify); |
| 42 | + notify.enable(); |
| 43 | +} |
| 44 | + |
| 45 | +/// Acquires the render lock which will prevent the next frame from being drawn |
| 46 | +/// until the returned guard is dropped. |
| 47 | +pub fn lock_frame() -> RenderLockGuard { |
| 48 | + RENDER_LOCK.read() |
| 49 | +} |
0 commit comments