diff options
author | Sven Gothel <[email protected]> | 2014-02-13 21:32:36 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-02-13 21:32:36 +0100 |
commit | 908ebd99d1eb57ce773a1fdd67c76886da86b9e6 (patch) | |
tree | b453b2beb3abc60acaabd87b2f2a5eb4d200302d /src | |
parent | 8be9d9b5bd71854f4da15294b47125a8a4975e31 (diff) |
Bug 975 - GLJPanel's OffscreenDrawable shall not double swap (custom swap by GLEventListener using [AWT]GLReadBufferUtil)
When utilizing [AWT]GLReadBufferUtil it is usually desired to read from the front-buffer
instead the back-buffer. The latter may not be defined, e.g. when using MSAA.
A GLEventListener utilizing [AWT]GLReadBufferUtil,
must perform the drawable.swapBuffers() to be able to read from the front-buffer.
Usually GLAutoDrawable.setAutoSwapBuffer(false) should be called here,
to avoid a double swap - however GLJPanel does not support toggling auto-swap
since it requires to control swap for it's own read-pixels.
Remedy for GLJPanel:
- GLJPanel issues helper.setAutoSwapBufferMode(false) - immutable
- Enable GLJPanel.swapBuffer() if initializes
This was previously disabled.
- GLJPanel's OffscreenBackend listens to surfaceUpdated,
to be notified whether postGL needs to swap buffer
or the drawable.swapBuffer() was already called between preGL and postGL.
See unit tests adding/removing a snapshot GLEventListener
performing swapBuffers() and setting auto-swap accordingly.
Diffstat (limited to 'src')
-rw-r--r-- | src/jogl/classes/javax/media/opengl/awt/GLJPanel.java | 74 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java | 97 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelResize02AWT.java) | 82 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java | 158 |
4 files changed, 350 insertions, 61 deletions
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 522585f16..66a757d10 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -60,6 +60,7 @@ import java.util.List; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceUpdatedListener; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.opengl.GL; import javax.media.opengl.GL2; @@ -222,7 +223,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return singleAWTGLPixelBufferProvider; } - private final GLDrawableHelper helper = new GLDrawableHelper(); + private final GLDrawableHelper helper; private volatile boolean isInitialized; // @@ -352,9 +353,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing this.glProfile = offscreenCaps.getGLProfile(); this.factory = GLDrawableFactoryImpl.getFactoryImpl(glProfile); this.chooser = chooser; + + helper = new GLDrawableHelper(); + helper.setAutoSwapBufferMode(false); /** Always handles buffer swapping in Backend! */ if( null != shareWith ) { helper.setSharedContext(null, shareWith); } + this.setFocusable(true); // allow keyboard input! this.addHierarchyListener(hierarchyListener); this.isShowing = isShowing(); @@ -941,34 +946,25 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public void setAutoSwapBufferMode(boolean onOrOff) { - // In the current implementation this is a no-op. Both the pbuffer - // and pixmap based rendering paths use a single-buffered surface - // so swapping the buffers doesn't do anything. We also don't - // currently have the provision to skip copying the data to the - // Swing portion of the GLJPanel in any of the rendering paths. + // In the current implementation this is a no-op. + // All Backend's require control of buffer swapping, + // i.e. as required for MSAA offscreen FBO buffer. } @Override public boolean getAutoSwapBufferMode() { - // In the current implementation this is a no-op. Both the pbuffer - // and pixmap based rendering paths use a single-buffered surface - // so swapping the buffers doesn't do anything. We also don't - // currently have the provision to skip copying the data to the - // Swing portion of the GLJPanel in any of the rendering paths. + // In the current implementation this is a no-op. + // All Backend's require control of buffer swapping, + // i.e. as required for MSAA offscreen FBO buffer. return true; } @Override public void swapBuffers() { - // In the current implementation this is a no-op. Both the pbuffer - // and pixmap based rendering paths use a single-buffered surface - // so swapping the buffers doesn't do anything. We also don't - // currently have the provision to skip copying the data to the - // Swing portion of the GLJPanel in any of the rendering paths. - if( printActive && isInitialized) { + if( isInitialized ) { final Backend b = backend; if ( null != b ) { - b.getDrawable().swapBuffers(); + b.swapBuffers(); } } } @@ -1366,6 +1362,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing public boolean preGL(Graphics g); /** + * Shall invoke underlying drawable's swapBuffer. + */ + public void swapBuffers(); + + /** * Called after the OpenGL work is done in init() and display(). * The isDisplay argument indicates whether this was called on * behalf of a call to display() rather than init(). @@ -1401,6 +1402,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private volatile GLContextImpl offscreenContext; // volatile: avoid locking for read-only access private boolean flipVertical; + private boolean needsSwapBuffers = true; + // For saving/restoring of OpenGL state during ReadPixels private final GLPixelStorageModes psm = new GLPixelStorageModes(); @@ -1436,6 +1439,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing chooser, panelWidth, panelHeight); offscreenDrawable.setRealized(true); + offscreenDrawable.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public final void surfaceUpdated(Object updater, NativeSurface ns, long when) { + needsSwapBuffers = false; + } } ); + offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith[0]); offscreenContext.setContextCreationFlags(additionalCtxCreationFlags); if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) { @@ -1453,8 +1462,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing ", isGL2ES2 " + gl.isGL2ES2()+"]"); } if( useGLSLFlip ) { - final boolean _autoSwapBufferMode = helper.getAutoSwapBufferMode(); - helper.setAutoSwapBufferMode(false); final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable; fboDrawable.setTextureUnit( GLJPanel.this.requestedTextureUnit ); try { @@ -1475,7 +1482,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing fboFlipped.destroy(gl); fboFlipped = null; } - helper.setAutoSwapBufferMode(_autoSwapBufferMode); } } else { fboFlipped = null; @@ -1558,11 +1564,19 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public final boolean preGL(Graphics g) { - // Empty in this implementation + needsSwapBuffers = true; return true; } @Override + public final void swapBuffers() { + final GLDrawable d = offscreenDrawable; + if( null != d ) { + d.swapBuffers(); + } + } + + @Override public final void postGL(Graphics g, boolean isDisplay) { if (isDisplay) { final GL gl = offscreenContext.getGL(); @@ -1652,7 +1666,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer()); } - offscreenDrawable.swapBuffers(); + if( needsSwapBuffers ) { + offscreenDrawable.swapBuffers(); + } if(null != glslTextureRaster) { // implies flippedVertical final boolean viewportChange; @@ -1924,13 +1940,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public final GLCapabilitiesImmutable getChosenGLCapabilities() { - // FIXME: should do better than this; is it possible to using only platform-independent code? + // FIXME: should do better than this; is it possible to query J2D Caps ? return new GLCapabilities(null); } @Override public final GLProfile getGLProfile() { - // FIXME: should do better than this; is it possible to using only platform-independent code? + // FIXME: should do better than this; is it possible to query J2D's Profile ? return GLProfile.getDefault(GLProfile.getDefaultDevice()); } @@ -2078,6 +2094,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } @Override + public final void swapBuffers() { + final GLDrawable d = joglDrawable; + if( null != d ) { + d.swapBuffers(); + } + } + + @Override public final void postGL(Graphics g, boolean isDisplay) { // Cause OpenGL pipeline to flush its results because // otherwise it's possible we will buffer up multiple frames' diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java new file mode 100644 index 000000000..c5885d6b4 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java @@ -0,0 +1,97 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Multiple GLJPanels in a JFrame + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public abstract class GLReadBuffer00Base extends UITestCase { + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(); + } + + protected abstract void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip); + + private boolean defAutoSwapBufferMode = true; + protected void addSnapshotGLEL(final GLAutoDrawable glad, final GLEventListener snapshotGLEL) { + defAutoSwapBufferMode = glad.getAutoSwapBufferMode(); + glad.setAutoSwapBufferMode(false); + glad.addGLEventListener(snapshotGLEL); + } + protected void removeSnapshotGLEL(final GLAutoDrawable glad, final GLEventListener snapshotGLEL) { + glad.removeGLEventListener(snapshotGLEL); + glad.setAutoSwapBufferMode(defAutoSwapBufferMode); + } + + + @Test + public void test00_MSAA0_DefFlip() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */); + } + + @Test + public void test01_MSAA0_UsrFlip() throws InterruptedException, InvocationTargetException { + test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */); + } + + @Test + public void test10_MSAA4_DefFlip() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + test(caps, false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */); + } + + @Test + public void test11_MSAA4_UsrFlip() throws InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + test(caps, false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */); + } + + static long duration = 500; // ms +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelResize02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java index dabfb737a..4ad84aa73 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelResize02AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java @@ -25,19 +25,17 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ -package com.jogamp.opengl.test.junit.jogl.awt; +package com.jogamp.opengl.test.junit.jogl.acore; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import javax.imageio.ImageIO; import javax.media.opengl.GL; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLEventListener; @@ -50,12 +48,11 @@ import javax.swing.SwingUtilities; import org.junit.Assume; import org.junit.BeforeClass; import org.junit.FixMethodOrder; -import org.junit.Test; import org.junit.runners.MethodSorters; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.util.MiscUtils; -import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil; import com.jogamp.opengl.util.texture.TextureIO; @@ -63,18 +60,18 @@ import com.jogamp.opengl.util.texture.TextureIO; * Multiple GLJPanels in a JFrame */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class TestGLJPanelResize02AWT extends UITestCase { +public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00Base { @BeforeClass public static void initClass() { GLProfile.initSingleton(); } - public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer) { + public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) { final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false); final JFrame frame = new JFrame(); final Dimension d = new Dimension(320, 240); - + final GLJPanel glad = createGLJPanel(skipGLOrientationVerticalFlip, useSwingDoubleBuffer, caps, d); try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -84,11 +81,10 @@ public class TestGLJPanelResize02AWT extends UITestCase { panel.setDoubleBuffered(useSwingDoubleBuffer); frame.getContentPane().add(panel); - final GLJPanel glad = createGLJPanel(useSwingDoubleBuffer, caps, d); final GearsES2 gears = new GearsES2(0); + gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); gears.setVerbose(false); glad.addGLEventListener(gears); - glad.addGLEventListener(new SnapshotGLEL(awtGLReadBufferUtil)); panel.add(glad); frame.pack(); frame.setVisible(true); @@ -97,10 +93,18 @@ public class TestGLJPanelResize02AWT extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } + final GLEventListener snapshotGLEL = new SnapshotGLEL(awtGLReadBufferUtil, skipGLOrientationVerticalFlip); final Dimension size0 = frame.getSize(); - final Dimension size1 = new Dimension(size0.width+30, size0.height+30); - final Dimension size2 = new Dimension(size0.width-30, size0.height-30); + final Dimension size1 = new Dimension(size0.width+100, size0.height+100); + final Dimension size2 = new Dimension(size0.width-100, size0.height-100); try { + final Animator anim = new Animator(glad); + anim.start(); + try { Thread.sleep(2*duration); } catch (InterruptedException e) { } + anim.stop(); + addSnapshotGLEL(glad, snapshotGLEL); + glad.display(); + try { Thread.sleep(duration); } catch (InterruptedException e) { } javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -120,6 +124,11 @@ public class TestGLJPanelResize02AWT extends UITestCase { frame.validate(); } } ); try { Thread.sleep(duration); } catch (InterruptedException e) { } + + removeSnapshotGLEL(glad, snapshotGLEL); + anim.start(); + try { Thread.sleep(2*duration); } catch (InterruptedException e) { } + anim.stop(); } catch (Exception e1) { e1.printStackTrace(); } @@ -133,12 +142,24 @@ public class TestGLJPanelResize02AWT extends UITestCase { } } + private GLJPanel createGLJPanel(final boolean skipGLOrientationVerticalFlip, final boolean useSwingDoubleBuffer, final GLCapabilitiesImmutable caps, final Dimension size) { + final GLJPanel canvas = new GLJPanel(caps); + canvas.setSize(size); + canvas.setPreferredSize(size); + canvas.setMinimumSize(size); + canvas.setDoubleBuffered(useSwingDoubleBuffer); + canvas.setSkipGLOrientationVerticalFlip(skipGLOrientationVerticalFlip); + return canvas; + } + private class SnapshotGLEL implements GLEventListener { final AWTGLReadBufferUtil glReadBufferUtil; + final boolean skipGLOrientationVerticalFlip; int i; - SnapshotGLEL(final AWTGLReadBufferUtil glReadBufferUtil) { + SnapshotGLEL(final AWTGLReadBufferUtil glReadBufferUtil, final boolean skipGLOrientationVerticalFlip) { this.glReadBufferUtil = glReadBufferUtil; + this.skipGLOrientationVerticalFlip = skipGLOrientationVerticalFlip; i = 0; } @@ -157,40 +178,29 @@ public class TestGLJPanelResize02AWT extends UITestCase { final String filenameAWT = getSnapshotFilename(sn, "awt", drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(), glReadBufferUtil.hasAlpha(), fileSuffix, destPath); - final String filenameJGL = getSnapshotFilename(sn, "jgl", - drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(), - glReadBufferUtil.hasAlpha(), fileSuffix, destPath); - System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filenameAWT+", "+filenameJGL); - gl.glFinish(); // just make sure rendering finished .. - final BufferedImage image = glReadBufferUtil.readPixelsToBufferedImage(gl, true /* awtOrientation */); + // gl.glFinish(); // just make sure rendering finished .. + drawable.swapBuffers(); + final boolean awtOrientation = !( drawable.isGLOriented() && skipGLOrientationVerticalFlip ); + System.err.println(Thread.currentThread().getName()+": ** screenshot: awtOrient/v-flip "+awtOrientation+", "+filenameAWT); + + final BufferedImage image = glReadBufferUtil.readPixelsToBufferedImage(gl, awtOrientation); final File fout = new File(filenameAWT); try { ImageIO.write(image, "png", fout); } catch (IOException e) { e.printStackTrace(); } + /** + final String filenameJGL = getSnapshotFilename(sn, "jgl", + drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(), + glReadBufferUtil.hasAlpha(), fileSuffix, destPath); glReadBufferUtil.write(new File(filenameJGL)); + */ } }; - private GLJPanel createGLJPanel(final boolean useSwingDoubleBuffer, final GLCapabilitiesImmutable caps, final Dimension size) { - final GLJPanel canvas = new GLJPanel(caps); - canvas.setSize(size); - canvas.setPreferredSize(size); - canvas.setMinimumSize(size); - canvas.setDoubleBuffered(useSwingDoubleBuffer); - return canvas; - } - static GLCapabilitiesImmutable caps = null; - @Test - public void test00() throws InterruptedException, InvocationTargetException { - test(new GLCapabilities(null), false /*useSwingDoubleBuffer*/); - } - - static long duration = 500; // ms - public static void main(String[] args) { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { @@ -198,7 +208,7 @@ public class TestGLJPanelResize02AWT extends UITestCase { duration = MiscUtils.atol(args[i], duration); } } - org.junit.runner.JUnitCore.main(TestGLJPanelResize02AWT.class.getName()); + org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLJPanelAWT.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java new file mode 100644 index 000000000..598ec1021 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java @@ -0,0 +1,158 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.File; + +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * Multiple GLJPanels in a JFrame + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLReadBuffer01GLWindowNEWT extends GLReadBuffer00Base { + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(); + } + + public void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip) { + if( skipGLOrientationVerticalFlip || useSwingDoubleBuffer ) { + return; // NOP + } + final GLReadBufferUtil glReadBufferUtil = new GLReadBufferUtil(false, false); + final GLWindow glad= GLWindow.create(caps); + try { + glad.setPosition(64, 64); + glad.setSize(320, 240); + final GearsES2 gears = new GearsES2(0); + gears.setVerbose(false); + glad.addGLEventListener(gears); + glad.setVisible(true); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + final GLEventListener snapshotGLEL = new SnapshotGLEL(glReadBufferUtil); + final DimensionImmutable size0 = new Dimension(glad.getWidth(), glad.getHeight()); + final DimensionImmutable size1 = new Dimension(size0.getWidth()+100, size0.getHeight()+100); + final DimensionImmutable size2 = new Dimension(size0.getWidth()-100, size0.getHeight()-100); + try { + final Animator anim = new Animator(glad); + anim.start(); + try { Thread.sleep(2*duration); } catch (InterruptedException e) { } + anim.stop(); + addSnapshotGLEL(glad, snapshotGLEL); + glad.display(); + + try { Thread.sleep(duration); } catch (InterruptedException e) { } + glad.setSize(size1.getWidth(), size1.getHeight()); + try { Thread.sleep(duration); } catch (InterruptedException e) { } + glad.setSize(size2.getWidth(), size2.getHeight()); + try { Thread.sleep(duration); } catch (InterruptedException e) { } + glad.setSize(size0.getWidth(), size0.getHeight()); + try { Thread.sleep(duration); } catch (InterruptedException e) { } + + removeSnapshotGLEL(glad, snapshotGLEL); + anim.start(); + try { Thread.sleep(2*duration); } catch (InterruptedException e) { } + anim.stop(); + } catch (Exception e1) { + e1.printStackTrace(); + } + glad.destroy(); + } + + private class SnapshotGLEL implements GLEventListener { + final GLReadBufferUtil glReadBufferUtil; + int i; + + SnapshotGLEL(final GLReadBufferUtil glReadBufferUtil) { + this.glReadBufferUtil = glReadBufferUtil; + i = 0; + } + + @Override + public void init(GLAutoDrawable drawable) { } + @Override + public void dispose(GLAutoDrawable drawable) { } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + @Override + public void display(GLAutoDrawable drawable) { + snapshot(i++, drawable.getGL(), TextureIO.PNG, null); + } + public void snapshot(int sn, GL gl, String fileSuffix, String destPath) { + final GLDrawable drawable = gl.getContext().getGLReadDrawable(); + final String filenameJGL = getSnapshotFilename(sn, "jgl", + drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(), + glReadBufferUtil.hasAlpha(), fileSuffix, destPath); + // gl.glFinish(); // just make sure rendering finished .. + drawable.swapBuffers(); + final boolean mustFlipVertically = !drawable.isGLOriented(); + System.err.println(Thread.currentThread().getName()+": ** screenshot: v-flip "+mustFlipVertically+", "+filenameJGL); + + if(glReadBufferUtil.readPixels(gl, mustFlipVertically)) { + glReadBufferUtil.write(new File(filenameJGL)); + } + } + }; + + static GLCapabilitiesImmutable caps = null; + + public static void main(String[] args) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestGLReadBuffer01GLWindowNEWT.class.getName()); + } + +} |