Common GL Context Management Adapter

This a new thread to discuss what might need to be done to get a common GL context management system in place.

There are four issues:

  1. Modularisation

This is less of an issue for LWJGL as we have almost no integration with anything else. JOGL has some crazy stuff going on under the hood but it largely seems to be split up along the lines of context management and then the separate autogenerated GL API. Is there scope to break JOGL into two main modules; context management, and the GL API, so that they can be built separately and used independently?

  1. Requirements

Need to define precisely what the adapter needs to accomplish in terms of context management. This involves looking at a few use cases and picking a solution that works simply for all of them.

  1. Definition of an API

Which I believe should simply be in terms of a single interface, and therefore as absolutely lightweight as possible. But that’s open for discussion :wink:

  1. Namespace

We really, really, ideally would have things like this in a javax.awt.opengl package but the namespace is reserved by Beelzebub. And the truest reason I suggested org.lwjgl.opengl as the package is because it’s my baby. But there’s another good reason for it living there, in that because it’s a dot org namespace and has no commercial entity giving its blessings it’s far more neutral than java.net, and lives its own independent life away from political machinations. Your thoughts?

Plus of course anything else you can think of.

Cas :slight_smile:

[quote]2. Requirements

Need to define precisely what the adapter needs to accomplish in terms of context management. This involves looking at a few use cases and picking a solution that works simply for all of them.
[/quote]
The only thing I notice in your current API suggestion that’s missing is the problem of multiple contexts. Not an issue with LWJGL, but certainly an issue with everyone else. I guess you need a unique ID generated somewhere, or the window/context handle.

[quote]4. Namespace

We really, really, ideally would have things like this in a javax.awt.opengl package but the namespace is reserved by Beelzebub. And the truest reason I suggested org.lwjgl.opengl as the package is because it’s my baby. But there’s another good reason for it living there, in that because it’s a dot org namespace and has no commercial entity giving its blessings it’s far more neutral than java.net, and lives its own independent life away from political machinations. Your thoughts?
[/quote]
Nope, this shouldn’t exist anywhere in the LWJGL namespace - that’s not fair on the JoGL guys, even if it is your idea. :wink: I agree, however, that a dot-org is preferable to java.net.

It may seem a silly suggestion, but we’re all sitting on a dot-org that is being completely ignored at the moment… java-gaming.org. These OpenGL bindings aren’t restricted to games, but as the entire community is here it seems appropiate to me. Therefore I suggest:

org.javagaming.opengl

[quote]It may seem a silly suggestion, but we’re all sitting on a dot-org that is being completely ignored at the moment… java-gaming.org. These OpenGL bindings aren’t restricted to games, but as the entire community is here it seems appropiate to me. Therefore I suggest:

org.javagaming.opengl
[/quote]
200% following that, even if the javagaming may suggest limited domain only applied to gaming.

[quote] The only thing I notice in your current API suggestion that’s missing is the problem of multiple contexts. Not an issue with LWJGL, but certainly an issue with everyone else. I guess you need a unique ID generated somewhere, or the window/context handle.
[/quote]
yep. It has to be taken in account.

It’s taking a way better road. I like that.

We’re on top of the multiple contexts problem already. We do in fact have multiple contexts already in LWJGL - Pbuffers - so we were already dealing with them in a simplistic fashion. What we haven’t yet sorted out is how to deal with the fact that extension availability and even function pointers are different between contexts.

I propose that the actual instance of GLContext itself is the unique handle to a context.

Cas :slight_smile:

Hi Cas,

During the weekend I tried to build the initial OpenGL support for my particular port of SWT, SWT-On-Fox (http://swtfox.sf.net).

The good thing for the standard (but still experimental) SWT-OpenGL binding is that they have nicely separated the context management from the pure OpenGL API bindings.

You see, they have this cool thingy, org.eclipse.swt.opengl.GLContext, which has a constructor that takes any SWT control or pixmap. If you call setCurrent() on this, you of course redirect the OpenGL rendering to the control/pixmap passed on the GLContext constructor.

(Pretty nice solution, compared to GLCanvas or something of the sort, isn’t it?)

So I implemented this class in terms of the underlying toolkit (Fox - which has platform independent abstractions for GLX & WGL).

Then I tried to use LWJGL (latest CVS surface) to call into OpenGL, because SWT’s OpenGL binding supports only GL1.1 and here’s the problem: contrary to your claims, you lazily load the OpenGL API functions when Window.create() is called, thus tying the OpenGL API bindings to the LWJGL-specific context management class (Window).

I tried to separate the two (extgl_Open/Initialize/Close from Window.nCreate) but it is pretty hard.

Do you plan to do this separation for 0.9?
Also, as far as I remember, there was some guy (fbi or something?) that did a nonstandard LWJGL-SWT binding (GLCanvas based).
Can you point me to his sources, because the link on puppygames.com forums doesn’t work and his sources are not in LWJGL CVS.

I’m not sure I understand this. How can that be? (function pointers are different between contexts)

Lastly, I don’t know how to classify the PBuffers. On one hand, they are not pure OpenGL API, because their creation involves GLX/WGL, but on the other, they seem like a pure OpenGL thing, because they are neither window nor pixmap/bitmap, i.e. these are not related, at least on the surface, with the windowing system.

Please, execuse me if I’m not making any sense - I’m quite new to OpenGL ;-).

What I’m working on in the CVS right now is getting this exact problem solved. Here’s what the issue is:

When a context is made current, we have no idea how that context sprang into being. It could be in control of a software driver, or it could be a hardware driver, depending on the pixel format of the context.

LWJGL, for simplicity and performance, assumes that there’s only rendering going on in one thread. IMHO JOGL should really work this way too but it’s so insanely complex I haven’t quite figured out what it’s up to yet.

Because we only have one thread in our model of the world we only have one class that needs to keep track of what extensions are enabled in the current context. So when a context is made current, we need to query the GL extensions string and enable or disable all the GL extensions dynamically. This may involve getting new function pointers dynamically as well, and nulling other function pointers.

It’s a bit of a faff but it looks like I’m going to store contexts and their function pointers in a HashMap and maintain a reference to the current context. If the context reference changes we’ll look in the hashmap to see if we’ve encountered that context before and restore all the function pointers etc. Or otherwise we will call a LWJGL “init” at that point. Then all LWJGL code will run correctly from that point onwards.

I’m now wondering whether we actually need the GLContext interface exposed to the outside world at all. After all it is the context management system that actually tells the GL renderers to paint, rather than the GL renderers telling the context manager that they need painting.

In other words, the context is the only thing that is really responsible for making itself current and knowing its size, and the LWJGL client is responsible for detecting context changes at the start of its rendering and doing this init code itself.

Am I making sense??

Cas :slight_smile:

Not sure. (Don’t forget I’m very new to OpenGL. :slight_smile: ) Are you saying, that depending on the context+surface chosen (software rendering into X11 pixmap or hardware rendering into X11 window), you have different extensions available, i.e. your GLQueryExtension()->glGetString() will return different string depending on what type of context is made current for the thread? Now that I think of it, it seems obvious…

If so, then yes, I get it.
I wonder why you don’t have this problem with the pbuffers currently - they are different surfaces from X11 window, yet you don’t seem to requery for extensions & reload all OpenGL pointers when a PBuffer-based context is made current for the thread?

Technically, we haven’t worked around this problem for pbuffers at all - we’re assuming that the driver that gives us a window context is going to give is the same extensions for the pbuffer. Because the pbuffer creation is itself a function of the driver we know that the function pointers are going to be the same but not necessarily whether all the extensions are available. It might be in the spec of pbuffers that they are - maybe Elias or Spasi could help here (I don’t know anything about pbuffers).

Cas :slight_smile:

That’s right- Pbuffer could potentially return different function pointers and/or extensions, but we have simply assumed that not to be the case.

  • elias

I think unless we want to totally kill performance we should assume that a pbuffer created from functions in one context is going to have the same driver and extension availability as the context from whence it spawned. It might actually be buried in the spec that this is actually the case already.

In any case we can probably assume that JOGL makes that assumption too, yes?

So back to the interface question: do we actually need a common interface? Can we get away with simply mandating preconditions for rendering, and get LWJGL component programmers to ensure that before any rendering they check the current context? (It’s a non issue if you’re using LWJGL end-to-end as it takes care of all this stuff for you under the hood)

Cas :slight_smile:

princec-

I doubt very much that anyone will take my suggestions, but here they are nonetheless.

When I rewrote Magician, I eliminated the Java GLContext class. GLComponent has 5 or 6 native methods (e.g. create, destroy, makecurrent, unmakecurrent, swap). All the platform specific stuff is done on the native side. My implementation is now trivial (read: even I can understand it).

(In general, exposing native side stuff in Java is a huge mistake. Those SWT folks are insane.)

My rewrite of Magician doesn’t have a separate Animator class either. Each GLComponent instance just creates its own thread. It’s fast and simple and never ever not once wrong. In other words, in my design, all that makecurrent stuff cannot be wrong.

The autogenerated Java GL interfaces stuff is absolutely gonzo nuts. Take a snapshot of the resulting GL interface and dump the scripts. The rate of change for gl.h, glu.h, extensions, and so forth is glacial. You guys spent a huge amount of time getting that auto stuff just so. I can’t imagine that investment will pay off.

I’m the guy to blame for both GLEventListener and the GL pipeline. I’m still not pleased with the listener interface. Though I did add a parameter for GLDrawable (the event source) which makes some things easier.

I’m thinking of dumping TraceGL, DebugGL, ProfileGL, etc. Now that we have stuff like aspects, profilers, and interactive debuggers, those classes are largely moot. Though I might keep TraceGL a bit longer, because I beefed it up to emit compilable code and I haven’t learned that aspect nonsense (think metaobject protocol from Smalltalk and you’ll have the rough idea) well enough to replace TraceGL yet.

Inspired by extGL, I made my own faux_gl.h and faux_glu.h. I made up some spiffy macros for declaring function pointers and probing extensions, such that the native code still looks like ‘C’ OpenGL code and there’s no dispatch overhead after a function pointer has been resolved. I can’t remember how JOGL does this, but I think it was pretty involved.

I’m thinking of dumping all the gl* methods. There used to be a reason for keeping them. Now it’s moot.

Well. Good luck.

Cheers, Jason Aaron Osgood / Seattle WA

Well… here’s what I’ve got so far in CVS in LWJGL:

The proposed GLContext interface has been deleted - I can’t really see the use of it after all. The GLCaps class has been renamed GLContext, and it’s got a method on it, setContext(Object), which must be called before any rendering occurs in LWJGL.

In other words, when your JOGL GLCanvas is trying to paint itself, and finally gets round to calling the LWJGL “rendering bean”, the application would do:


lwjglbean.setContext(joglContext);
lwjglbean.setBounds(x, y, width, height);
lwjglbean.render();

And a nicely written bean implementation would look something like:


public void render() {
org.lwjgl.opengl.GLContext(joglContext);
GL11.glViewPort(x, y, width, height);
// draw here
}

Looks peachy to me! The version in CVS is not 100% efficient yet. I am about to implement cached function pointers on the native side, which should speed things up no end. As it is, it works, but if you start using multiple contexts, it’s likely to get slow. But then if you’re using multiple contexts, you’ve got it all wrong anyway, and should go back to Game Programming School.

Jason - we’re really happy with how the LWJGL is turning out, design-wise and API wise. We’ve been preparing for JDK1.5 for some time now and everything has been geared for static import. All our GL methods are static - because that’s how they are in C - and that’s why you need to keep the gl* prefix :slight_smile:

You’re quite right about autogen - it is a huge overhead of complexity. I haven’t even got a JOGL application to build yet because I haven’t got the time to figure out how to make it from CVS. Life’s too short for open source :wink:

Cas :slight_smile:

Can anybody help me out here - I would like to build JOGL without a GL class. Or with a GL class, but with no methods in it. How might I go about this?

Cas :slight_smile:

Looks very cool to me! I’ll try the new LWJGL CVS head with SWT tonight.
So basically I have to use my own SWT GLContext, but immediately after calling setCurrent(true) on it, I should also call org.lwjgl.opengl.GLContext.setContext(mySwtContext), to reinitialize the correct GL capabilities & function pointers.

The only thing I don’t like is the new name of this class - GLContext. It is not a context, after all. But I can live with that, I guess… :slight_smile:

Committed for Win32 now, linux & mac to follow sometime this week.

Cas :slight_smile:

Hi Cas,

The new scheme with the GLContext thingy looks nice but unfortunately you haven’t moved the extgl_Open() call from Window.nCreate() to a more appropriate place.

Problem is, I don’t want to create a LWJGL window, ergo, extgl_Open() is not called at all and the foolowing code segfaults:

swtctx.setCurrent(true);
org.lwjgl.opengl.GLContext.useCurrent(swtctx);

… because GLContext.useCurrent() calls extgl_Initialize(), but the handle to the OpenGL shared library is not created yet.

Yep, I saw that a few days ago, it’s being fixed…

  • elias

Fixed now with a lazy creation in extgl_Init. So id extgl_Init is called and we haven’t already called extgl_Open, it now does so.

Cas :slight_smile:

Okay… so anyone have a small sample of how this works so I can try it out? I just changed a bunch of stuff in JOGL for OSX and I want to make sure what you’re proposing works on OSX.

OK, the final fix, hopefully:

glXGetProcAddressARB (I’m testing this on Linux) is not initialized, because extgl_initGLX() which initializes this function pointer is not called at all. The result is that extgl_GetProcAddress() segfaults.

What I did was to place the following code in extgl_GetProcAddress(), just below the #ifdef _X11 macro:
if (glXGetProcAddressARB == NULL)
glXGetProcAddressARB = (glXGetProcAddressARBPROC) dlsym(lib_gl_handle, “glXGetProcAddressARB”);

I think both Win32 & Mac OS versions of extgl_GetProcAddress() don’t need fixing.

Oh, by using this patch I was finally able to render the white square of org.lwjgl.opengl.test.Game in SWT Canvas. :slight_smile: