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

Add from_canvas() to Surface for Wasm #76

Merged
merged 4 commits into from
May 8, 2023

Conversation

daxpedda
Copy link
Member

@daxpedda daxpedda commented Feb 28, 2023

Added methods to create Surface from a HtmlCanvasElement or OffscreenCanvas following wgpu's example https://github.com/gfx-rs/wgpu/blob/v0.15.1/wgpu/src/lib.rs#L1570-L1640

My use case required this to render in a web worker.

Edit: See this for a future alternative implementation rust-windowing/raw-window-handle#102

This PR addresses the issues in #74 and additionally handles an error when using OffscreenCanvas, which has a different context type: OffscreenCanvasRenderingContext2d. It was assumed that it inherits from CanvasRenderingContext2d, which it does not, see the MDN documentation.

I spoke to @Toniman575 after we discussed some issues, he told me to replace his PR instead.

Replaces #74.

src/lib.rs Show resolved Hide resolved
src/web.rs Outdated Show resolved Hide resolved
src/web.rs Outdated
Comment on lines 42 to 62
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = OffscreenCanvasRenderingContext2D)]
pub type OffscreenCanvasRenderingContext2d;

#[wasm_bindgen(catch, method, structural, js_class = "OffscreenCanvasRenderingContext2D", js_name = putImageData)]
fn put_image_data(
this: &OffscreenCanvasRenderingContext2d,
imagedata: &ImageData,
dx: f64,
dy: f64,
) -> Result<(), JsValue>;

#[wasm_bindgen(method, structural, js_class = "OffscreenCanvasRenderingContext2D")]
pub fn commit(this: &OffscreenCanvasRenderingContext2d);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

web-sys doesn't currently support OffscreenCanvasRenderingContext2D, a PR has already been made and merged, but it will require a new version release: rustwasm/wasm-bindgen#3319.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's wait for that, then

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, will put it into draft mode then.

@daxpedda
Copy link
Member Author

CI failures are because sudo apt-get update && sudo apt-get install gcc-multilib fails on Linux.

@ids1024
Copy link
Member

ids1024 commented Feb 28, 2023

CI seems to pass after rerunning the failed jobs.

@daxpedda
Copy link
Member Author

Thanks 🎉.

src/web.rs Outdated
Comment on lines 158 to 155
fn from_canvas(canvas: HtmlCanvasElement) -> Result<Self, SoftBufferError>;

/// Creates a new instance of this struct, using the provided [`HtmlCanvasElement`].
fn from_offscreen_canvas(offscreen_canvas: OffscreenCanvas) -> Result<Self, SoftBufferError>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd still like to avoid having web_sys as a public dependency if possible. I know winit does it, but I'd like to keep the number of public dependencies in this project as low as possible.

Would it be possible to just pass in the ID/XPath of the canvas into these functions instead?

Copy link
Member Author

@daxpedda daxpedda Mar 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also want to add that wgpu does that too: https://github.com/gfx-rs/wgpu/blob/v0.15.1/wgpu/src/lib.rs#L1570-L1640.


It would be possible for HtmlCanvasElement, but not for OffscreenCanvas, because it's not a DOM element.
The best alternative I can come up with is using wasm_bindgen::JsValue.

Another unsafe alternative I can think of is using a pointer, basically. See wasm_bindgen::convert::IntoWasmAbi.

Completely different direction: we could maybe hide this behind a feature called wasm-bindgen instead of just hiding it behind target_arch = wasm32, if this alleviates some of your concerns.


I want to point out though, that specifically with the wasm-bindgen ecosystem there is not much gained from avoiding making it a public dependency. The thing is that if a library uses wasm-bindgen, the library can't actually work without downstream users having to use wasm-bindgen-cli, so switching to a different ecosystem would still require a breaking change. Even having different versions is not allowed, wasm-bindgen-cli will error out if you do.

At least to me, versioning and the inability to change a dependency without a breaking change, are the big reasons to keep public dependencies low.

EDIT: For more context: this issue with wasm-bindgen and being locked into it's ecosystem is not going to go away anytime soon. The problem is that to make wasm-bindgen work, a JS shim has to be created that provides all the necessary imports, this is done by wasm-bindgen-cli by actually parsing the compiled Wasm file and then extracting the necessary information. Without running wasm-bindgen-cli your Wasm file is unusable. Not only does it generate the JS shim, but it actually modifies the Wasm file to actually make it work, this includes removing garbage that is inserted during the compilation by wasm-bindgen and properly hooking up imports and what wasm-bindgen calls intrinsics, basically things like referencing JsValues, copying arrays and what not.

The only salvation in sight is the Component Model Proposal, which is still at Phase 1.

But when it eventually gets accepted, we won't need wasm-bindgen anymore and hopefully we can move to ecosystem neutral Wasm libraries that don't force downstream users in one or the other ecosystem.

Copy link
Member

@madsmtm madsmtm Mar 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds reasonable to me, I'd be fine with the public dep on web-sys in this case.

@daxpedda
Copy link
Member Author

daxpedda commented Apr 6, 2023

Rebased after #65.

@daxpedda
Copy link
Member Author

daxpedda commented Apr 6, 2023

Rebased after #77.

@daxpedda
Copy link
Member Author

Rebased after #88.

@notgull
Copy link
Member

notgull commented May 7, 2023

Would it be possible to split this PR into one that adds the ability to use a HtmlCanvasElement and one for OffscreenCanvas? We can do the first one now but we need to wait until rustwasm/wasm-bindgen#3319 for the second one.

Cargo.toml Outdated
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other targets don't have any target-specific APIs, should I still add them to the list?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say yes; I think they've expected at this point.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only added 64-bit targets, say the word if I should add anything else.

@daxpedda daxpedda marked this pull request as ready for review May 8, 2023 10:24
@daxpedda
Copy link
Member Author

daxpedda commented May 8, 2023

Would it be possible to split this PR into one that adds the ability to use a HtmlCanvasElement and one for OffscreenCanvas? We can do the first one now but we need to wait until rustwasm/wasm-bindgen#3319 for the second one.

Done: #103.

@daxpedda daxpedda requested a review from notgull May 8, 2023 10:30
Copy link
Member

@notgull notgull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM aside from minor nitpicks

src/web.rs Outdated Show resolved Hide resolved
@daxpedda daxpedda requested a review from notgull May 8, 2023 13:33
@daxpedda daxpedda merged commit fcda747 into rust-windowing:master May 8, 2023
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants