diff --git a/CHANGELOG.md b/CHANGELOG.md index 94705b3340..ff05881b0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -129,6 +129,7 @@ By @cwfitzgerald in [#3671](https://github.com/gfx-rs/wgpu/pull/3671). - Change type of `mip_level_count` and `array_layer_count` (members of `TextureViewDescriptor` and `ImageSubresourceRange`) from `Option` to `Option`. By @teoxoy in [#3445](https://github.com/gfx-rs/wgpu/pull/3445) - All `fxhash` dependencies have been replaced with `rustc-hash`. By @james7132 in [#3502](https://github.com/gfx-rs/wgpu/pull/3502) - Change type of `bytes_per_row` and `rows_per_image` (members of `ImageDataLayout`) from `Option` to `Option`. By @teoxoy in [#3529](https://github.com/gfx-rs/wgpu/pull/3529) +- On Web, `Instance::create_surface_from_canvas()` and `create_surface_from_offscreen_canvas()` now take the canvas by value. By @daxpedda in [#3690](https://github.com/gfx-rs/wgpu/pull/3690) ### Changes @@ -144,6 +145,7 @@ By @cwfitzgerald in [#3671](https://github.com/gfx-rs/wgpu/pull/3671). - Don't include ANSI terminal color escape sequences in shader module validation error messages. By @jimblandy in [#3591](https://github.com/gfx-rs/wgpu/pull/3591) - Report error messages from DXC compile. By @Davidster in [#3632](https://github.com/gfx-rs/wgpu/pull/3632) - Error in native when using a filterable `TextureSampleType::Float` on a multisample `BindingType::Texture`. By @mockersf in [#3686](https://github.com/gfx-rs/wgpu/pull/3686) +- On Web, the size of the canvas is adjusted when using `Surface::configure()`. If the canvas was given an explicit size (via CSS), this will not affect the visual size of the canvas. By @daxpedda in [#3690](https://github.com/gfx-rs/wgpu/pull/3690) #### WebGPU diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 8db3d60d06..c5989f4bf4 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -520,7 +520,7 @@ impl Global { #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] pub fn create_surface_webgl_canvas( &self, - canvas: &web_sys::HtmlCanvasElement, + canvas: web_sys::HtmlCanvasElement, id_in: Input, ) -> Result { profiling::scope!("Instance::create_surface_webgl_canvas"); @@ -547,7 +547,7 @@ impl Global { #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] pub fn create_surface_webgl_offscreen_canvas( &self, - canvas: &web_sys::OffscreenCanvas, + canvas: web_sys::OffscreenCanvas, id_in: Input, ) -> Result { profiling::scope!("Instance::create_surface_webgl_offscreen_canvas"); diff --git a/wgpu-hal/src/gles/web.rs b/wgpu-hal/src/gles/web.rs index 01c37ec5f9..565ffcab18 100644 --- a/wgpu-hal/src/gles/web.rs +++ b/wgpu-hal/src/gles/web.rs @@ -31,20 +31,20 @@ pub struct Instance { impl Instance { pub fn create_surface_from_canvas( &self, - canvas: &web_sys::HtmlCanvasElement, + canvas: web_sys::HtmlCanvasElement, ) -> Result { - self.create_surface_from_context( - canvas.get_context_with_context_options("webgl2", &Self::create_context_options()), - ) + let result = + canvas.get_context_with_context_options("webgl2", &Self::create_context_options()); + self.create_surface_from_context(Canvas::Canvas(canvas), result) } pub fn create_surface_from_offscreen_canvas( &self, - canvas: &web_sys::OffscreenCanvas, + canvas: web_sys::OffscreenCanvas, ) -> Result { - self.create_surface_from_context( - canvas.get_context_with_context_options("webgl2", &Self::create_context_options()), - ) + let result = + canvas.get_context_with_context_options("webgl2", &Self::create_context_options()); + self.create_surface_from_context(Canvas::Offscreen(canvas), result) } /// Common portion of public `create_surface_from_*` functions. @@ -53,6 +53,7 @@ impl Instance { /// `wgpu::backend::web::Context`. fn create_surface_from_context( &self, + canvas: Canvas, context_result: Result, wasm_bindgen::JsValue>, ) -> Result { let context_object: js_sys::Object = match context_result { @@ -84,6 +85,7 @@ impl Instance { *self.webgl2_context.lock() = Some(webgl2_context.clone()); Ok(Surface { + canvas, webgl2_context, srgb_present_program: None, swapchain: None, @@ -142,7 +144,7 @@ impl crate::Instance for Instance { .dyn_into() .expect("Failed to downcast to canvas type"); - self.create_surface_from_canvas(&canvas) + self.create_surface_from_canvas(canvas) } else { Err(crate::InstanceError) } @@ -161,6 +163,7 @@ impl crate::Instance for Instance { #[derive(Clone, Debug)] pub struct Surface { + canvas: Canvas, webgl2_context: web_sys::WebGl2RenderingContext, pub(super) swapchain: Option, texture: Option, @@ -168,6 +171,12 @@ pub struct Surface { srgb_present_program: Option, } +#[derive(Clone, Debug)] +enum Canvas { + Canvas(web_sys::HtmlCanvasElement), + Offscreen(web_sys::OffscreenCanvas), +} + // SAFE: Because web doesn't have threads ( yet ) unsafe impl Sync for Surface {} unsafe impl Send for Surface {} @@ -270,6 +279,17 @@ impl crate::Surface for Surface { device: &super::Device, config: &crate::SurfaceConfiguration, ) -> Result<(), crate::SurfaceError> { + match self.canvas { + Canvas::Canvas(ref canvas) => { + canvas.set_width(config.extent.width); + canvas.set_height(config.extent.height); + } + Canvas::Offscreen(ref canvas) => { + canvas.set_width(config.extent.width); + canvas.set_height(config.extent.height); + } + } + let gl = &device.shared.context.lock(); if let Some(swapchain) = self.swapchain.take() { diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index 53f3c81dfe..2f33915ba9 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -173,8 +173,9 @@ async fn setup(title: &str) -> Setup { let surface = { if let Some(offscreen_canvas_setup) = &offscreen_canvas_setup { log::info!("Creating surface from OffscreenCanvas"); - instance - .create_surface_from_offscreen_canvas(&offscreen_canvas_setup.offscreen_canvas) + instance.create_surface_from_offscreen_canvas( + offscreen_canvas_setup.offscreen_canvas.clone(), + ) } else { instance.create_surface(&window) } diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index d79c11f8f0..6d181043e8 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -205,7 +205,7 @@ impl Context { #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] pub fn instance_create_surface_from_canvas( &self, - canvas: &web_sys::HtmlCanvasElement, + canvas: web_sys::HtmlCanvasElement, ) -> Result { let id = self .0 @@ -220,7 +220,7 @@ impl Context { #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] pub fn instance_create_surface_from_offscreen_canvas( &self, - canvas: &web_sys::OffscreenCanvas, + canvas: web_sys::OffscreenCanvas, ) -> Result { let id = self .0 diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index 743c51b9df..e0d78c3fe0 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -762,7 +762,7 @@ where impl Context { pub fn instance_create_surface_from_canvas( &self, - canvas: &web_sys::HtmlCanvasElement, + canvas: web_sys::HtmlCanvasElement, ) -> Result< ( ::SurfaceId, @@ -770,12 +770,13 @@ impl Context { ), crate::CreateSurfaceError, > { - self.create_surface_from_context(canvas.get_context("webgpu")) + let result = canvas.get_context("webgpu"); + self.create_surface_from_context(Canvas::Canvas(canvas), result) } pub fn instance_create_surface_from_offscreen_canvas( &self, - canvas: &web_sys::OffscreenCanvas, + canvas: web_sys::OffscreenCanvas, ) -> Result< ( ::SurfaceId, @@ -783,7 +784,8 @@ impl Context { ), crate::CreateSurfaceError, > { - self.create_surface_from_context(canvas.get_context("webgpu")) + let result = canvas.get_context("webgpu"); + self.create_surface_from_context(Canvas::Offscreen(canvas), result) } /// Common portion of public `instance_create_surface_from_*` functions. @@ -792,6 +794,7 @@ impl Context { /// `wgpu_hal::gles::web::Instance`. fn create_surface_from_context( &self, + canvas: Canvas, context_result: Result, wasm_bindgen::JsValue>, ) -> Result< ( @@ -825,7 +828,7 @@ impl Context { .dyn_into() .expect("canvas context is not a GPUCanvasContext"); - Ok(create_identified(context)) + Ok(create_identified((canvas, context))) } } @@ -844,6 +847,12 @@ extern "C" { fn worker(this: &Global) -> JsValue; } +#[derive(Debug)] +pub enum Canvas { + Canvas(web_sys::HtmlCanvasElement), + Offscreen(web_sys::OffscreenCanvas), +} + impl crate::context::Context for Context { type AdapterId = Identified; type AdapterData = Sendable; @@ -885,8 +894,8 @@ impl crate::context::Context for Context { type RenderBundleEncoderData = Sendable; type RenderBundleId = Identified; type RenderBundleData = Sendable; - type SurfaceId = Identified; - type SurfaceData = Sendable; + type SurfaceId = Identified<(Canvas, web_sys::GpuCanvasContext)>; + type SurfaceData = Sendable<(Canvas, web_sys::GpuCanvasContext)>; type SurfaceOutputDetail = SurfaceOutputDetail; type SubmissionIndex = Unused; @@ -949,7 +958,7 @@ impl crate::context::Context for Context { .expect("expected to find single canvas") .into(); let canvas_element: web_sys::HtmlCanvasElement = canvas_node.into(); - self.instance_create_surface_from_canvas(&canvas_element) + self.instance_create_surface_from_canvas(canvas_element) } fn instance_request_adapter( @@ -1138,6 +1147,17 @@ impl crate::context::Context for Context { device_data: &Self::DeviceData, config: &crate::SurfaceConfiguration, ) { + match surface_data.0 .0 { + Canvas::Canvas(ref canvas) => { + canvas.set_width(config.width); + canvas.set_height(config.height); + } + Canvas::Offscreen(ref canvas) => { + canvas.set_width(config.width); + canvas.set_height(config.height); + } + } + if let wgt::PresentMode::Mailbox | wgt::PresentMode::Immediate = config.present_mode { panic!("Only FIFO/Auto* is supported on web"); } @@ -1160,7 +1180,7 @@ impl crate::context::Context for Context { .map(|format| JsValue::from(map_texture_format(*format))) .collect::(); mapped.view_formats(&mapped_view_formats); - surface_data.0.configure(&mapped); + surface_data.0 .1.configure(&mapped); } fn surface_get_current_texture( @@ -1173,7 +1193,7 @@ impl crate::context::Context for Context { wgt::SurfaceStatus, Self::SurfaceOutputDetail, ) { - let (surface_id, surface_data) = create_identified(surface_data.0.get_current_texture()); + let (surface_id, surface_data) = create_identified(surface_data.0 .1.get_current_texture()); ( Some(surface_id), Some(surface_data), diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index b783e0f0dc..c694d9a5db 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -1599,7 +1599,7 @@ impl Instance { #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] pub fn create_surface_from_canvas( &self, - canvas: &web_sys::HtmlCanvasElement, + canvas: web_sys::HtmlCanvasElement, ) -> Result { let surface = self .context @@ -1635,7 +1635,7 @@ impl Instance { #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] pub fn create_surface_from_offscreen_canvas( &self, - canvas: &web_sys::OffscreenCanvas, + canvas: web_sys::OffscreenCanvas, ) -> Result { let surface = self .context diff --git a/wgpu/tests/common/mod.rs b/wgpu/tests/common/mod.rs index e50a9bdfab..4e0f784bec 100644 --- a/wgpu/tests/common/mod.rs +++ b/wgpu/tests/common/mod.rs @@ -358,7 +358,7 @@ fn initialize_adapter() -> (Adapter, SurfaceGuard) { let canvas = create_html_canvas(); let surface = instance - .create_surface_from_canvas(&canvas) + .create_surface_from_canvas(canvas.clone()) .expect("could not create surface from canvas"); surface_guard = SurfaceGuard { canvas };