is there any documentation of how to create a pbuffer with jogl?
i cant get it working… i have some exceptions in the kind glActiveTexture not supported or Not implemented yet. sounds like the creation of the pbuffer is not done the right way, but i have no clue of what is the way… there is too much things in the nvidia sample to understand how to do a new pbuffer. any sample with only pbuffer?
oh and the init in th pbufferlistener class is never called.
GLCapabilities caps = new GLCapabilities();
caps.setDoubleBuffered(false);
pbuffer = dr.createOffscreenDrawable(caps, 1024, 1024);
pbuffer.addGLEventListener(new GLpBuffer());
shouldnt it happen there?
You probably need to call display() on the parent heavyweight drawable until the GLPbuffer’s isInitialized() method returns true.
isInitialized() always returns false to me, regardless of how often I call display on the glcanvas. =/
(this is mentioned in my “pbuffers cause crash to desktop on ati” bug report)
Is the parent GLCanvas visible? That is, is it in a window that has been shown? It needs to be. If you need to have a completely invisible parent GLCanvas, put it in an undecorated Frame that is sized to (0, 0). Or have you done this already? Is your code working on other vendors’ cards?
Source code here: http://www.wurmonline.com/newclient/PBufferTest.java
The line is commented out about 33% down.
Always false. GeForce TI4800, latest jogl build.
I haven’t tested on other cards.
I get a CTD here on my Radeon 9700 PRO.
Current Java thread:
at net.java.games.jogl.impl.windows.WGL.wglCreateContext(Native Method)
at net.java.games.jogl.impl.windows.WindowsPbufferGLContext.create(Windo
wsPbufferGLContext.java:388)
at net.java.games.jogl.impl.windows.WindowsGLContext.makeCurrent(Windows
GLContext.java:133)
- locked <0x1052a168> (a net.java.games.jogl.impl.windows.WindowsPbuffer
GLContext)
at net.java.games.jogl.impl.windows.WindowsPbufferGLContext.makeCurrent(
WindowsPbufferGLContext.java:314)
- locked <0x1052a168> (a net.java.games.jogl.impl.windows.WindowsPbuffer
GLContext)
I’ll have a quick look at the code to see what you’re doing wrong.
Heh, that was quick.
Right, number of things that I’ve noticed:
-
You set frame visible after you’ve done everything else. In order for JOGL to remain sane, you must make the frame visible first, and then create the main canvas, add the main canvas to the frame then add the listener.
-
You’re creating the pBuffer before the canvas has even had a chance to initialise. You need to wait for that init() callback on the canvas before creating the pBuffer. JOGL has issues with trying to create stuff before that initial canvas init() call is finished.
-
You are only creating and calling a swing component in the middle of a GL drawing callback. Very, very bad thing to do. Inside the drawing loop for GL, you should do nothing else except issue gl commands. Making calls to external rendering threads is just asking for a crash.
-
I’m not entirely sure your little render thread is valid way of telling GL to actually draw.
-
You’ve told the pbuffer to not use double buffering. This causes JOGL to have a fit. pBuffers are, by definition, not double buffered, and setting an explicit set of capabilities to turn it off always seems to get JOGL confused. I don’t know why it does, as it should just completely ignore that part, however it does and I’ve been bitten by it a few times.
Now, if you modify the code to move frame.setVisible() to immediately after frame.setSize() everything works and now JOGL bitches about not being able to find the required capabilities, which is due to point 4. Fixing up the timing issue of the canvas/pbuffer creation was going to take up a lot more time than I have to spend on it, so you’ll need to look into that yourself. However, you should submit the file as is as a bug to the issue tracker as it caused an immediate CTD on the ATI cards, which it really should not have.
[quote]1) You set frame visible after you’ve done everything else. In order for JOGL to remain sane, you must make the frame visible first, and then create the main canvas, add the main canvas to the frame then add the listener.
- You’re creating the pBuffer before the canvas has even had a chance to initialise. You need to wait for that init() callback on the canvas before creating the pBuffer. JOGL has issues with trying to create stuff before that initial canvas init() call is finished.
[/quote]
Rightie-o, that would explain a lot. Thanks.
[quote]3) You are only creating and calling a swing component in the middle of a GL drawing callback. Very, very bad thing to do. Inside the drawing loop for GL, you should do nothing else except issue gl commands. Making calls to external rendering threads is just asking for a crash.
[/quote]
The only swing call I can see is the debug JOptionPane.showMessageDialog that pops up when (one of) the error(s) occur(s). Surely that can’t trigger the crash that causes itself to appear.
[quote]4) I’m not entirely sure your little render thread is valid way of telling GL to actually draw.
[/quote]
Mind telling me what’s wrong with it?
[quote]5) You’ve told the pbuffer to not use double buffering. This causes JOGL to have a fit. pBuffers are, by definition, not double buffered, and setting an explicit set of capabilities to turn it off always seems to get JOGL confused. I don’t know why it does, as it should just completely ignore that part, however it does and I’ve been bitten by it a few times.
[/quote]
I did not know that. =D
[quote] The only swing call I can see is the debug JOptionPane.showMessageDialog that pops up when (one of) the error(s) occur(s). Surely that can’t trigger the crash that causes itself to appear.
[/quote]
Yup, that’s the one. At the very least you’re going to end up with a deadlock in the middle of your code or some oddball apparently non-sensical, exception from the internals of JOGL. Java3D and JMF also suffer from exactly the same problem. UI code and rendering interaction code have to remain completely separate. Swing does it’s own stuff under the covers that seems to have problems playing nice with anyone else that uses heavyweight canvases and their own separate updating threads.
while(true) loops without a surrounding thread are always dodgy coding practice. JOGL does not have to directly just display when you call it. It’s a hint to tell JOGL to repaint. That little section is very likely going to cause an extremely fast infinite loop that consumes 100% CPU. If you want to directly control the render framerate then using the Animator class or your own separate render thread is the way to go.
[quote]Yup, that’s the one. At the very least you’re going to end up with a deadlock in the middle of your code or some oddball apparently non-sensical, exception from the internals of JOGL. Java3D and JMF also suffer from exactly the same problem. UI code and rendering interaction code have to remain completely separate. Swing does it’s own stuff under the covers that seems to have problems playing nice with anyone else that uses heavyweight canvases and their own separate updating threads.
[/quote]
As I said, that window only pops up when a pbuffer error occurs. That popup cannot cause itself to pop up.
[quote]while(true) loops without a surrounding thread are always dodgy coding practice. JOGL does not have to directly just display when you call it. It’s a hint to tell JOGL to repaint. That little section is very likely going to cause an extremely fast infinite loop that consumes 100% CPU. If you want to directly control the render framerate then using the Animator class or your own separate render thread is the way to go.
[/quote]
Wrong.
From the Animator source code:
while (!shouldStop) {
noException = false;
drawable.display();
noException = true;
}
From the GLDrawable javadoc:
public void display()
Causes OpenGL rendering to be performed for this GLDrawable by calling GLEventListener.display(net.java.games.jogl.GLDrawable) for all registered GLEventListeners.
It’s not wrong. Have a look at what is around the animator class. There’s a full Thread, as well as a call to setRenderingThread() and setNoAutoRedrawMode(). That is what allows you to be able to make that other call in an infinite loop. First, understand the code you are quoting before trying to make a point :o
[quote]It’s not wrong.
[/quote]
Yes, it is.
[quote]Have a look at what is around the animator class. There’s a full Thread,
[/quote]
The thread that calls the main method is also a full Thread. Why would it be better to spawn a new thread and let the first thread die, other than purely for style points? (remember that this is a test case)
[quote]as well as a call to setRenderingThread()
[/quote]
From the javadoc for said method:
“Setting up the rendering thread is not required but enables the system to perform additional optimizations, in particular when the application requires control over the rendering loop.”
And a bit further down:
“NOTE: Currently this routine is only advisory, which means that on some platforms the underlying optimizations are disabled and setting the rendering thread has no effect. Applications should not rely on setRenderingThread to prevent rendering from other threads.”
[quote]and setNoAutoRedrawMode().
[/quote]
From the javadoc for said method:
“Its sole purpose is to avoid deadlocks that are unfortunately all too easy to run into when both animating a drawable from a given thread as well as having updates performed by the AWT event thread (repaints, etc.).”
[quote]That is what allows you to be able to make that other call in an infinite loop.
[/quote]
Wrong, setRenderingThread() is an optimisation, and setNoAutoRedrawMode() is a hack to prevent deadlocks.
These two methods are very useful, but they only work well when you’re calling display() frequently, eg by using a while(true) loop. (note that they’re in no way a requirement for doing so)
[quote]First, understand the code you are quoting before trying to make a point :o
[/quote]
And I would advice you to read up on the javadocs. There really is a lot of useful information in there.
Actually, I think that the javadoc is wrong in this case. It seems that setRenderingThread method is not only an optimization hint. At least, I’ve had problems rendering from the current thread, if I haven’t called the method to explicitly set the rendering thread. I’ve experienced these problems on ATI cards (haven’t got an NVidia card). This problem can be seen in the following demo:
http://www.g0dmode.com/javastuff/jogl-simpledemo.zip
…on line 28 there’s a call to setRenderingThread. Without the call the demo will not work (tested on ATI 9600). Have I missed something or is the call really necessary?
Markus, not sure where to start, but it’s fairly clear that you don’t understand what either pieces of code are doing. You read the individual method documentation, but you are ignoring the global picture they are painting. Not only have I read the documentation many times, but I’ve also implemented a heap of applications using it.
JOGL operates in one of two modes when rendering. Both of them require calling the display() method in order to get a repaint action happening (GLEventListener.display() callback).
In the first case, which is that presented by the original poster’s code, is an advisory request. There are many possible threads that can call display(). The canvas is not required to immediately initiate a repaint. In this mode, calling display() is a non-blocking method. It puts a request on the queue and returns immediately. Internally JOGL will (potentially) then combine a collection of repaint requests from both user land and AWT’s requirements and turn them into a single call to the listener’s display callback. If it is in the middle of a repaint for an earlier request, another will be queued up and immediately called once the current repaint is finished. This is what the original poster’s code does. It goes into an infinite loop that doesn’t have any blocking in it. Apart from the Thread.yield() call, there is no other way of stopping that loop from executing as fast as possible. There is no other thread or Runnable in the code. Since there is no other thread, it is quite possible to completely starve JOGL from getting any CPU cycles to do redrawing (Which is what is exactly happening on my machine if I remove the pBuffer code and just use the main canvas). Nothing appears on screen because the original code is not doing anything to give any other piece of the application cycles to do the drawing with. That’s why it is dodgy.
In the second case, which is what the Animator class implements, is a strictly controlled repaint cycle that is locked to a single thread. In this mode, calling display() is a blocking call. display() does not return until the listener’s callback method has finished. Any other thread that wants to repaint the canvas is told to go away, particularly AWT’s own repainting (the setNoAutoRedraw() part). Now, because there is a blocking part of the code, cycles are available to repaint with. A separate thread makes sure that this can happen only at the times required etc.
Now, onto your specific points:
Because there is no way of getting CPU cycles to the JOGL to do the repainting with. At an absolute minimum, there should be a Thread.sleep() in there for a few milliseconds to that other threads may take up the CPU (Thread.yield() is almost never good enough).
An optimisation that, unless used, results in an application that can’t even draw it’s own piece of the window. It’s only an optimisation when it actually does something faster (or less memory) than before. In this case, unless it is used, the application is non-functional. That’s not an optimisation in my book.
If it was such an optimisation, why does every single demostration you see of JOGL use the Animator class or a custom-coded equivalent? Surely it is not because that these method usages are required in order to have a functional demo? That’s not an optimisation at all from any direction that you look at it from.
for the markus code example for pbuffer.
Exception in thread “main” net.java.games.jogl.GLException: Method “wglChoosePix
elFormatARB” not available…
ok… Why is it trying to call the ARB function? and even the samples in jogl-demo using pbuffer works on this graphic card. something weird here.
I tried changing the order of my setup to go along with what Mithrandir said, set Frame to visible, create glcanvas, add canvas to frame, add gleventlistener to canvas. Before my order was like this: create glcanvas, add listener to canvas, add canvas to frame, make frame visible. It worked before but now my init(GLDrawable) method never gets called… what could I be doing wrong?
Well… If you add the listener to the canvas as the last thing, it will not be notified about the initialization of the canvas. Try adding the listener before adding the canvas to the frame.
hmm, that would make sense, but its still not working:
frame = new JFrame();
frame.setBackground(Color.BLACK);
frame.setIgnoreRepaint(true);
frame.setBounds(screenWidth/2-displayWidth/2, screenHeight/2-displayHeight/2, displayWidth, displayHeight);
frame.setVisible(true); //1: set frame visible
GLCapabilities caps = new GLCapabilities();
caps.setHardwareAccelerated(true);
caps.setDoubleBuffered(true);
canvas = GLDrawableFactory.getFactory().createGLCanvas(caps); //2: create canvas
canvas.setSize(size);
canvas.setBackground(Color.BLACK);
canvas.setIgnoreRepaint(true);
canvas.addGLEventListener(mainClass); //3: add listener
frame.getContentPane().add(canvas); //4: add to frame
frame.pack();
there something I’m missing still?
You won’t get an init() until you start calling display() on the GLDrawable. Stick an Animator in there and you’ll see it come up. The order I gave you is the only one that seems to work with any reliability. You really do need to add the canvas to the frame first before doing anything else, including adding listeners otherwise at least half the time you won’t get the callbacks. You’re not going to get init() calls until you actually try to display something, so make sure you have that in your code next.