mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 02:48:12 +08:00
Restructure window state management and fix Vello canvas not resizing with viewport (#1900)
* Restructure window state management * Disable window creation on ci * Code review --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
@@ -66,7 +66,7 @@ impl Size for web_sys::HtmlCanvasElement {
|
||||
impl<S: Size> From<SurfaceHandleFrame<S>> for SurfaceFrame {
|
||||
fn from(x: SurfaceHandleFrame<S>) -> Self {
|
||||
Self {
|
||||
surface_id: x.surface_handle.surface_id,
|
||||
surface_id: x.surface_handle.window_id,
|
||||
transform: x.transform,
|
||||
resolution: x.surface_handle.surface.size(),
|
||||
}
|
||||
@@ -75,9 +75,10 @@ impl<S: Size> From<SurfaceHandleFrame<S>> for SurfaceFrame {
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct SurfaceHandle<Surface> {
|
||||
pub surface_id: SurfaceId,
|
||||
pub window_id: SurfaceId,
|
||||
pub surface: Surface,
|
||||
}
|
||||
|
||||
// #[cfg(target_arch = "wasm32")]
|
||||
// unsafe impl<T: dyn_any::WasmNotSend> Send for SurfaceHandle<T> {}
|
||||
// #[cfg(target_arch = "wasm32")]
|
||||
@@ -131,8 +132,9 @@ pub type ResourceFuture = Pin<Box<dyn Future<Output = Result<Arc<[u8]>, Applicat
|
||||
pub trait ApplicationIo {
|
||||
type Surface;
|
||||
type Executor;
|
||||
fn create_surface(&self) -> SurfaceHandle<Self::Surface>;
|
||||
fn destroy_surface(&self, surface_id: SurfaceId);
|
||||
fn window(&self) -> Option<SurfaceHandle<Self::Surface>>;
|
||||
fn create_window(&self) -> SurfaceHandle<Self::Surface>;
|
||||
fn destroy_window(&self, surface_id: SurfaceId);
|
||||
fn gpu_executor(&self) -> Option<&Self::Executor> {
|
||||
None
|
||||
}
|
||||
@@ -143,12 +145,16 @@ impl<T: ApplicationIo> ApplicationIo for &T {
|
||||
type Surface = T::Surface;
|
||||
type Executor = T::Executor;
|
||||
|
||||
fn create_surface(&self) -> SurfaceHandle<T::Surface> {
|
||||
(**self).create_surface()
|
||||
fn window(&self) -> Option<SurfaceHandle<Self::Surface>> {
|
||||
(**self).window()
|
||||
}
|
||||
|
||||
fn destroy_surface(&self, surface_id: SurfaceId) {
|
||||
(**self).destroy_surface(surface_id)
|
||||
fn create_window(&self) -> SurfaceHandle<T::Surface> {
|
||||
(**self).create_window()
|
||||
}
|
||||
|
||||
fn destroy_window(&self, surface_id: SurfaceId) {
|
||||
(**self).destroy_window(surface_id)
|
||||
}
|
||||
|
||||
fn gpu_executor(&self) -> Option<&T::Executor> {
|
||||
|
||||
@@ -222,7 +222,7 @@ impl From<SurfaceFrame> for GraphicElement {
|
||||
}
|
||||
impl From<alloc::sync::Arc<SurfaceHandleFrame<HtmlCanvasElement>>> for GraphicElement {
|
||||
fn from(surface: alloc::sync::Arc<SurfaceHandleFrame<HtmlCanvasElement>>) -> Self {
|
||||
let surface_id = surface.surface_handle.surface_id;
|
||||
let surface_id = surface.surface_handle.window_id;
|
||||
let transform = surface.transform;
|
||||
GraphicElement::Surface(SurfaceFrame {
|
||||
surface_id,
|
||||
@@ -236,7 +236,7 @@ impl From<alloc::sync::Arc<SurfaceHandleFrame<HtmlCanvasElement>>> for GraphicEl
|
||||
}
|
||||
impl From<SurfaceHandleFrame<HtmlCanvasElement>> for GraphicElement {
|
||||
fn from(surface: SurfaceHandleFrame<HtmlCanvasElement>) -> Self {
|
||||
let surface_id = surface.surface_handle.surface_id;
|
||||
let surface_id = surface.surface_handle.window_id;
|
||||
let transform = surface.transform;
|
||||
GraphicElement::Surface(SurfaceFrame {
|
||||
surface_id,
|
||||
|
||||
@@ -1,36 +1,40 @@
|
||||
use crate::{Node, WasmNotSend};
|
||||
use core::future::Future;
|
||||
use core::ops::Deref;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use dyn_any::DynFuture;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use alloc::sync::Arc;
|
||||
use dyn_any::DynFuture;
|
||||
use core::future::Future;
|
||||
use core::ops::Deref;
|
||||
use std::hash::DefaultHasher;
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// Caches the output of a given Node and acts as a proxy
|
||||
#[derive(Default)]
|
||||
pub struct MemoNode<T, CachedNode> {
|
||||
cache: Arc<Mutex<Option<T>>>,
|
||||
cache: Arc<Mutex<Option<(u64, T)>>>,
|
||||
node: CachedNode,
|
||||
}
|
||||
impl<'i, 'o: 'i, T: 'i + Clone + 'o + WasmNotSend, CachedNode: 'i> Node<'i, ()> for MemoNode<T, CachedNode>
|
||||
impl<'i, 'o: 'i, I: Hash + 'i, T: 'i + Clone + 'o + WasmNotSend, CachedNode: 'i> Node<'i, I> for MemoNode<T, CachedNode>
|
||||
where
|
||||
CachedNode: for<'any_input> Node<'any_input, ()>,
|
||||
for<'a> <CachedNode as Node<'a, ()>>::Output: core::future::Future<Output = T> + WasmNotSend,
|
||||
CachedNode: for<'any_input> Node<'any_input, I>,
|
||||
for<'a> <CachedNode as Node<'a, I>>::Output: core::future::Future<Output = T> + WasmNotSend,
|
||||
{
|
||||
// TODO: This should return a reference to the cached cached_value
|
||||
// but that requires a lot of lifetime magic <- This was suggested by copilot but is pretty accurate xD
|
||||
type Output = DynFuture<'i, T>;
|
||||
fn eval(&'i self, input: ()) -> Self::Output {
|
||||
if let Some(cached_value) = self.cache.lock().as_ref().unwrap().deref() {
|
||||
let data = cached_value.clone();
|
||||
fn eval(&'i self, input: I) -> Self::Output {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
input.hash(&mut hasher);
|
||||
let hash = hasher.finish();
|
||||
if let Some(data) = self.cache.lock().as_ref().unwrap().as_ref().and_then(|data| (data.0 == hash).then_some(data.1.clone())) {
|
||||
Box::pin(async move { data })
|
||||
} else {
|
||||
let fut = self.node.eval(input);
|
||||
let cache = self.cache.clone();
|
||||
Box::pin(async move {
|
||||
let value = fut.await;
|
||||
*cache.lock().unwrap() = Some(value.clone());
|
||||
*cache.lock().unwrap() = Some((hash, value.clone()));
|
||||
value
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user