Skip to content
This repository has been archived by the owner on Mar 4, 2024. It is now read-only.

GLContext integration #94

Open
gkoz opened this issue Nov 3, 2015 · 20 comments
Open

GLContext integration #94

gkoz opened this issue Nov 3, 2015 · 20 comments
Labels
enhancement New feature or request gdk

Comments

@gkoz
Copy link
Member

gkoz commented Nov 3, 2015

There currently is no reliable way to use the glium/gl crates together with GLContext (and gtk::GLArea), which a very limited API. Previous discussion is at gtk-rs/examples#44, let's continue it here.

@gkoz
Copy link
Member Author

gkoz commented Nov 3, 2015

@mjkoo

Either way to me it looks like GtkGLArea creates a context for you, but relies on you to correctly infer the correct way to load and use OpenGL functions after initialization, so the same type of logic with the same type of assumptions probably needs to go somewhere to make this usable.

What would happen if we gave epoxy_get_proc_address to gl::load_with?

@mjkoo
Copy link

mjkoo commented Nov 3, 2015

Pretty sure that should work, I can give it a try in a bit to confirm. That seems to be about half of what epoxy provides, the other half is autogenerated wrappers around OpenGL functions which load the required symbols at runtime lazily. This is pretty much exactly what gl-rs does AFAICT, so we don't necessarily care about that. Given that, not sure if it would make more sense to make bindings and add in a dependency to libepoxy or just use FFI to call the underlying glx/wgl/egl functions based on the target platform in the same manner epoxy and glutin does.

@gkoz
Copy link
Member Author

gkoz commented Nov 3, 2015

I'd favor adding limited bindings over replicating libepoxy logic.

I'm also unsure if gdk_gl_context_set_required_version and gdk_gl_context_set_forward_compatible can influence the selection of gl* functions in a problematic way or just let you get an error if the implementation is incompatible.

@gkoz
Copy link
Member Author

gkoz commented Nov 3, 2015

It might be possible to look for the epoxy_get_proc_address symbol on demand at runtime instead of adding a dependency.

@mjkoo
Copy link

mjkoo commented Nov 3, 2015

Looking into it now, one issue is that epoxy_get_proc_address is not exposed by libepoxy, likely because it takes some bootstrapping to get it working, which we would also need to make sure gets done prior to using it even if we expose it. We could instead try to load libepoxy at runtime like you said and have gl::load_with attempt to dlsym the equivalent symbols from libepoxy. This is somewhat janky because now there's two levels of symbol lookup and function pointer caching being done, but it looks like not doing that will involve a considerable amount of tearing libepoxy apart.

@mjkoo
Copy link

mjkoo commented Nov 3, 2015

Regarding gdk_gl_context_set_required_version and gdk_gl_context_set_forward_compatible, it looks like they just influence the parameters passed to glXCreateContextAttribsARB from gdk (https://github.com/GNOME/gtk/blob/master/gdk/x11/gdkglcontext-x11.c#L578), which should result in calling an invalid function returning an error code according to https://open.gl/context , so this shouldn't be a worry I think.

Diving into the gdk source it looks like they themselves already depend on libepoxy and use it to set up the context behind the scenes, so that's good news. Do you know of a relatively platform-independent way to dlsym or similar from rust to get at the epoxy_* wrappers from gl-rs?

@gkoz
Copy link
Member Author

gkoz commented Nov 3, 2015

I'm only aware of unstable std::dynamic_lib. FWIW, GTK relies on dlfcn-win32 to provide dlsym on Windows.

@mjkoo
Copy link

mjkoo commented Nov 3, 2015

Pushed a PoC of the example from gtk-rs/examples#44 back to the same branch, now loading OpenGL function addresses from epoxy, relying on it being loaded already by gdk. Uses the shared_library crate which is also used in glutin (std::dynamic_lib is deprecated according to rustc I guess).

This is not correct as it stands, as I'm pretty sure gl-rs's caching of function pointers means that it will always invoke the libepoxy lookup function even when epoxy has already resolved the address and altered it's internal function pointer table resulting in many superfluous dlsym invocations, but is a start.

@mjkoo
Copy link

mjkoo commented Nov 3, 2015

After researching it a bit, I think the best way forward is to use gl_generator from gl-rs with a custom generator to wrap libepoxy and let it handle lookup and caching of the relevant functions when using it with GdkGLContext. I've modified the StaticStructGenerator from gl_generator to generate bindings for epoxy in a build.rs, and modified the example again to use this new method (https://github.com/mjkoo/examples/tree/epoxy-glgenerator) This supports the goal of integrating with glium, as it uses the similar StructGenerator to construct it's own bindings, but using the get_proc_address from glutin or similar.

Wanted to get some thoughts on this before moving forward, but I'm thinking that the build.rs from the branch above can be cleaned up and put into gdk, and the epoxy wrapper struct made accessible from GdkGLContext. A GtkGLArea user can then use the reference to the context in its render handler and can use this to draw to its window.

@gkoz
Copy link
Member Author

gkoz commented Nov 3, 2015

Oh wow, that's some sudden explosion of complexity :)

If generating epoxy bindings is the way to go, that's outside the scope of gdk. In the near term you'd probably want to put an epoxy-gl crate on github and import that in the example.

and the epoxy wrapper struct made accessible from GdkGLContext

From what I can see there's nothing but magical side-effects to tie a particular GLContext instance to the gl* impls, so I'm not sure what the GLContext/GLArea bindings could do except reexport the epoxy bindings.

Perhaps the best solution would be to ignore the whole epoxy/GLContext/GLArea stack and implement a new widget, that would really be in control of its context. Like, wrap the window primitive, that glium creates, in a GdkWindow or vice versa.

@mjkoo
Copy link

mjkoo commented Nov 3, 2015

Okay sure, crate is up and example is updated.

From what I can see there's nothing but magical side-effects to tie a particular GLContext instance to the gl* impls, so I'm not sure what the GLContext/GLArea bindings could do except reexport the epoxy bindings.

Yep, I agree with that assessment. Using the epoxy bindings though should allow us to get some integration going with glium now, perhaps with a small modification to glium to allow generic gl::Gl type structs in glium::context::Context (epoxy::Gl should be a drop-in replacement). If @tomaka isn't for that, potentially a small get_proc_address-like shim could be added to epoxy to allow interop with gl/glium without running into the function pointer caching issue. Will keep exploring down these lines for the time being.

@mjkoo
Copy link

mjkoo commented Nov 5, 2015

As an update, I've ported the simple example from the examples repo to use glium with a GLArea. There's definitely some cleanup to do and some decisions on where things belong, but it seems to work. The work in progress code can be found at https://github.com/mjkoo/examples/tree/glium

@gkoz
Copy link
Member Author

gkoz commented Nov 6, 2015

That's impressive progress :)
FWIW it seems GLContext can be made capable of telling if it's current (by comparing what gdk_gl_context_get_current returns with itself) and the dimensions could be retrieved from its GdkWindow.

swap_buffers... it appears the window painting mechanisms take care of swapping the buffers. Wouldn't queue_render there lead to constant repainting?

@mjkoo
Copy link

mjkoo commented Nov 6, 2015

Thanks! Cool that's good to know, I will change is_current accordingly and try it out. Spot on with your comment on swap_buffers, I actually just fixed that up :)

I'm thinking that once the Backend and Facade implementations are looking good they probably also belong in a separate crate, similar to glium_sdl2, unless you'd like to see this put into gdk somewhere?

@gkoz
Copy link
Member Author

gkoz commented Nov 6, 2015

I will change is_current accordingly and try it out

This will require patching gdk as I don't think PartialEq/Eq is implemented for objects. Not even sure if it would be appropriate in general to implement it as pointers equality. Specialization will make that decision easier :)

I'm thinking that once the Backend and Facade implementations are looking good they probably also belong in a separate crate, similar to glium_sdl2, unless you'd like to see this put into gdk somewhere?

Still not sure but a separate crate is a good bet.

@mjkoo
Copy link

mjkoo commented Nov 6, 2015

Ok cool I will defer doing that for now then, let me know what you'd like to see going forward.

@gkoz
Copy link
Member Author

gkoz commented Nov 6, 2015

A separate crate seems more flexible, we wouldn't need to track changes to glium and epoxy in the gdk and gtk crates and it wouldn't matter that GLArea and GLContext are in different crates.

@phrohdoh
Copy link

Hey @mjkoo - sorry for digging up an old thread!

Has there been any progress on this front? (another crate being spawned or something similar)

I'd really like to use glium in some of my gtk apps. :-}

@mjkoo
Copy link

mjkoo commented Jan 16, 2018

Sorry I ended up going a different route for the project that I was working on and therefore didn't pursue this further, not sure what the glium + gtk story is today.

@bilelmoussaoui bilelmoussaoui transferred this issue from gtk-rs/gdk Nov 10, 2020
@sdroege sdroege added the enhancement New feature or request label Nov 10, 2020
@lattice0
Copy link

What is the state of this? Wanted to render into Flutter which uses GTK, it gives me a GTKWindow and GdkGlContext. Works in C++ so should work in Rust

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request gdk
Projects
None yet
Development

No branches or pull requests

6 participants