Rules for sharing context between GLJPanels?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Rules for sharing context between GLJPanels?

Marian Schedenig
I'm working on a level editor which I originally wrote with plain Java2D and later converted to JOGL.

The original Java2D implementation had several JPanels, a big one for actually editing a level and many small ones as level previews. Each panel was connected to the same instance of my ResourceManager class which held all the images (now textures) and knew how to paint itself when an update was necessary.

When I switched my game to JOGL, I quick-and-dirtily turned each of these panels into a GLJPanel, with its own ResourceManager (because instantiating the ResourceManager required a GL context). Aside from certainly wasting a lot of resources, this also makes things horribly slow when, while scrolling through the list of level previews, each panel that's displayed for the first time reads and initialises its textures.

I've therefore been trying to switch to a shared GL context which would be the home of the ResourceManager. It's been mostly trial and error and Google searches (the link on the GLJPanel Javadoc page that would presumably provide more info doesn't exist: https://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/javax/spec-overview.html#SHARING).

Before creating any of my panels, I create an offscreen AutoDrawable and call display() on it. In its init() event callback, I initialise my ResourceManager. I then create my panels and set this AutoDrawable as the shared AutoDrawable. But my reshape() and display() method throw exceptions when they actually access GL objects, like this one:

Exception in thread "AWT-EventQueue-0" javax.media.opengl.GLException: Caught GLException: This GL object is being incorrectly used with a different GLContext than that which created it on thread AWT-EventQueue-0
	at javax.media.opengl.GLException.newGLException(GLException.java:75)
	at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1318)
	at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1138)
	at javax.media.opengl.awt.GLJPanel$OffscreenBackend.doPaintComponent(GLJPanel.java:1922)
	at javax.media.opengl.awt.GLJPanel.paintComponent(GLJPanel.java:559)
	at javax.swing.JComponent.paint(JComponent.java:1045)
[...]
Caused by: javax.media.opengl.GLException: This GL object is being incorrectly used with a different GLContext than that which created it
	at javax.media.opengl.DebugGL4bc.checkContext(DebugGL4bc.java:29477)
	at javax.media.opengl.DebugGL4bc.glUseProgram(DebugGL4bc.java:24132)

I do all my GL access in GLEventListener callbacks. The threads are indeed different - the offscreen drawable's init() runs on a non-AWT thread, and all the actual drawing calls seem to run on AWT threads.

I've tried to reproduce the issue with a simple test application. It creates a JFrame, initialises an offscreen drawable and two simple shaders, then creates two GLJPanels and sets the shared drawable. Each panel's display() method calls glUseProgram() and clears the panel with a different colour. But all this runs flawlessly.

The threads in the test tool are similar to those in the non-working editor: Non-AWT thread when initialising my resources, AWT thread for actual drawing operations.

Clearly I'm violating some rule about context sharing I'm not aware of. But so far I've been unable to even figure out where my broken editor significantly differs from my test tool.
Reply | Threaded
Open this post in threaded view
|

Re: Rules for sharing context between GLJPanels?

Sven Gothel
Administrator
On 08/28/2014 11:23 PM, Marian Schedenig [via jogamp] wrote:

> I'm working on a level editor which I originally wrote with plain Java2D and
> later converted to JOGL.
>
> The original Java2D implementation had several JPanels, a big one for actually
> editing a level and many small ones as level previews. Each panel was
> connected to the same instance of my ResourceManager class which held all the
> images (now textures) and knew how to paint itself when an update was necessary.
>
> When I switched my game to JOGL, I quick-and-dirtily turned each of these
> panels into a GLJPanel, with its own ResourceManager (because instantiating
> the ResourceManager required a GL context). Aside from certainly wasting a lot
> of resources, this also makes things horribly slow when, while scrolling
> through the list of level previews, each panel that's displayed for the first
> time reads and initialises its textures.
>
> I've therefore been trying to switch to a shared GL context which would be the
> home of the ResourceManager. It's been mostly trial and error and Google
> searches (the link on the GLJPanel Javadoc page that would presumably provide
> more info doesn't exist:
> https://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/javax/spec-overview.html#SHARING).
Try GLSharedContextSetter
  <http://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/javax/media/opengl/GLSharedContextSetter.html>

as mentioned in GLJPanel and other implementations itself
  <http://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/javax/media/opengl/awt/GLJPanel.html>

we also mentioned it in our SIGGRAPH 2014 BOF.

You may also add jogl-test.jar and it's sources jogl-test-java-src.zip
to your IDE and see the unit tests by GLSharedContextSetter methods calltree.

Hope this helps.

~Sven


signature.asc (828 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Rules for sharing context between GLJPanels?

Sven Gothel
Administrator
In reply to this post by Marian Schedenig
On 08/28/2014 11:23 PM, Marian Schedenig [via jogamp] wrote:

> more info doesn't exist:
> https://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/javax/spec-overview.html#SHARING).

thx .. fixed in git repo, will be avail w/ 2.2.1

I also reviewed the API doc of GLSharedContextSetter and fixed/clarified language.

~Sven


signature.asc (828 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Rules for sharing context between GLJPanels?

Marian Schedenig
Thanks for the corrections.

I was already using GLSharedContextSetter via GLJPanel. Turns out the problem was a stupid mistake buried in my core code. I have a common class to encapsulate and handle all my drawing operations. I initialise that with the GL instance from my JOGL context. What I didn't think of was that when using multiple panels with multiple GL contexts, that GL instance was changing - hence the drawing operations still using the GL from a different context.

I now always set the current GL instance before painting a panel, and it works fine.

The only problem that's left is that my textures (loaded from the shared dummy auto drawable) lack alpha, even though I list an 8/8/8/8 colour configuration in my requested capabilities. But that's probably also just some remaining bug somewhere in my own code.
Reply | Threaded
Open this post in threaded view
|

Re: Rules for sharing context between GLJPanels?

gouessej
Administrator
Actually, you should never store the GL instance.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Rules for sharing context between GLJPanels?

Marian Schedenig
Gotcha. It works fine in the actual game, where I only have a single GL context, on all platforms I've tried (Windows, Mac, Linux), also survives resizes and fullscreen toggles just fine. But I'll make sure to update my drawing instance's GL pointer each frame just to be safe.
Reply | Threaded
Open this post in threaded view
|

Re: Rules for sharing context between GLJPanels?

gouessej
Administrator
A small change in your own code or in our implementation might break that, you shouldn't rely on this kind of assumption. It works now, it might no longer work in several months. Personally, I wasted a lot of time with invalidated GL instances, I prefer manipulating them only in some software layers (as few as possible), I never pass them, I do nothing to encourage other contributors to store them.

In practice, you don't see several instances now but in theory, we don't guarantee that you'll get the same GL instance between 2 successive GLEventListener.display() calls.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Rules for sharing context between GLJPanels?

Marian Schedenig
That's what I meant. I now set a new link to the instance from the callback's drawable parameter whenever display() or reshape() is called.