Bug 841

Summary: GLJPanel "lagging" by one frame.
Product: [JogAmp] Jogl Reporter: Sven Gothel <sgothel>
Component: awtAssignee: Sven Gothel <sgothel>
Status: RESOLVED WORKSFORME    
Severity: major CC: bkuker
Priority: ---    
Version: 2   
Hardware: All   
OS: all   
Type: --- SCM Refs:
Workaround: ---
Attachments: A test program

Description Sven Gothel 2013-09-24 19:38:16 CEST
GLJPanel's offscreen FBO usage [w/o GLSL flip] 
seems to lag by one frame.
Comment 1 Bill Kuker 2013-09-25 00:35:02 CEST
Created attachment 505 [details]
A test program
Comment 2 Bill Kuker 2013-09-25 00:41:08 CEST
When you create a GLJPanel using multisampling and disable the GLSL flip code the image displayed on screen lags one frame behind the image rendered by the display() method.

This means the very first frame displayed is garbage from video memory.

This is only very noticeable in a non-animated situation when repaint() is called in response to user input. For example in my application a user can select a part of the model in a menu and that part is highlighted. The image on screen displays the previously selected part.

Click on the Head and nothing happens, click on the Arm and the Head is highlighted, click on the Leg and the Arm is higlighted, etc.

In the sample program the constructor is:

public Bug841(boolean enableAA, boolean glsl)...

These three work correctly
new Bug841(true, true);
new Bug841(false, true);
new Bug841(false, false);

// This one is the problem one.
new Bug841(true, false);

NOTE: Because GLSL is controlled via a system property you must only run ONE of these at a time, do NOT uncomment them all.
Comment 3 Sven Gothel 2013-10-19 03:02:35 CEST
Hi Bill, I tested you use case w/ latest git tip and I could not reproduce it.

I verified that AA was enabled and GLSL not, see dump below.

Since GLJPanel operates OS agnostic I assume
my test on GNU/Linux w/ an NV card is representative.

If you still experience this bug, please reopen and 
try to send me more detailed information (Wiki/FAQ/Bugreport).
Maybe a better test .. as well.

Thank you.

~Sven

main: GLJPanel.addNotify()
main: GLJPanel.reshape resize [ panel 0x0, reshape: 0x0] -> 390x270
AWT-EventQueue-0: GLJPanel.reshape resize [ panel 0x0, reshape: 390x270] -> 392x273
AWT-EventQueue-0: GLJPanel.createAndInitializeBackend: 0x0 -> 392x273
AWT-EventQueue-0: OffscreenBackend: initialize()
AWT-EventQueue-0: OffscreenBackend.initialize: useGLSLFlip false [flip true, isFBO true, isGL2ES2 true, noglsl true, glslNonCompliant false, isGL2ES2 true]
AWT-EventQueue-0: GLJPanel.handleReshape: 392x273 -> 392x273
AWT-EventQueue-0: GLJPanel.OffscreenBackend.handleReshape: 392x273 -> 392x273
AWT-EventQueue-0: GLJPanel.display: reshape(0,0 392x273)

XXX GLCaps[glx vid 0x27, fbc 0x10d: rgba 8/8/8/8, opaque, accum-rgba 0/0/0/0, dp/st/ms 24/0/6, sample-ext default, dbl, mono  , hw, GLProfile[GL2/GL2.hw], offscr[fbo]]

AWT-EventQueue-0: GLJPanel.OffscreenBackend.postGL.0: pixelBufferProvider isSingletonBufferProvider true, 0x7312c7dd, SingleAWTGLPixelBufferProvider
AWT-EventQueue-0: GLJPanel.OffscreenBackend.postGL.0: pixelBuffer 0x55ffb930, AWTGLPixelBuffer[PixelAttributes[comp 3, fmt 0x80e1, type 0x1401, bytesPerPixel 4], dim 392x273x1, pack true, disposed false, valid true, buffer[bytes 428064, elemSize 4, java.nio.HeapIntBuffer[pos=0 lim=107016 cap=107016]], allowRowStride true, image [392x273, BufferedImage@7d72a6c: type = 1 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=0 IntegerInterleavedRaster: width = 392 height = 273 #Bands = 3 xOff = 0 yOff = 0 dataOffset[0] 0]], alignment 1
AWT-EventQueue-0: GLJPanel.OffscreenBackend.postGL.0: flippedVertical true, glslTextureRaster false
AWT-EventQueue-0: GLJPanel.OffscreenBackend.postGL.0: panelSize 392x273
AWT-EventQueue-0: GLJPanel.OffscreenBackend.postGL.0: alignedImage 392x273, pixelBuffer 392x273
Comment 4 Bill Kuker 2013-10-19 04:41:55 CEST
To be honest I have not managed to build JOGL from source, the build process seems like it is looking for some additional utilities to be installed to work.

If this is fixed in git I'll let you know after the next release.

BTW since the problem is using glReadPixels on an multi-sampled FBO this could be  hardware dependent I think.
Comment 5 Bill Kuker 2013-10-19 04:46:32 CEST
Here are some links:

http://stackoverflow.com/questions/765434/glreadpixels-from-fbo-fails-with-multisampling/819463#819463

http://www.khronos.org/message_boards/showthread.php/7637-How-to-read-Pixel-data-from-the-MultiSampled-framebuffer

I realize they are just Q&A forums, but they are what led me to this conclusion.

What would you suggest for a better test case? The code I provided shows one obviously different behavior out of four (At least on affected systems).
Comment 6 Sven Gothel 2013-10-19 05:23:06 CEST
(In reply to comment #5)
> Here are some links:
> 
> http://stackoverflow.com/questions/765434/glreadpixels-from-fbo-fails-with-
> multisampling/819463#819463
> 
> http://www.khronos.org/message_boards/showthread.php/7637-How-to-read-Pixel-
> data-from-the-MultiSampled-framebuffer
> 
> I realize they are just Q&A forums, but they are what led me to this
> conclusion.

I see no conclusion, sorry.

Ofc we blit the msamples -> 1sample
otherwise no result.

> 
> What would you suggest for a better test case? The code I provided shows one
> obviously different behavior out of four (At least on affected systems).

1 - Wiki/Faq/Bugreport (full details)
2 - run failing test also w/ full debug props
3- 7z piped out logs and attach

w/o reproduction we cannot fix ..

you could also try whether a 'glFinish()' _after_ or/and _before_ glReadPixels(..)
in GLJPanel solves your problem .. (GPU/driver ..)

update driver .. ?

thx.

~Sven
Comment 7 Bill Kuker 2013-10-19 14:51:32 CEST
Thanks much for the feedback, I appreciate it. I am going to keep looking into this because it affects my users with Java 7 & OSX (because they need to use GLJPanel instead of GLCanvas, this bug is 100% cross platform as you expect) and ATI cards.

(In reply to comment #6)
> (In reply to comment #5)
> > Here are some links:
> > 
> > http://stackoverflow.com/questions/765434/glreadpixels-from-fbo-fails-with-
> > multisampling/819463#819463
> > 
> > http://www.khronos.org/message_boards/showthread.php/7637-How-to-read-Pixel-
> > data-from-the-MultiSampled-framebuffer
> > 
> > I realize they are just Q&A forums, but they are what led me to this
> > conclusion.
> 
> I see no conclusion, sorry.
> 
> Ofc we blit the msamples -> 1sample
> otherwise no result.
> 

So in GLJPanel there are two uses of GLReadPixels to get image data:

The first is the one that works:

https://github.com/sgothel/jogl/blob/master/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java#L1552

This works because the GLSL flip from the multisampled buffer to the second, non multi-sampled buffer takes the place of blitting from the multisampled buffer.

The Second is the one with the problem:

https://github.com/sgothel/jogl/blob/master/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java#L1560

Unless I am misreading the code this calls glReadPixels without any kind of blit first. Can you point out where it does?

BTW a little more googling make it sound like this is a problem on ATI, and not on NV.
Comment 8 Sven Gothel 2014-08-30 18:45:08 CEST
(In reply to comment #7)
> So in GLJPanel there are two uses of GLReadPixels to get image data:
> 
> The first is the one that works:
> 
> https://github.com/sgothel/jogl/blob/master/src/jogl/classes/javax/media/
> opengl/awt/GLJPanel.java#L1552
> 
> This works because the GLSL flip from the multisampled buffer to the second,
> non multi-sampled buffer takes the place of blitting from the multisampled
> buffer.
> 
> The Second is the one with the problem:
> 
> https://github.com/sgothel/jogl/blob/master/src/jogl/classes/javax/media/
> opengl/awt/GLJPanel.java#L1560
> 
> Unless I am misreading the code this calls glReadPixels without any kind of
> blit first. Can you point out where it does?
> 
> BTW a little more googling make it sound like this is a problem on ATI, and
> not on NV.

the swap-buffers which also blits/AA the MSAA buffer command 
is in (current) line 1808 above the glReadPixels(..):
<<<
        if( autoSwapBufferMode ) {
            // Since we only use a single-buffer non-MSAA or double-buffered MSAA offscreenDrawable,
            // we can always swap!
            offscreenDrawable.swapBuffers();
        }
>>>

I see that disabling autoSwap may case issues here ..

Does it work for you by now ?

Sorry that I have not replied earlier, I was not reading comments
on closed reports .. (ping me w/ an additional email next time pls).
Comment 9 Sven Gothel 2014-08-30 19:34:32 CEST
Also related Bug 975 and Bug 1020
Comment 10 Sven Gothel 2014-08-30 20:04:13 CEST
Test cases:
  com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLJPanelAWT
  com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLCanvasAWT
  com.jogamp.opengl.test.junit.jogl.acore.TestGLReadBuffer01GLWindowNEWT