web: Add Instance::create_surface_from_canvas

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.
This commit is contained in:
Mike Welsh
2021-09-09 15:36:17 -07:00
committed by Dzmitry Malyshau
parent ca6fd97c62
commit 8080a3c6da
3 changed files with 60 additions and 5 deletions

View File

@@ -269,6 +269,7 @@ web-sys = { version = "0.3.53", features = [
"GpuVertexState",
"GpuVertexStepMode",
"HtmlCanvasElement",
"OffscreenCanvas",
"Window",
]}
js-sys = "0.3.50"

View File

@@ -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>;
@@ -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(

View File

@@ -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.