Skip to content

Commit

Permalink
Implemented support for creating a render surface from canvas or offs…
Browse files Browse the repository at this point in the history
…creencanvas elements on the wasm target.
  • Loading branch information
anlumo committed Oct 2, 2022
1 parent 3aaf746 commit eb5529e
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
11 changes: 11 additions & 0 deletions crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,17 @@ impl Plugin for RenderPlugin {
let surface = {
let windows = app.world.resource_mut::<bevy_window::Windows>();
let raw_handle = windows.get_primary().map(|window| unsafe {
#[cfg(target_arch = "wasm32")]
if let Some(canvas) = &window.canvas_element {
return match canvas {
bevy_window::Canvas::HtmlCanvas(canvas) => {
instance.create_surface_from_canvas(canvas)
}
bevy_window::Canvas::OffscreenCanvas(canvas) => {
instance.create_surface_from_offscreen_canvas(canvas)
}
};
}
let handle = window.raw_window_handle().get_handle();
instance.create_surface(&handle)
});
Expand Down
15 changes: 15 additions & 0 deletions crates/bevy_render/src/view/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ pub struct ExtractedWindow {
pub swap_chain_texture: Option<TextureView>,
pub size_changed: bool,
pub present_mode_changed: bool,
#[cfg(target_arch = "wasm32")]
pub canvas: Option<bevy_window::Canvas>,
}

#[derive(Default, Resource)]
Expand Down Expand Up @@ -92,6 +94,8 @@ fn extract_windows(
swap_chain_texture: None,
size_changed: false,
present_mode_changed: false,
#[cfg(target_arch = "wasm32")]
canvas: window.canvas_element.clone(),
});

// NOTE: Drop the swap chain frame here
Expand Down Expand Up @@ -168,6 +172,17 @@ pub fn prepare_windows(
.surfaces
.entry(window.id)
.or_insert_with(|| unsafe {
#[cfg(target_arch = "wasm32")]
if let Some(canvas) = &window.canvas {
return match canvas {
bevy_window::Canvas::HtmlCanvas(canvas) => {
render_instance.create_surface_from_canvas(canvas)
}
bevy_window::Canvas::OffscreenCanvas(canvas) => {
render_instance.create_surface_from_offscreen_canvas(canvas)
}
};
}
// NOTE: On some OSes this MUST be called from the main thread.
render_instance.create_surface(&window.handle.get_handle())
});
Expand Down
24 changes: 24 additions & 0 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ pub struct Window {
focused: bool,
mode: WindowMode,
canvas: Option<String>,
#[cfg(target_arch = "wasm32")]
pub canvas_element: Option<Canvas>,
fit_canvas_to_parent: bool,
command_queue: Vec<WindowCommand>,
}
Expand Down Expand Up @@ -339,6 +341,8 @@ impl Window {
focused: true,
mode: window_descriptor.mode,
canvas: window_descriptor.canvas.clone(),
#[cfg(target_arch = "wasm32")]
canvas_element: window_descriptor.canvas_element.clone(),
fit_canvas_to_parent: window_descriptor.fit_canvas_to_parent,
command_queue: Vec::new(),
}
Expand Down Expand Up @@ -781,6 +785,17 @@ pub enum MonitorSelection {
Index(usize),
}

#[cfg(target_arch = "wasm32")]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Canvas {
HtmlCanvas(web_sys::HtmlCanvasElement),
OffscreenCanvas(web_sys::OffscreenCanvas),
}
#[cfg(target_arch = "wasm32")]
unsafe impl Send for Canvas {}
#[cfg(target_arch = "wasm32")]
unsafe impl Sync for Canvas {}

/// Describes the information needed for creating a window.
///
/// This should be set up before adding the [`WindowPlugin`](crate::WindowPlugin).
Expand Down Expand Up @@ -859,6 +874,8 @@ pub struct WindowDescriptor {
///
/// This value has no effect on non-web platforms.
pub canvas: Option<String>,
#[cfg(target_arch = "wasm32")]
pub canvas_element: Option<Canvas>,
/// Whether or not to fit the canvas element's size to its parent element's size.
///
/// **Warning**: this will not behave as expected for parents that set their size according to the size of their
Expand All @@ -869,6 +886,11 @@ pub struct WindowDescriptor {
pub fit_canvas_to_parent: bool,
}

#[cfg(target_arch = "wasm32")]
unsafe impl Send for WindowDescriptor {}
#[cfg(target_arch = "wasm32")]
unsafe impl Sync for WindowDescriptor {}

impl Default for WindowDescriptor {
fn default() -> Self {
WindowDescriptor {
Expand All @@ -887,6 +909,8 @@ impl Default for WindowDescriptor {
mode: WindowMode::Windowed,
transparent: false,
canvas: None,
#[cfg(target_arch = "wasm32")]
canvas_element: None,
fit_canvas_to_parent: false,
}
}
Expand Down

0 comments on commit eb5529e

Please sign in to comment.