Skip to content

Commit

Permalink
WebGL: add support for more RawWindowHandle variants (#4888)
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda authored Dec 18, 2023
1 parent 159ac9e commit bcdc240
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 23 deletions.
33 changes: 22 additions & 11 deletions wgpu-hal/src/gles/web.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use glow::HasContext;
use parking_lot::{Mutex, RwLock};
use wasm_bindgen::JsCast;
use wasm_bindgen::{JsCast, JsValue};

use super::TextureFormatDesc;

Expand Down Expand Up @@ -55,7 +55,7 @@ impl Instance {
fn create_surface_from_context(
&self,
canvas: Canvas,
context_result: Result<Option<js_sys::Object>, wasm_bindgen::JsValue>,
context_result: Result<Option<js_sys::Object>, JsValue>,
) -> Result<Surface, crate::InstanceError> {
let context_object: js_sys::Object = match context_result {
Ok(Some(context)) => context,
Expand Down Expand Up @@ -147,22 +147,33 @@ impl crate::Instance<super::Api> for Instance {
_display_handle: raw_window_handle::RawDisplayHandle,
window_handle: raw_window_handle::RawWindowHandle,
) -> Result<Surface, crate::InstanceError> {
if let raw_window_handle::RawWindowHandle::Web(handle) = window_handle {
let canvas: web_sys::HtmlCanvasElement = web_sys::window()
let canvas: web_sys::HtmlCanvasElement = match window_handle {
raw_window_handle::RawWindowHandle::Web(handle) => web_sys::window()
.and_then(|win| win.document())
.expect("Cannot get document")
.query_selector(&format!("canvas[data-raw-handle=\"{}\"]", handle.id))
.expect("Cannot query for canvas")
.expect("Canvas is not found")
.dyn_into()
.expect("Failed to downcast to canvas type");
.expect("Failed to downcast to canvas type"),
raw_window_handle::RawWindowHandle::WebCanvas(handle) => {
let value: &JsValue = unsafe { handle.obj.cast().as_ref() };
value.clone().unchecked_into()
}
raw_window_handle::RawWindowHandle::WebOffscreenCanvas(handle) => {
let value: &JsValue = unsafe { handle.obj.cast().as_ref() };
let canvas: web_sys::OffscreenCanvas = value.clone().unchecked_into();

self.create_surface_from_canvas(canvas)
} else {
Err(crate::InstanceError::new(format!(
"window handle {window_handle:?} is not a web handle"
)))
}
return self.create_surface_from_offscreen_canvas(canvas);
}
_ => {
return Err(crate::InstanceError::new(format!(
"window handle {window_handle:?} is not a web handle"
)))
}
};

self.create_surface_from_canvas(canvas)
}

unsafe fn destroy_surface(&self, surface: Surface) {
Expand Down
36 changes: 24 additions & 12 deletions wgpu/src/backend/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1098,20 +1098,32 @@ impl crate::context::Context for Context {
_display_handle: raw_window_handle::RawDisplayHandle,
window_handle: raw_window_handle::RawWindowHandle,
) -> Result<(Self::SurfaceId, Self::SurfaceData), crate::CreateSurfaceError> {
let canvas_attribute = match window_handle {
raw_window_handle::RawWindowHandle::Web(web_handle) => web_handle.id,
let canvas_element: web_sys::HtmlCanvasElement = match window_handle {
raw_window_handle::RawWindowHandle::Web(handle) => {
let canvas_node: wasm_bindgen::JsValue = web_sys::window()
.and_then(|win| win.document())
.and_then(|doc| {
doc.query_selector_all(&format!("[data-raw-handle=\"{}\"]", handle.id))
.ok()
})
.and_then(|nodes| nodes.get(0))
.expect("expected to find single canvas")
.into();
canvas_node.into()
}
raw_window_handle::RawWindowHandle::WebCanvas(handle) => {
let value: &JsValue = unsafe { handle.obj.cast().as_ref() };
value.clone().unchecked_into()
}
raw_window_handle::RawWindowHandle::WebOffscreenCanvas(handle) => {
let value: &JsValue = unsafe { handle.obj.cast().as_ref() };
let canvas: web_sys::OffscreenCanvas = value.clone().unchecked_into();

return self.instance_create_surface_from_offscreen_canvas(canvas);
}
_ => panic!("expected valid handle for canvas"),
};
let canvas_node: wasm_bindgen::JsValue = web_sys::window()
.and_then(|win| win.document())
.and_then(|doc| {
doc.query_selector_all(&format!("[data-raw-handle=\"{canvas_attribute}\"]"))
.ok()
})
.and_then(|nodes| nodes.get(0))
.expect("expected to find single canvas")
.into();
let canvas_element: web_sys::HtmlCanvasElement = canvas_node.into();

self.instance_create_surface_from_canvas(canvas_element)
}

Expand Down

0 comments on commit bcdc240

Please sign in to comment.