Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust internal canvas size on Surface::configure() #3690

Merged
merged 2 commits into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<NonZeroU32>` to `Option<u32>`. 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<NonZeroU32>` to `Option<u32>`. 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

Expand All @@ -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

Expand Down
4 changes: 2 additions & 2 deletions wgpu-core/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
#[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<G, SurfaceId>,
) -> Result<SurfaceId, hal::InstanceError> {
profiling::scope!("Instance::create_surface_webgl_canvas");
Expand All @@ -547,7 +547,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
#[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<G, SurfaceId>,
) -> Result<SurfaceId, hal::InstanceError> {
profiling::scope!("Instance::create_surface_webgl_offscreen_canvas");
Expand Down
38 changes: 29 additions & 9 deletions wgpu-hal/src/gles/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Surface, crate::InstanceError> {
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<Surface, crate::InstanceError> {
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.
Expand All @@ -53,6 +53,7 @@ impl Instance {
/// `wgpu::backend::web::Context`.
fn create_surface_from_context(
&self,
canvas: Canvas,
context_result: Result<Option<js_sys::Object>, wasm_bindgen::JsValue>,
) -> Result<Surface, crate::InstanceError> {
let context_object: js_sys::Object = match context_result {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -142,7 +144,7 @@ impl crate::Instance<super::Api> 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)
}
Expand All @@ -161,13 +163,20 @@ impl crate::Instance<super::Api> for Instance {

#[derive(Clone, Debug)]
pub struct Surface {
canvas: Canvas,
webgl2_context: web_sys::WebGl2RenderingContext,
pub(super) swapchain: Option<Swapchain>,
texture: Option<glow::Texture>,
pub(super) presentable: bool,
srgb_present_program: Option<glow::Program>,
}

#[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 {}
Expand Down Expand Up @@ -270,6 +279,17 @@ impl crate::Surface<super::Api> 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() {
Expand Down
5 changes: 3 additions & 2 deletions wgpu/examples/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,9 @@ async fn setup<E: Example>(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)
}
Expand Down
4 changes: 2 additions & 2 deletions wgpu/src/backend/direct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Surface, crate::CreateSurfaceError> {
let id = self
.0
Expand All @@ -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<Surface, crate::CreateSurfaceError> {
let id = self
.0
Expand Down
40 changes: 30 additions & 10 deletions wgpu/src/backend/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,28 +762,30 @@ where
impl Context {
pub fn instance_create_surface_from_canvas(
&self,
canvas: &web_sys::HtmlCanvasElement,
canvas: web_sys::HtmlCanvasElement,
) -> Result<
(
<Self as crate::Context>::SurfaceId,
<Self as crate::Context>::SurfaceData,
),
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<
(
<Self as crate::Context>::SurfaceId,
<Self as crate::Context>::SurfaceData,
),
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.
Expand All @@ -792,6 +794,7 @@ impl Context {
/// `wgpu_hal::gles::web::Instance`.
fn create_surface_from_context(
&self,
canvas: Canvas,
context_result: Result<Option<js_sys::Object>, wasm_bindgen::JsValue>,
) -> Result<
(
Expand Down Expand Up @@ -825,7 +828,7 @@ impl Context {
.dyn_into()
.expect("canvas context is not a GPUCanvasContext");

Ok(create_identified(context))
Ok(create_identified((canvas, context)))
}
}

Expand All @@ -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<web_sys::GpuAdapter>;
type AdapterData = Sendable<web_sys::GpuAdapter>;
Expand Down Expand Up @@ -885,8 +894,8 @@ impl crate::context::Context for Context {
type RenderBundleEncoderData = Sendable<web_sys::GpuRenderBundleEncoder>;
type RenderBundleId = Identified<web_sys::GpuRenderBundle>;
type RenderBundleData = Sendable<web_sys::GpuRenderBundle>;
type SurfaceId = Identified<web_sys::GpuCanvasContext>;
type SurfaceData = Sendable<web_sys::GpuCanvasContext>;
type SurfaceId = Identified<(Canvas, web_sys::GpuCanvasContext)>;
type SurfaceData = Sendable<(Canvas, web_sys::GpuCanvasContext)>;

type SurfaceOutputDetail = SurfaceOutputDetail;
type SubmissionIndex = Unused;
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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");
}
Expand All @@ -1160,7 +1180,7 @@ impl crate::context::Context for Context {
.map(|format| JsValue::from(map_texture_format(*format)))
.collect::<js_sys::Array>();
mapped.view_formats(&mapped_view_formats);
surface_data.0.configure(&mapped);
surface_data.0 .1.configure(&mapped);
}

fn surface_get_current_texture(
Expand All @@ -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),
Expand Down
4 changes: 2 additions & 2 deletions wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Surface, CreateSurfaceError> {
let surface = self
.context
Expand Down Expand Up @@ -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<Surface, CreateSurfaceError> {
let surface = self
.context
Expand Down
2 changes: 1 addition & 1 deletion wgpu/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ fn initialize_adapter() -> (Adapter, SurfaceGuard) {
let canvas = create_html_canvas();

let surface = instance
.create_surface_from_canvas(&canvas)
daxpedda marked this conversation as resolved.
Show resolved Hide resolved
.create_surface_from_canvas(canvas.clone())
.expect("could not create surface from canvas");

surface_guard = SurfaceGuard { canvas };
Expand Down