libui
libui copied to clipboard
OpenGL control
Are there any plans to add an OpenGL control?
GLFW is great for making a bare window and OpenGL context across platforms, but doesn't have the sweet cross-platform UI support that libui seems to offer.
Yes. Unfortunately, GTK+ only added OpenGL support in 3.16, so if I want to use that I'll need to make it a separate library until I can bump my version numbers up (2018) or use the X11-only tegtkgl until then (possibly with Wayland once I formally drop 3.4-3.8 sometime this weekend or next week).
This would potentially be really interesting for https://github.com/servo/servo/. +1 here :)
@andlabs If you're willing to provide a sketch of the API you're looking for, I could start on implementing this in my spare time.
I'd have to evaluate what APIs I can provide; that would mean going through wgl, GtkGLArea, and NSOpenGLView to see how they work and how to do OpenGL with them.
If you haven't seen it yet, a good place to start is looking at GLFW's window attributes (as windows are 1:1 with GL contexts). This set of attributes is supported across WGL, GtkGLArea, and NSOpenGLView. Another place to look is the GL attributes for the Rust glutin library (which I've done a good bit of work on): these are supported across all three backends as well.
Those, along with a MakeCurrent()
(wglMakeCurrent()
/CGLSetCurrentContext()
/gtk_gl_area_make_current()
) API and a rendering callback (that calls wglSwapBuffers()
on Windows and CGLFlushDrawable()
on Mac), would be enough to get started for our purposes :)
Besides all of the above, which helps a lot (thanks!), there's also realization/unrealization and context creation, which I'm also not fully sure about. There's also minimum OpenGL versions and required extensions, which have hit some programmers using GtkGLArea before.
Should OpenGL areas be scrollable? I want the uiOpenGLArea to be as orthogonal to uiArea as possible, even using much of the same code.
As far as realization/unrealization, if I'm understanding you correctly, I believe all you need to do is call the platform specific version of MakeCurrent()
before the rendering callback. Note that lots of games (and us) will want to be able to call MakeCurrent()
outside of the rendering callback and do our rendering outside of the main loop—obviously this requires a "step" kind of function like the one in #21.
For context creation, WGL and NSOpenGLView both support the full set of attributes; you use wglCreateContext()
for WGL, and for NSOpenGLView you use -[NSOpenGLView initWithFrame:pixelFormat:]
. Note that for me it was actually easier to not use NSOpenGLView and to just use a plain old NSView with a CGL context; NSOpenGLView really doesn't provide much if you're not using Interface Builder.
From a glance, it doesn't look like the GTK stuff provides all of the pixel format attributes that GLX does, which is a nuisance. I guess we'll have to either just omit unsupported pixel formats or drop down to GLX directly.
I personally don't care whether the OpenGL area is scrollable (Servo implements scrolling itself), but if it makes it easier for you I think all UI systems support it.
I suppose having backend-specific OpenGL code for Unix is fine; we'd really only need to support the backends that GTK+ itself supports that aren't Windows and OS X (and possibly also Broadway). Waiting a week for me to switch to 3.10 will help here, but it's not necessary. We can build on tegtkgl or one of its forks (but some are GPL, so we can't use those), or build it from scratch? Whatever you think is best, I suppose :) I'm not fully familiar with OpenGL in desktop applications yet myself.
By realization/unrealization I meant for allocating and deallocating context-specific resources like shaders. I assume on OS X and Windows the context will never change, right?
I'm not actually sure how the GTK GL view deals with realization and unrealization. In general, if you use the GLX API (or something that wraps it) then you can assume your context will stay put, just as on Windows and Mac it will.
The GTK+ GL API ties a GL context to a GdkWindow; if something causes a widget's GdkWindow to change (for instance, moving a widget from one GtkWindow to another) then the context will need to be re-realized. If using GLX directly makes this unnecessary then I suppose we can just go ahead and implement it ourselves. Still curious about how Wayland will work...
I guess you can get started now if you'd like :) I'll probably merge in uiMainStep() or similar later today.
Does what I said sound fine? I added uiMainStep()
in the meantime.
Yup, sounds good :) I'm not sure how much time I'll have to work on this in the near term, so feel free to take it if you'd like.
I've started on this: http://github.com/pcwalton/libui/tree/gl
Tasks:
- [x] Declare the basic interface.
- [x] Write an example.
- [x] Implement basic functionality on Mac.
- [x] Implement basic functionality on Linux.
- [ ] Implement basic functionality on Windows.
- [x] Unify the interface with
uiArea
to allow for event handling, etc. - [x] Unify the interface per above on Mac.
- [x] Unify the interface per above on Linux.
- [ ] Unify the interface per above on Windows.
- [x] Add support for an
InitGL
callback per request on Mac. - [x] Add support for an
InitGL
callback per request on Linux. - [ ] Improve the example to show animation, etc.
For unification, I was thinking of having a uiAreaEventHandler with just the event handler interface, that both uiAreaHandler and uiOpenGLAreaHandler (if that one is needed) derive from in the same COM-like way uiDarwinControl derives from uiControl.
On the backend, the area event handling code would be split and a uiAreaEventState object would be used to handle events. These would be accessible via functions on GTK+, a BOOL handlmessage(HWND, UINT, WPARAM, LPARAM, LRESULT *)
type thing on Windows, and an Objective-C class that implements the requisite methods on OS X. Each uiArea would have one of these and delegate their input handling work to that helper object.
Excellent, that sounds totally doable.
What branch is this on again? I forgot already.
The gl
branch.
Looks good to me so far :) If you want to merge it now, all that would need to be changed is the build system setup. Unless you want to wait for the Windows support?
I'm working on Windows right now.
I have Windows support via WGL drafted and am debugging it now.
Cool. I'm working on the uiGrid layout control; I can start merging other things once I finish that up.
Great work so far, I have been following the progress closely, because OpenGL support would be mandatory, if I wanted to replace the current GUI system with libui to support other platforms.
One question that has arisen though is, whether rendering in a background thread is possible? I noticed MakeCurrent
is exposed, so in theory everything is in place, but are there any known limitations in regards to threading?
On OS X CVDisplayLink I believe is the recommended way to use OpenGL, and that runs in a separate thread.
I don't like CVDisplayLink much: it doesn't synchronize to the vertical retrace, only to the vertical retrace interval. It's the equivalent of setting a kernel timer for 60 Hz—in fact, that's what it does (assuming your monitor refresh rate is 60 Hz). The result is that CVDisplayLink doesn't relieve you of the need to set an appropriate swap interval and enable vsync. And if you do set an appropriate swap interval and block in CGLFlushDrawable, then there's usually no need to use CVDisplayLink.
To reiterate somehow: Sorry, if I didn't made myself clear. I meant users being able to use rendering threads with libui rather than libui using a rendering thread. As I mentioned MakeCurrent
is there and basically all you need, but I wanted to know whether there are any limitations regarding threading and safety of libui and/or specific GUI backends, e.g. is SwapBuffers
thread-safe?
uiOpenGLAreaMakeCurrent
is guaranteed to be thread-safe in that it can be called from a thread other than the thread you created the area on, but a context can only belong to one thread at a time. I believe you can also call uiOpenGLAreaSwapBuffers
from any thread that the context is current for, though I would need to double-check this.
Quick updates:
- uiArea scrolling sizes are now int
- uiMouseEvent Down, Up, and Count are also now int
(as per #25)
Any progress? :)
Sorry, haven't had a lot of time for this lately…
Any update?