glutin icon indicating copy to clipboard operation
glutin copied to clipboard

wasm-unknown-unknown support

Open StevenDoesStuffs opened this issue 5 years ago • 18 comments

Are there any plans to support the wasm-unknown-unknown target with wasm-bindgen? That seems to be where most of the community is headed.

StevenDoesStuffs avatar Jun 09 '19 06:06 StevenDoesStuffs

If someone wants to do it, I'll be happy to accept it.

goddessfreya avatar Jun 09 '19 06:06 goddessfreya

https://github.com/rust-windowing/winit/pull/845 https://github.com/rust-windowing/winit/pull/797

goddessfreya avatar Jun 17 '19 22:06 goddessfreya

https://github.com/rust-windowing/winit/issues/1072

est31 avatar Aug 04 '19 01:08 est31

I'm working on this. If it's been two weeks and there's no update assume I'm lost at sea and ping me.

TannerRogalsky avatar Sep 04 '19 00:09 TannerRogalsky

Let's consider the difference between winit's "emscripten" and "web" Window structures, respectively.

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId(usize);

impl WindowId {
    pub unsafe fn dummy() -> Self {
        WindowId(0)
    }
}

pub struct Window2 {
    cursor_grabbed: Mutex<bool>,
    cursor_visible: Mutex<bool>,
    is_fullscreen: bool,
    events: Box<Mutex<VecDeque<::Event>>>,
}

pub struct Window {
    window: Arc<Window2>,
}
mod backend {
    pub struct Canvas {
        raw: HtmlCanvasElement,
        ...
    }
}

pub struct Window {
    canvas: backend::Canvas,
    previous_pointer: RefCell<&'static str>,
    position: RefCell<LogicalPosition>,
}

In many ways I think that the web one is better.

The emscripten struct maintains no identifying information. The emscripten implementation, when asked for it's id, always returns 0. When setting HTML state, the emscripten implementation either uses an API that doesn't specify a target or passes a null pointer (both of these actions result in emscripten falling back to it's own internally-tracked reference to the canvas object).

The web one maintains a reference to the canvas object. The creation function creates the canvas element. It's not clear to me where (or if) that gets inserted into the document (it's possible that that's beyond glutin's scope). State queries and modifications act on that reference.

Where this falls down is that glutin requires that Context implement Send + Sync. At it's core, the Canvas reference (via wasm_bindgen::JsValue) is backed by a *mut u8 which... presents some thread-safety issues.

The easiest solution is to modify the web implementation to maintain a singleton reference outside of it's struct. It's bad but it's bad in a similar way to how the emscripten implementation is bad. Better solutions aren't coming to me right off the bat. But maybe posting this will spark some conversation. Either way I will try the easy way and report back.

TannerRogalsky avatar Sep 05 '19 00:09 TannerRogalsky

I haven't given up on this but I'm expanding my thesis a bit. Bear with me.

TannerRogalsky avatar Sep 23 '19 15:09 TannerRogalsky

So there are two outstanding issues that I see with bringing wasm32-unknown-unknown support to glutin.

Firstly, as outlined above, glutin's requirement that the window context implement the synchronization traits is problematic with regards to the web. References to a canvas element (or any JS references for that matter) cannot be shared between threads. There are definitely hacks to get around this but that would mean that glutin's API is writing checks that it's implementation can't cash. An honest implementation for the web will require a relaxation of those trait requirements.

Secondly, one of the primary benefits from using this library is being able to initialize a GL context via get_proc_address. While it's likely possible to replicate that functionality with WebGL, the API differences between OpenGL and WebGL will require awareness from the calling code anyway so the point is, I think, moot.

Between these two issues, I'm not sure bringing wasm32-unknown-unknown support to glutin is valuable.

That said, winit's web improvements + glow together offer what I think is a compelling replacement on web.

TannerRogalsky avatar Oct 11 '19 00:10 TannerRogalsky

I'm not familiar with how how get_proc_address would work w/ web, as I have no knowledge wrt wasm-unknown-unknown.

As for the requirement of Sync + Send, we could just not implement FailToCompileIfNotSendSync on Context<NotCurrent> on web. I'm pretty sure JS does not support multi threading, altho I'm not precisely sure how it works wrt wasm-unknown-unknown.

goddessfreya avatar Oct 11 '19 03:10 goddessfreya

Implementing get_proc_address can be made to work. There currently aren't any crates that I'm aware of that could take advantage of that on web because the way that WebGL bindings are loaded and used is significantly different from OpenGL. I suppose that's a chicken and the egg problem, though, so that's not necessarily a non-starter.

Yeah, relaxing the requirements for that trait from being global to being native-only would resolve the first problem. Really, it should be relaxed for web platforms, though, including emscripten. Does that sound reasonable to you?

TannerRogalsky avatar Oct 11 '19 10:10 TannerRogalsky

WebGL is fundamentally binary-incompatible with OpenGL. It's a JavaScript API, with quite a few differences. It would require an OpenGL implementation that acts as a translation layer, which is what emscripten does.

I'm currently working on a crate that would provide a similar thing, but as a standalone library that works on wasm32-unknown-unknown, if you are interested in following its progress and/or contributing. It's not completely conformant yet, though I do have some working demos, and I'm actively working on compatibility issues as I find them.

agausmann avatar Apr 14 '20 12:04 agausmann

What about adding optional integration with glow instead? glutin can add a function to retrieve a glow context, which will internally use glow::Context::from_loader_function and get_proc_address on native platforms, but use HtmlCanvasElement::get_context("webgl2") and glow::Context::from_webgl2_context (or webgl1) on wasm32 + web-sys.

alvinhochun avatar Aug 29 '20 12:08 alvinhochun

+1 for glow, it also supports wasm-unknown-emscripten

caiiiycuk avatar Jan 03 '22 13:01 caiiiycuk

This should be reiterated, given that winit is not involved anymore.

kchibisov avatar Sep 03 '22 06:09 kchibisov