Hey all,
I'm currently working on the EGL & OpenGL ES bindings for LWJGL 3. It was the largest amount of work left for the 3.0 beta and it's almost done now. But I'm looking for some feedback on some API issues that have been bothering me. I want to get them fixed before the beta, if possible.
It has to do with the *Capabilities classes. In LWJGL 2 we had:
- OpenAL: n/a
- OpenCL: CLCapabilities, CLDeviceCapabilities, CLPlatformCapabilities
- OpenGL: ContextCapabilities
- OpenGL ES: ContextCapabilities
In LWJGL 3 we currently have:
- OpenAL: ALCapabilities, ALCCapabilities
- OpenCL: CLCapabilities
- OpenGL: ContextCapabilities
- OpenGL ES: ?
OpenAL in 3 supports several AL/ALC extensions, so we had to add new capability classes. OpenCL in 3 is not backwards compatible, so it was a chance to reduce complexity; we now have a single class.
My suggestion has two parts:
a) Rename the OpenGL ContextCapabilities to GLCapabilities. OpenGL ES would then have GLESCapabilities and everything will be symmetric with no aliasing. The downside will be that it will break (even more) existing LWJGL 2 code.
b) Replace GLContext GLContext.createFromCurrent() with GLCapabilities GL.createFromCurrent(). LWJGL would then hold the GLCapabilities instance in thread-local state, instead of the GLContext instance. I'd like to do this to decouple the capability instance (which contains the context function pointers, the stuff LWJGL needs to work) from whatever is managing the OpenGL context. The current situation is confusing, because GLFW has context management functions (e.g. glfwMakeContextCurrent(window)) and the GLContext instance has the same functions. It's not clear which ones must be called.
To move a context to another thread, now you'd do:
long window = glfwCreateWindow(...);
...
glfwMakeContextCurrent(window);
GLContext context = GLContext.createFromCurrent();
...
// in another thread
glfwMakeContextCurrent(window);
GL.setCurrent(context); // what does this do? do I have to call context.makeCurrent()?
if ( context.getCapabilities().OpenGL40 ) { ... }
Used concepts: GLFW window/context, GLContext, ContextCapabilities, GL
with the proposed change:
long window = glfwCreateWindow(...);
...
glfwMakeContextCurrent(window);
GLCapabilities caps = GL.createFromCurrent();
...
// in another thread
glfwMakeContextCurrent(window);
GL.setCurrent(caps); // better: we already made the context current, now let LWJGL know
if ( caps.OpenGL40 ) { ... }
Used concepts: GLFW window/context, GLCapabilities, GL. So we have to do deal with one less concept. The GLContext class would then only be useful if someone did custom context management without GLFW, via WGL/GLX/CGL. We could also just remove it altogether.
The proposed change is not only about usability and aesthetics. You can actually create and manage OpenGL contexts using EGL. Right now the GL thread-local state is coupled with the GLContext class. In order to create a "GLContextEGL" implementation, the two packages (org.lwjgl.egl and org.lwjgl.opengl) will be coupled as well. This is the kind of bad design we had to deal with in LWJGL 2 and I'd like to avoid that. If the GL only knows about GLCapabilities, that GLCapabilities instance can be created externally, without infecting anything.
I'd love to hear any thoughts on the above.