I am using JOGL (2.4.0-rc-20210111) together with VTK 9.0.1.
In particular, I am using the GLCanvas component embedded into VTK's vtkJoglCanvasComponent.
My application works quite fine (both on Windows and on macOS - with Java 8 JRE).
However, I am facing a strange sporadic crash when I invoke a function in my application which removes the GLCanvas-based GUI panel from its container, and then adds it to a newly-created JFrame (it's a kind of "full screen mode" function of my application). This crash seems to happen only on Windows, while I've been unable to reproduce it on macOS so far.
In VTK's vtkJoglCanvasComponent class, there is a GLEventListener, whose init() callback gets called both upon initial display of the GLCanvas-based GUI panel, and then again when the GLCanvas-based GUI panel is added to the newly-created JFrame. Between the two init() calls, there is a dispose() call which is invoked when the GLCanvas-based GUI panel is removed form its original container.
Upon first invocation of the init() callback, if I call 'drawable.getContext()', I obtain an OpenGL 4.6 context, and everything works like a charm.
On the other side, upon the second invocation of the init() callback (after addition of the GLCanvas to the new JFrame), **SOMETIMES** calling 'drawable.getContext()', I obtain an OpenGL 1.1 context. When this happens, then VTK crashes, because VTK 9 requires at least OpenGL 3.2 in order to work properly.
I know that my description of the problem is quite limited, but can you guess why I **SOMETIMES** get an OpenGL 1.1 context upon init() with my GLCanvas-based panel?
This happens on many different Windows PCs with many different display adapters / drivers, when I invoke this "full screen mode" feature in my application (which works as described above: remove GLCanvas from its container --> create a new JFrame --> add the GLCanvas to the new JFrame).
It may be something in VTK, but I was just wondering if you could guess where the problem might be, and maybe point us in the correct direction.
Also, let me mention that for some reason this issue seems to appear more frequently with Jetbrain's Java 8 JRE, even though I have had a few occurrences of the issue even with Adopt OpenJDK Java 8 JRE.
GLCanvas glCanvas = new GLCanvas(new GLCapabilities(GLProfile.getMaximum(true)));
In fact, when the GLCanvas-based VTK component is initially used in my application, it ALWAYS works fine. Once the GLCanvas-based panel is displayed for the first time in my application, GLEventListener.init() is called inside vtkAbstractJoglComponent.java (see https://github.com/Kitware/VTK/blob/master/Wrapping/Java/vtk/rendering/jogl/vtkAbstractJoglComponent.java). At this point, the "GLContext ctx" variable defined inside the GLEventListener.init() always corresponds with an OpenGL 4.6 context, as logged by a "ctx.toString()" call. So far, so good.
However, when a "full screen mode" function is invoked in my application, sometimes my application crashes. Here is what this "full screen mode" function does:
3) Add the existing GLCanvas-based component (i.e., the same GLCanvas which was created at point 1 above, hence apparently using the same GLCapabilities) to this newly-created JFrame
--> GLEventListener.init() is invoked again inside vtkAbstractJoglComponent.java
However, this time, if I invoke "ctx.toString()" inside the init() callback, **SOMETIMES** I get an OpenGL 1.1 context, and when this happens, my application crashes, because VTK crashes, due to insufficient OpenGL context.
Do you have an explanation as to why the second GLEventListener.init() made on the same GLCanvas instance (following to removal of the panel from its container + add of the panel to new JFrame) **SOMETIMES** returns an OpenGL 1.1 context?
I was suspecting some threading issue, but I've verified and I am sure that all init() and all dispose() calls are always done on the same thread, which is the EDT (SwingUtilities.isEventDispatcherThread() always returns 'true' in these callbacks).
Any hint would be greatly appreciated.
Thanks in advance for your feedback.
Actually, I spent several hours in an effort to create a self-contained test case, demonstrating the crash outside my own VTK-based application, but so far I've been unable to do so.
So, for now, the question is: can you imagine any reason why JOGL's GLCanvas may correctly return a "correct" OpenGL 4.6 GLContext in my application's init() callback [calling drawable.getContext()], and then at a certain point, for the same GLCanvas, with the same GLProfile and the same GLCapabilities, return an "incorrect" OpenGL 1.1 GLContext at a later invocation of my application's init() callback [calling drawable.getContext()]?
May an incomplete / incorrect release of some OpenGL resources cause this behavior in your opinion? May some threading issues (I don't see which ones, since my init() always executes on the EDT...) cause a similar behavior? May creation of a new "root" JFrame somehow cause a similar behavior?
Sorry for asking such generic questions, but I am looking for some guidance about where to look to build a test case which indeed is able to reproduce the issue I am experiencing inside my application.
I am looking forward to hearing from you.
Thanks and best regards,
do you think the GraphicsConfiguration upon which I create my "root" JFrame (i.e., the one finally containing my GLCanvas-based panel) may make a difference with respect to the GLContext that GLCanvas's init() callback is able to return?
My approach in creating JFrames in my application is that I identify the GraphicsDevice corresponding to my target screen (in case of a multi-screen environment), then I use this GraphicsConfiguration:
If I invoke myTargetScreenDev.getConfigurations(), I obtain 6 different GraphicsConfiguration's for my target GraphicsDevice. However, just inspecting these 6 different instances, I am unable to tell what is different in each instance.
Do you think it is worth investigating more about this, or creating my root JFrame on myTargetScreenDev.getDefaultConfiguration() is safe enough for JOGL purposes?
Thanks in advance for your comments.
I had read your post before, but my problem seems to be a bit different:
In fact, my application's vtkJoglCanvasComponent, in turn using JOGL's GLCanvas, is "sometimes" picking up an OpenGL 1.1 GLContext, and in those cases VTK crashes. The GLProfile seems to be always correct.
One question for the JOGL guys: I've noticed that vtkJoglCanvasComponent creates GLCanvas like this:
GLCanvas joglCanvas = new GLCanvas(new GLCapabilities(GLProfile.getMaximum(true)));
As far as I can see, VTK doesn't pass any GraphicsDevice to GLCanvas.
So, in this situation, will the GraphicsConfiguration upon which I create my root JFrame (i.e., the JFrame containing the GLCanvas containers, hence in turn also the GLCanvas itself) be relevant for the capabilities of the GLCanvas in terms of the GLContext it will be able to create?
Since my issue happens when I create a new root JFrame for my GLCanvas, I have the feeling the involved GraphicsConfigurations may have an influence.
Please notice that on my test PC I have multiple screens. However, my crash also happens on other single-screen PCs I have tested.
This test program simply creates a JFrame on the default GraphicsConfiguration for my first screen, and adds an empty GLCanvas to this JFrame.
While creating the GUI, this test program enumerates all GraphicsDevice's available on my PC, and for each GraphicsDevice, all available GraphicsConfigurations.
Finally, in the init() callback of my GLEventListener, I simply print the GLVersion of my drawable.getContext().
On my Windows 10 development PC, which has two screens attached to a NVIDIA GeForce GTX 1060 6 GB graphics adapter, here is what I get on the stdout:
As you can see, with this system property, first of all I get 6 different GraphicsConfiguration per each screen (I am uncertain why, but this certainly doesn't depend on JOGL), and then the GLContext I get in my init() callback is an OpenGL 1.1 context (and I believe this depends on JOGL and shouldn't happen)!
Even stranger, if in my test case code I simply remove the call to GraphicsDevice.getConfigurations() (but always passing "-Dsun.java2d.noddraw=true"), then again I am getting a correct OpenGL 4.6 context. Here is the output I obtain in this last test configuration:
Contact Sven for the financial contribution, yes it may help. I think that disabling DirectDraw in Java2D seems to be the culprit but I don't see precisely why right now, maybe Java2D tries to use its OpenGL pipeline in this case and something bad happens (you could disable it too to force Java2D to use its software renderer). Your reproducer is very helpful.
thank you for your reply.
I have just written an email to Sven through this Forum. I hope he gets it.
In the meanwhile, if you discover something on the issue, please let me know.
The strangest thing is that somehow the presence of the .getConfigurations() call is making a difference for JOGL. It would be very interesting to understand why.