mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +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
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ default = ["dealloc_nodes"]
|
||||
serde = ["dep:serde", "graphene-core/serde", "glam/serde", "bezier-rs/serde"]
|
||||
dealloc_nodes = []
|
||||
wgpu = []
|
||||
ci = []
|
||||
tokio = ["dep:tokio"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -22,14 +22,49 @@ use web_sys::window;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use web_sys::HtmlCanvasElement;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct WindowWrapper {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
window: SurfaceHandle<HtmlCanvasElement>,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
window: SurfaceHandle<Arc<winit::window::Window>>,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
impl Drop for WindowWrapper {
|
||||
fn drop(&mut self) {
|
||||
let window = window().expect("should have a window in this context");
|
||||
let window = Object::from(window);
|
||||
|
||||
let image_canvases_key = JsValue::from_str("imageCanvases");
|
||||
|
||||
let wrapper = || {
|
||||
if let Ok(canvases) = Reflect::get(&window, &image_canvases_key) {
|
||||
// Convert key and value to JsValue
|
||||
let js_key = JsValue::from_str(format!("canvas{}", self.window.window_id).as_str());
|
||||
|
||||
// Use Reflect API to set property
|
||||
Reflect::delete_property(&canvases.into(), &js_key)?;
|
||||
}
|
||||
Ok::<_, JsValue>(())
|
||||
};
|
||||
|
||||
wrapper().expect("should be able to set canvas in global scope")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
unsafe impl Sync for WindowWrapper {}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
unsafe impl Send for WindowWrapper {}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct WasmApplicationIo {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
ids: AtomicU64,
|
||||
#[cfg(feature = "wgpu")]
|
||||
pub(crate) gpu_executor: Option<WgpuExecutor>,
|
||||
// #[cfg(not(target_arch = "wasm32"))]
|
||||
// windows: Mutex<Vec<Arc<winit::window::Window>>>,
|
||||
windows: Vec<WindowWrapper>,
|
||||
pub resources: HashMap<String, Arc<[u8]>>,
|
||||
}
|
||||
|
||||
@@ -68,10 +103,14 @@ impl WasmApplicationIo {
|
||||
ids: AtomicU64::new(0),
|
||||
#[cfg(feature = "wgpu")]
|
||||
gpu_executor: executor,
|
||||
// #[cfg(not(target_arch = "wasm32"))]
|
||||
// windows: Vec::new().into(),
|
||||
windows: Vec::new().into(),
|
||||
resources: HashMap::new(),
|
||||
};
|
||||
#[cfg(not(feature = "ci"))]
|
||||
let window = io.create_window();
|
||||
#[cfg(not(feature = "ci"))]
|
||||
io.windows.push(WindowWrapper { window });
|
||||
|
||||
io.resources.insert("null".to_string(), Arc::from(include_bytes!("null.png").to_vec()));
|
||||
io
|
||||
}
|
||||
@@ -99,14 +138,14 @@ impl ApplicationIo for WasmApplicationIo {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
type Surface = HtmlCanvasElement;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
type Surface = winit::window::Window;
|
||||
type Surface = Arc<winit::window::Window>;
|
||||
#[cfg(feature = "wgpu")]
|
||||
type Executor = WgpuExecutor;
|
||||
#[cfg(not(feature = "wgpu"))]
|
||||
type Executor = ();
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn create_surface(&self) -> SurfaceHandle<Self::Surface> {
|
||||
fn create_window(&self) -> SurfaceHandle<Self::Surface> {
|
||||
let wrapper = || {
|
||||
let document = window().expect("should have a window in this context").document().expect("window should have a document");
|
||||
|
||||
@@ -133,7 +172,7 @@ impl ApplicationIo for WasmApplicationIo {
|
||||
// Use Reflect API to set property
|
||||
Reflect::set(&canvases, &js_key, &js_value)?;
|
||||
Ok::<_, JsValue>(SurfaceHandle {
|
||||
surface_id: graphene_core::SurfaceId(id),
|
||||
window_id: graphene_core::SurfaceId(id),
|
||||
surface: canvas,
|
||||
})
|
||||
};
|
||||
@@ -141,7 +180,7 @@ impl ApplicationIo for WasmApplicationIo {
|
||||
wrapper().expect("should be able to set canvas in global scope")
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn create_surface(&self) -> SurfaceHandle<Self::Surface> {
|
||||
fn create_window(&self) -> SurfaceHandle<Self::Surface> {
|
||||
#[cfg(feature = "wayland")]
|
||||
use winit::platform::wayland::EventLoopBuilderExtWayland;
|
||||
|
||||
@@ -156,13 +195,13 @@ impl ApplicationIo for WasmApplicationIo {
|
||||
.unwrap();
|
||||
// self.windows.lock().as_mut().unwrap().push(window.clone());
|
||||
SurfaceHandle {
|
||||
surface_id: SurfaceId(window.id().into()),
|
||||
surface: window,
|
||||
window_id: SurfaceId(window.id().into()),
|
||||
surface: Arc::new(window),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn destroy_surface(&self, surface_id: SurfaceId) {
|
||||
fn destroy_window(&self, surface_id: SurfaceId) {
|
||||
let window = window().expect("should have a window in this context");
|
||||
let window = Object::from(window);
|
||||
|
||||
@@ -183,7 +222,7 @@ impl ApplicationIo for WasmApplicationIo {
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn destroy_surface(&self, _surface_id: SurfaceId) {}
|
||||
fn destroy_window(&self, _surface_id: SurfaceId) {}
|
||||
|
||||
#[cfg(feature = "wgpu")]
|
||||
fn gpu_executor(&self) -> Option<&Self::Executor> {
|
||||
@@ -226,6 +265,10 @@ impl ApplicationIo for WasmApplicationIo {
|
||||
_ => Err(ApplicationError::NotFound),
|
||||
}
|
||||
}
|
||||
|
||||
fn window(&self) -> Option<SurfaceHandle<Self::Surface>> {
|
||||
self.windows.iter().next().map(|wrapper| wrapper.window.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub type WasmSurfaceHandle = SurfaceHandle<wgpu_executor::Window>;
|
||||
|
||||
@@ -28,7 +28,7 @@ pub struct CreateSurfaceNode {}
|
||||
|
||||
#[node_macro::node_fn(CreateSurfaceNode)]
|
||||
async fn create_surface_node<'a: 'input>(editor: &'a WasmEditorApi) -> Arc<WasmSurfaceHandle> {
|
||||
Arc::new(editor.application_io.as_ref().unwrap().create_surface())
|
||||
Arc::new(editor.application_io.as_ref().unwrap().create_window())
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@@ -207,7 +207,7 @@ async fn render_node<'a: 'input, T: 'input + GraphicElementRendered + WasmNotSen
|
||||
render_config: RenderConfig,
|
||||
editor_api: &'a WasmEditorApi,
|
||||
data: impl Node<Footprint, Output = T>,
|
||||
_surface_handle: impl Node<Footprint, Output = Option<wgpu_executor::WgpuSurface>>,
|
||||
_surface_handle: impl Node<(), Output = Option<wgpu_executor::WgpuSurface>>,
|
||||
) -> RenderOutput {
|
||||
let footprint = render_config.viewport;
|
||||
|
||||
@@ -216,7 +216,7 @@ async fn render_node<'a: 'input, T: 'input + GraphicElementRendered + WasmNotSen
|
||||
|
||||
let data = self.data.eval(footprint).await;
|
||||
#[cfg(all(feature = "vello", target_arch = "wasm32"))]
|
||||
let surface_handle = self._surface_handle.eval(footprint).await;
|
||||
let surface_handle = self._surface_handle.eval(()).await;
|
||||
let use_vello = editor_api.editor_preferences.use_vello();
|
||||
#[cfg(all(feature = "vello", target_arch = "wasm32"))]
|
||||
let use_vello = use_vello && surface_handle.is_some();
|
||||
|
||||
@@ -382,7 +382,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||
#[cfg(feature = "gpu")]
|
||||
async_node!(wgpu_executor::ReadOutputBufferNode<_, _>, input: Arc<WgpuShaderInput>, output: Vec<u8>, params: [&WgpuExecutor, ()]),
|
||||
#[cfg(feature = "gpu")]
|
||||
async_node!(wgpu_executor::CreateGpuSurfaceNode<_>, input: Footprint, output: Option<wgpu_executor::WgpuSurface>, params: [&WasmEditorApi]),
|
||||
async_node!(wgpu_executor::CreateGpuSurfaceNode, input: &WasmEditorApi, output: Option<wgpu_executor::WgpuSurface>, params: []),
|
||||
#[cfg(feature = "gpu")]
|
||||
async_node!(wgpu_executor::RenderTextureNode<_, _, _>, input: Footprint, output: graphene_std::SurfaceFrame, fn_params: [Footprint => ShaderInputFrame, () => Option<wgpu_executor::WgpuSurface>, () =>&WgpuExecutor]),
|
||||
#[cfg(feature = "gpu")]
|
||||
@@ -617,6 +617,21 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: (), output: wgpu_executor::WindowHandle, params: [wgpu_executor::WindowHandle]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: (), output: graphene_std::SurfaceFrame, params: [graphene_std::SurfaceFrame]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: (), output: RenderOutput, params: [RenderOutput]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: Image<Color>, fn_params: [Footprint => Image<Color>]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: ImageFrame<Color>, fn_params: [Footprint => ImageFrame<Color>]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: QuantizationChannels, fn_params: [Footprint => QuantizationChannels]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: Vec<DVec2>, fn_params: [Footprint => Vec<DVec2>]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: Arc<WasmSurfaceHandle>, fn_params: [Footprint => Arc<WasmSurfaceHandle>]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: WindowHandle, fn_params: [Footprint => WindowHandle]),
|
||||
#[cfg(feature = "gpu")]
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: ShaderInputFrame, fn_params: [Footprint => ShaderInputFrame]),
|
||||
#[cfg(feature = "gpu")]
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: wgpu_executor::WgpuSurface, fn_params: [Footprint => wgpu_executor::WgpuSurface]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: Option<wgpu_executor::WgpuSurface>, fn_params: [Footprint => Option<wgpu_executor::WgpuSurface>]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: wgpu_executor::WindowHandle, fn_params: [Footprint => wgpu_executor::WindowHandle]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: graphene_std::SurfaceFrame, fn_params: [Footprint => graphene_std::SurfaceFrame]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: UVec2, output: graphene_std::SurfaceFrame, fn_params: [UVec2 => graphene_std::SurfaceFrame]),
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Footprint, output: RenderOutput, fn_params: [Footprint => RenderOutput]),
|
||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Footprint, output: GraphicElement, fn_params: [Footprint => GraphicElement]),
|
||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Footprint, output: GraphicGroup, fn_params: [Footprint => GraphicGroup]),
|
||||
async_node!(graphene_core::memo::ImpureMemoNode<_, _, _>, input: Footprint, output: VectorData, fn_params: [Footprint => VectorData]),
|
||||
@@ -632,17 +647,17 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||
register_node!(graphene_core::quantization::QuantizeNode<_>, input: Color, params: [QuantizationChannels]),
|
||||
register_node!(graphene_core::quantization::DeQuantizeNode<_>, input: PackedPixel, params: [QuantizationChannels]),
|
||||
register_node!(graphene_core::ops::CloneNode<_>, input: &QuantizationChannels, params: []),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => ImageFrame<Color>, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => VectorData, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => GraphicGroup, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => Artboard, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => ArtboardGroup, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => Option<Color>, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => Vec<Color>, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => bool, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => f32, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => f64, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => String, Footprint => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => ImageFrame<Color>, () => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => VectorData, () => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => GraphicGroup, () => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => Artboard, () => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => ArtboardGroup, () => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => Option<Color>, () => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => Vec<Color>, () => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => bool, () => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => f32, () => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => f64, () => Option<WgpuSurface>]),
|
||||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: RenderConfig, output: RenderOutput, fn_params: [() => &WasmEditorApi, Footprint => String, () => Option<WgpuSurface>]),
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
async_node!(graphene_std::wasm_application_io::RasterizeNode<_, _>, input: VectorData, output: ImageFrame<Color>, params: [Footprint, Arc<WasmSurfaceHandle>]),
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
|
||||
@@ -123,7 +123,7 @@ pub struct Surface {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub type Window = HtmlCanvasElement;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub type Window = winit::window::Window;
|
||||
pub type Window = Arc<winit::window::Window>;
|
||||
|
||||
unsafe impl StaticType for Surface {
|
||||
type Static = Surface;
|
||||
@@ -509,22 +509,8 @@ impl WgpuExecutor {
|
||||
let surface = self.context.instance.create_surface(wgpu::SurfaceTarget::Canvas(canvas.surface))?;
|
||||
let resolution = resolution.unwrap_or(UVec2::new(1920, 1080));
|
||||
|
||||
// let surface_caps = surface.get_capabilities(&self.context.adapter);
|
||||
// let surface_format = wgpu::TextureFormat::Rgba16Float;
|
||||
// let config = wgpu::SurfaceConfiguration {
|
||||
// usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
// format: surface_format,
|
||||
// width: 1920,
|
||||
// height: 1080,
|
||||
// present_mode: surface_caps.present_modes[0],
|
||||
// alpha_mode: surface_caps.alpha_modes[0],
|
||||
// view_formats: vec![],
|
||||
// desired_maximum_frame_latency: 2,
|
||||
// };
|
||||
// surface.configure(&self.context.device, &config);
|
||||
// self.surface_config.set(Some(config));
|
||||
Ok(SurfaceHandle {
|
||||
surface_id: canvas.surface_id,
|
||||
window_id: canvas.window_id,
|
||||
surface: Surface { inner: surface, resolution },
|
||||
})
|
||||
}
|
||||
@@ -534,24 +520,8 @@ impl WgpuExecutor {
|
||||
let resolution = resolution.unwrap_or(UVec2 { x: size.width, y: size.height });
|
||||
let surface = self.context.instance.create_surface(wgpu::SurfaceTarget::Window(Box::new(window.surface)))?;
|
||||
|
||||
let surface_caps = surface.get_capabilities(&self.context.adapter);
|
||||
println!("{surface_caps:?}");
|
||||
let surface_format = wgpu::TextureFormat::Rgba16Float;
|
||||
let _config = wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
format: surface_format,
|
||||
width: resolution.x,
|
||||
height: resolution.y,
|
||||
present_mode: surface_caps.present_modes[0],
|
||||
alpha_mode: surface_caps.alpha_modes[0],
|
||||
view_formats: vec![],
|
||||
desired_maximum_frame_latency: 2,
|
||||
};
|
||||
// surface.configure(&self.context.device, &config);
|
||||
|
||||
let surface_id = window.surface_id;
|
||||
Ok(SurfaceHandle {
|
||||
surface_id,
|
||||
window_id: window.window_id,
|
||||
surface: Surface { inner: surface, resolution },
|
||||
})
|
||||
}
|
||||
@@ -929,17 +899,25 @@ async fn read_output_buffer_node<'a: 'input>(buffer: Arc<WgpuShaderInput>, execu
|
||||
executor.read_output_buffer(buffer).await.unwrap()
|
||||
}
|
||||
|
||||
pub struct CreateGpuSurfaceNode<EditorApi> {
|
||||
pub type WindowHandle = Arc<SurfaceHandle<Window>>;
|
||||
|
||||
pub struct CreateGpuSurfaceNode;
|
||||
|
||||
#[node_macro::node_fn(CreateGpuSurfaceNode)]
|
||||
async fn create_gpu_surface<'a: 'input, Io: ApplicationIo<Executor = WgpuExecutor, Surface = Window> + 'a + Send + Sync>(editor_api: &'a EditorApi<Io>) -> Option<WgpuSurface> {
|
||||
let canvas = editor_api.application_io.as_ref()?.window()?;
|
||||
let executor = editor_api.application_io.as_ref()?.gpu_executor()?;
|
||||
Some(Arc::new(executor.create_surface(canvas, None).ok()?))
|
||||
}
|
||||
pub struct ConfigureGpuSurfaceNode<EditorApi> {
|
||||
editor_api: EditorApi,
|
||||
}
|
||||
|
||||
pub type WindowHandle = Arc<SurfaceHandle<Window>>;
|
||||
|
||||
#[node_macro::node_fn(CreateGpuSurfaceNode)]
|
||||
async fn create_gpu_surface<'a: 'input, Io: ApplicationIo<Executor = WgpuExecutor, Surface = Window> + 'a + Send + Sync>(footprint: Footprint, editor_api: &'a EditorApi<Io>) -> Option<WgpuSurface> {
|
||||
let canvas = editor_api.application_io.as_ref()?.create_surface();
|
||||
#[node_macro::node_fn(ConfigureGpuSurfaceNode)]
|
||||
async fn create_gpu_surface<'a: 'input, Io: ApplicationIo<Executor = WgpuExecutor, Surface = Window> + 'a + Send + Sync>(resolution: UVec2, editor_api: &'a EditorApi<Io>) -> Option<WgpuSurface> {
|
||||
let canvas = editor_api.application_io.as_ref()?.create_window();
|
||||
let executor = editor_api.application_io.as_ref()?.gpu_executor()?;
|
||||
Some(Arc::new(executor.create_surface(canvas, Some(footprint.resolution)).ok()?))
|
||||
Some(Arc::new(executor.create_surface(canvas, Some(resolution)).ok()?))
|
||||
}
|
||||
|
||||
pub struct RenderTextureNode<Image, Surface, EditorApi> {
|
||||
@@ -957,7 +935,7 @@ pub struct ShaderInputFrame {
|
||||
#[node_macro::node_fn(RenderTextureNode)]
|
||||
async fn render_texture_node<'a: 'input>(footprint: Footprint, image: impl Node<Footprint, Output = ShaderInputFrame>, surface: Option<WgpuSurface>, executor: &'a WgpuExecutor) -> SurfaceFrame {
|
||||
let surface = surface.unwrap();
|
||||
let surface_id = surface.surface_id;
|
||||
let surface_id = surface.window_id;
|
||||
let image = self.image.eval(footprint).await;
|
||||
let transform = image.transform;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user