Skip to content

Commit

Permalink
web: Add Instance::create_surface_from_canvas
Browse files Browse the repository at this point in the history
Add specialized methods on web for creating a wgpu Surface directly
from an web_sys::HTMLCanvasElement and OffscreenCanvas.

 * Instance::create_surface_from_canvas
 * Instance::create_surface_from_offscreen_canvas

Fixes #1837.
  • Loading branch information
Herschel authored and kvark committed Sep 10, 2021
1 parent ca6fd97 commit 8080a3c
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 5 deletions.
1 change: 1 addition & 0 deletions wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ web-sys = { version = "0.3.53", features = [
"GpuVertexState",
"GpuVertexStepMode",
"HtmlCanvasElement",
"OffscreenCanvas",
"Window",
]}
js-sys = "0.3.50"
Expand Down
30 changes: 25 additions & 5 deletions wgpu/src/backend/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
) -> <Self as crate::Context>::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,
) -> <Self as crate::Context>::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<web_sys::GpuAdapter>;
type DeviceId = Sendable<web_sys::GpuDevice>;
Expand Down Expand Up @@ -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(
Expand Down
34 changes: 34 additions & 0 deletions wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 <canvas> 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.
Expand Down

0 comments on commit 8080a3c

Please sign in to comment.