diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index f8ad038f40..34305066ce 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -269,6 +269,7 @@ web-sys = { version = "0.3.53", features = [ "GpuVertexState", "GpuVertexStepMode", "HtmlCanvasElement", + "OffscreenCanvas", "Window", ]} js-sys = "0.3.50" diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index a4e957bd2f..15628de1e9 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -887,6 +887,30 @@ fn future_map_async(result: JsFutureResult) -> Result<(), crate::BufferAsyncErro result.map(|_| ()).map_err(|_| crate::BufferAsyncError) } +impl Context { + pub fn instance_create_surface_from_canvas( + &self, + canvas: &web_sys::HtmlCanvasElement, + ) -> ::SurfaceId { + let context: wasm_bindgen::JsValue = match canvas.get_context("webgpu") { + Ok(Some(ctx)) => ctx.into(), + _ => panic!("expected to get context from canvas"), + }; + Sendable(context.into()) + } + + pub fn instance_create_surface_from_offscreen_canvas( + &self, + canvas: &web_sys::OffscreenCanvas, + ) -> ::SurfaceId { + let context: wasm_bindgen::JsValue = match canvas.get_context("webgpu") { + Ok(Some(ctx)) => ctx.into(), + _ => panic!("expected to get context from canvas"), + }; + Sendable(context.into()) + } +} + impl crate::Context for Context { type AdapterId = Sendable; type DeviceId = Sendable; @@ -949,11 +973,7 @@ impl crate::Context for Context { .expect("expected to find single canvas") .into(); let canvas_element: web_sys::HtmlCanvasElement = canvas_node.into(); - let context: wasm_bindgen::JsValue = match canvas_element.get_context("webgpu") { - Ok(Some(ctx)) => ctx.into(), - _ => panic!("expected to get context from canvas"), - }; - Sendable(context.into()) + self.instance_create_surface_from_canvas(&canvas_element) } fn adapter_is_surface_supported( diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 3d258cd2ff..3eecd45ac2 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -1480,6 +1480,40 @@ impl Instance { self.context.create_surface_from_core_animation_layer(layer) } + /// Creates a surface from a `web_sys::HtmlCanvasElement`. + /// + /// # Safety + /// + /// - canvas must be a valid element to create a surface upon. + #[cfg(target_arch = "wasm32")] + pub unsafe fn create_surface_from_canvas( + &self, + canvas: &web_sys::HtmlCanvasElement, + ) -> Surface { + Surface { + context: Arc::clone(&self.context), + id: self.context.instance_create_surface_from_canvas(canvas), + } + } + + /// Creates a surface from a `web_sys::OffscreenCanvas`. + /// + /// # Safety + /// + /// - canvas must be a valid OffscreenCanvas to create a surface upon. + #[cfg(target_arch = "wasm32")] + pub unsafe fn create_surface_from_offscreen_canvas( + &self, + canvas: &web_sys::OffscreenCanvas, + ) -> Surface { + Surface { + context: Arc::clone(&self.context), + id: self + .context + .instance_create_surface_from_offscreen_canvas(canvas), + } + } + /// Polls all devices. /// If `force_wait` is true and this is not running on the web, /// then this function will block until all in-flight buffers have been mapped.