Skip to content

Commit bbaa8e1

Browse files
Fix tests
1 parent 23dc6e9 commit bbaa8e1

File tree

3 files changed

+219
-211
lines changed

3 files changed

+219
-211
lines changed

node-graph/interpreted-executor/src/node_registry.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use graphene_std::application_io::ImageTexture;
99
use graphene_std::brush::brush_cache::BrushCache;
1010
use graphene_std::brush::brush_stroke::BrushStroke;
1111
use graphene_std::gradient::GradientStops;
12-
#[cfg(feature = "wasm")]
12+
#[cfg(target_family = "wasm")]
1313
use graphene_std::platform_application_io::canvas_utils::CanvasHandle;
1414
#[cfg(feature = "gpu")]
1515
use graphene_std::raster::GPU;
@@ -137,7 +137,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
137137
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => &PlatformEditorApi, Context => graphene_std::ContextFeatures]),
138138
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => RenderIntermediate, Context => graphene_std::ContextFeatures]),
139139
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => RenderOutput, Context => graphene_std::ContextFeatures]),
140-
#[cfg(feature = "wasm")]
140+
#[cfg(target_family = "wasm")]
141141
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => CanvasHandle, Context => graphene_std::ContextFeatures]),
142142
// ==========
143143
// MEMO NODES
@@ -156,7 +156,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
156156
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<f64>]),
157157
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<f32>]),
158158
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => Vec<String>]),
159-
#[cfg(feature = "wasm")]
159+
#[cfg(target_family = "wasm")]
160160
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => CanvasHandle]),
161161
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => f64]),
162162
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => f32]),
Lines changed: 8 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -1,208 +1,8 @@
1-
use dyn_any::DynAny;
2-
#[cfg(feature = "wgpu")]
3-
use graphene_application_io::ImageTexture;
4-
use std::sync::Arc;
5-
use std::sync::atomic::{AtomicU64, Ordering};
6-
use web_sys::js_sys::{Object, Reflect};
7-
use web_sys::wasm_bindgen::{JsCast, JsValue};
8-
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, window};
9-
#[cfg(feature = "wgpu")]
10-
use wgpu_executor::WgpuExecutor;
11-
12-
const CANVASES_OBJECT_KEY: &str = "imageCanvases";
13-
14-
pub type CanvasId = u64;
15-
16-
static CANVAS_IDS: AtomicU64 = AtomicU64::new(0);
17-
18-
pub trait Canvas {
19-
fn id(&mut self) -> CanvasId;
20-
fn context(&mut self) -> CanvasRenderingContext2d;
21-
fn set_resolution(&mut self, resolution: glam::UVec2);
22-
}
23-
24-
#[cfg(feature = "wgpu")]
25-
pub trait CanvasSurface: Canvas {
26-
fn present(&mut self, image_texture: &ImageTexture, executor: &WgpuExecutor);
27-
}
28-
29-
#[derive(Clone, DynAny)]
30-
pub struct CanvasHandle(Option<Arc<CanvasImpl>>);
31-
impl CanvasHandle {
32-
pub fn new() -> Self {
33-
Self(None)
34-
}
35-
fn get(&mut self) -> &CanvasImpl {
36-
if self.0.is_none() {
37-
self.0 = Some(Arc::new(CanvasImpl::new()));
38-
}
39-
self.0.as_ref().unwrap()
40-
}
41-
}
42-
impl Canvas for CanvasHandle {
43-
fn id(&mut self) -> CanvasId {
44-
self.get().canvas_id
45-
}
46-
fn context(&mut self) -> CanvasRenderingContext2d {
47-
self.get().context()
48-
}
49-
fn set_resolution(&mut self, resolution: glam::UVec2) {
50-
self.get().set_resolution(resolution);
51-
}
52-
}
53-
54-
#[cfg(feature = "wgpu")]
55-
pub struct CanvasSurfaceHandle(CanvasHandle, Option<Arc<wgpu::Surface<'static>>>);
56-
#[cfg(feature = "wgpu")]
57-
impl CanvasSurfaceHandle {
58-
pub fn new() -> Self {
59-
Self(CanvasHandle::new(), None)
60-
}
61-
fn surface(&mut self, executor: &WgpuExecutor) -> &wgpu::Surface<'_> {
62-
if self.1.is_none() {
63-
let canvas = self.0.get().canvas.clone();
64-
let surface = executor
65-
.context
66-
.instance
67-
.create_surface(wgpu::SurfaceTarget::Canvas(canvas))
68-
.expect("Failed to create surface from canvas");
69-
self.1 = Some(Arc::new(surface));
70-
}
71-
self.1.as_ref().unwrap()
72-
}
73-
}
74-
#[cfg(feature = "wgpu")]
75-
impl Canvas for CanvasSurfaceHandle {
76-
fn id(&mut self) -> CanvasId {
77-
self.0.id()
78-
}
79-
fn context(&mut self) -> CanvasRenderingContext2d {
80-
self.0.context()
81-
}
82-
fn set_resolution(&mut self, resolution: glam::UVec2) {
83-
self.0.set_resolution(resolution);
84-
}
85-
}
86-
#[cfg(feature = "wgpu")]
87-
impl CanvasSurface for CanvasSurfaceHandle {
88-
fn present(&mut self, image_texture: &ImageTexture, executor: &WgpuExecutor) {
89-
let source_texture: &wgpu::Texture = image_texture.as_ref();
90-
91-
let surface = self.surface(executor);
92-
93-
// Blit the texture to the surface
94-
let mut encoder = executor.context.device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
95-
label: Some("Texture to Surface Blit"),
96-
});
97-
98-
let size = source_texture.size();
99-
100-
// Configure the surface at physical resolution (for HiDPI displays)
101-
let surface_caps = surface.get_capabilities(&executor.context.adapter);
102-
surface.configure(
103-
&executor.context.device,
104-
&wgpu::SurfaceConfiguration {
105-
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST,
106-
format: wgpu::TextureFormat::Rgba8Unorm,
107-
width: size.width,
108-
height: size.height,
109-
present_mode: surface_caps.present_modes[0],
110-
alpha_mode: wgpu::CompositeAlphaMode::PreMultiplied,
111-
view_formats: vec![],
112-
desired_maximum_frame_latency: 2,
113-
},
114-
);
115-
116-
let surface_texture = surface.get_current_texture().expect("Failed to get surface texture");
117-
118-
encoder.copy_texture_to_texture(
119-
wgpu::TexelCopyTextureInfoBase {
120-
texture: source_texture,
121-
mip_level: 0,
122-
origin: Default::default(),
123-
aspect: Default::default(),
124-
},
125-
wgpu::TexelCopyTextureInfoBase {
126-
texture: &surface_texture.texture,
127-
mip_level: 0,
128-
origin: Default::default(),
129-
aspect: Default::default(),
130-
},
131-
source_texture.size(),
132-
);
133-
134-
executor.context.queue.submit([encoder.finish()]);
135-
surface_texture.present();
136-
}
137-
}
138-
139-
/// A wgpu surface backed by an HTML canvas element.
140-
/// Holds a reference to the canvas to prevent garbage collection.
141-
pub struct CanvasImpl {
142-
canvas_id: u64,
143-
canvas: HtmlCanvasElement,
144-
}
145-
146-
impl CanvasImpl {
147-
fn new() -> Self {
148-
let document = window().expect("should have a window in this context").document().expect("window should have a document");
149-
150-
let canvas: HtmlCanvasElement = document.create_element("canvas").unwrap().dyn_into::<HtmlCanvasElement>().unwrap();
151-
let canvas_id = CANVAS_IDS.fetch_add(1, Ordering::SeqCst);
152-
153-
// Store the canvas in the global scope so it doesn't get garbage collected
154-
let window = window().expect("should have a window in this context");
155-
let window_obj = Object::from(window);
156-
157-
let image_canvases_key = JsValue::from_str(CANVASES_OBJECT_KEY);
158-
159-
let mut canvases = Reflect::get(&window_obj, &image_canvases_key);
160-
if canvases.is_err() {
161-
Reflect::set(&JsValue::from(web_sys::window().unwrap()), &image_canvases_key, &Object::new()).unwrap();
162-
canvases = Reflect::get(&window_obj, &image_canvases_key);
163-
}
164-
165-
// Convert key and value to JsValue
166-
let js_key = JsValue::from_str(canvas_id.to_string().as_str());
167-
let js_value = JsValue::from(canvas.clone());
168-
169-
let canvases = Object::from(canvases.unwrap());
170-
171-
// Use Reflect API to set property
172-
Reflect::set(&canvases, &js_key, &js_value).unwrap();
173-
174-
Self { canvas_id, canvas }
175-
}
176-
fn context(&self) -> CanvasRenderingContext2d {
177-
self.canvas
178-
.get_context("2d")
179-
.expect("Failed to get 2D context from canvas")
180-
.unwrap()
181-
.dyn_into::<CanvasRenderingContext2d>()
182-
.expect("Failed to cast context to CanvasRenderingContext2d")
183-
}
184-
fn set_resolution(&self, resolution: glam::UVec2) {
185-
self.canvas.set_width(resolution.x);
186-
self.canvas.set_height(resolution.y);
187-
}
188-
}
189-
190-
impl Drop for CanvasImpl {
191-
fn drop(&mut self) {
192-
let canvas_id = self.canvas_id;
193-
let window = window().expect("should have a window in this context");
194-
let window_obj = Object::from(window);
195-
196-
let image_canvases_key = JsValue::from_str(CANVASES_OBJECT_KEY);
197-
198-
if let Ok(canvases) = Reflect::get(&window_obj, &image_canvases_key) {
199-
let canvases = Object::from(canvases);
200-
let js_key = JsValue::from_str(canvas_id.to_string().as_str());
201-
Reflect::delete_property(&canvases, &js_key).unwrap();
202-
}
203-
}
204-
}
205-
206-
// SAFETY: WASM is single-threaded, so Send/Sync are safe
207-
unsafe impl Send for CanvasImpl {}
208-
unsafe impl Sync for CanvasImpl {}
1+
///! A collection of utilities for working with the HTML canvases.
2+
///! This library is designed to be used in a WebAssembly context.
3+
///! It doesn't expose any functionality when compiled for non-WebAssembly targets
4+
5+
#[cfg(target_family = "wasm")]
6+
mod wasm;
7+
#[cfg(target_family = "wasm")]
8+
pub use wasm::*;

0 commit comments

Comments
 (0)