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

Disjoint types are generated for different versions of webgl #476

Open
aubreyrjones opened this issue Nov 11, 2018 · 5 comments
Open

Disjoint types are generated for different versions of webgl #476

aubreyrjones opened this issue Nov 11, 2018 · 5 comments

Comments

@aubreyrjones
Copy link

I'm new to Rust, so I may be misunderstanding. Please close if so.

It appears that disjoint types are created for different versions of OpenGL. While I understand the appeal, and it's a pattern that shows up in several other frameworks (like Qt and Java), this makes it very hard to write code that targets common subsets of functionality. Every function winds up targeting specific versions in their parameter structure, and upgrading to a new version requires touching all those functions.

In C/C++, one can write OpenGL code using only the API common between ES 3, GL 4.5, and WebGL 2, then swap the actual GL implementation just by choosing a different header file and loader library. Likewise, if I have code that works in desktop 3.3, I can upgrade to 4.4 just by requesting a new context version and getting the new header.

A function in C like void clear_framebuffer() { glClear(GL_COLOR_BUFFER_BIT); } can be recompiled under any version of OpenGL that has ever been written. But I'm struggling to write an equivalent Rust function using these bindings.

I'm too much a beginner at this language to offer a suggested solution. I would guess maybe autogenerated traits? But the current situation appears to limit the portability of code written with at least the WebGL crates.

@brendanzab
Copy link
Owner

Good thinking! Yeah, I'm not sure what we can do about this, and I think it is worth thinking about! It would certainly be nice to be able to share common interfaces! Maybe traits would indeed be a solution... 🤔

@Diggsey
Copy link
Collaborator

Diggsey commented Nov 11, 2018

The GLContext type is what you're looking for - it can store any version of a webgl context and has methods for all of them.

@aubreyrjones
Copy link
Author

@Diggsey oh! I see that type. But I think my Rust ignorance is showing, because I cannot figure out how to assign a "real" context into it. There's some kind of magic going on with the InstanceOf trait, I think... but I don't even know what to google.

@Diggsey
Copy link
Collaborator

Diggsey commented Nov 11, 2018

This is more of a stdweb-ism than a rust-ism, but you can cast between any reference types in stdweb using the TryFrom trait - see here: https://docs.rs/webgl_stdweb/0.3.0/webgl_stdweb/struct.GLContext.html#impl-TryFrom%3CReference%3E

@aubreyrjones
Copy link
Author

@Diggsey ah, okay. I went ahead and enabled all the nightly try_from stuff. And I learned in the process that type inference works "both ways" in Rust, and that you can write something like try_into which depends on knowing the type of the receiver! Trippy!

However, now I get the following error which gives me pause:

  --> src/main.rs:30:34
   |
30 |     let ctx: GLContext = context.try_into().unwrap();
   |                                  ^^^^^^^^ the trait `stdweb::unstable::TryFrom<doodle::WebGL2RenderingContext>` is not implemented for `doodle::GLContext`
   |
   = help: the following implementations were found:
             <doodle::GLContext as stdweb::unstable::TryFrom<&'_r stdweb::Reference>>
             <doodle::GLContext as stdweb::unstable::TryFrom<&'_r stdweb::Value>>
             <doodle::GLContext as stdweb::unstable::TryFrom<stdweb::Reference>>
             <doodle::GLContext as stdweb::unstable::TryFrom<stdweb::Value>>
   = note: required because of the requirements on the impl of `stdweb::unstable::TryInto<doodle::GLContext>` for `doodle::WebGL2RenderingContext`

So what I'm seeing is that it's not a Rust conversion, but rather that it's stdweb exploiting the fact that it can send js!{} to either context without any type checking on the back end. I see what you meant.

This is nice, but I actually only support WebGL 2. My target common subset is actually WebGL 2, GL ES 3.0, and OpenGL 4.4 across WASM, ARM, and x86_64 targets respectively. I want the same renderering code to work everywhere with only a recompile. This is a thing in C++, but Rust is a much more attractive language for the browser than C++, so that's what we're going to use.

Am I going to be able to try_into() from a native GL context? Or should I be looking at parsing the IDL and doing codegen for my common subset?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants