aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-02-14 06:37:13 +0100
committerSven Gothel <[email protected]>2014-02-14 06:37:13 +0100
commit82f679b064784213591b460fc5eaa1f5f196fbd1 (patch)
tree58baaf8ee0461d8f481c287223192e78583983f6 /src
parentfb12b0b6fa37d3a4136bb04597b3c32b15832c82 (diff)
Bug 975 - GLJPanel's OffscreenDrawable shall not double swap - Use default auto-swap mechanims
Refines commit 908ebd99d1eb57ce773a1fdd67c76886da86b9e6 Note that the test case decide whether to auto-swap (after read-pixels) or not auto-swap (manual swap before read-pixels). See UITestCase.swapBuffersBeforeRead(GLCapabilitiesImmutable chosenCaps): Determines whether the chosen GLCapabilitiesImmutable requires a swap-buffers before reading pixels. Usually one uses the default-read-buffer, i.e. GL.GL_FRONT for single-buffer and GL.GL_BACK for double-buffer GLDrawables and GL.GL_COLOR_ATTACHMENT0 for offscreen framebuffer objects. Here swap-buffers shall happen after calling reading pixels, the default. However, multisampling offscreen GLFBODrawables utilize swap-buffers to downsample the multisamples into the readable sampling sink. In this case, we require a swap-buffers before reading pixels. Returns: chosenCaps.isFBO() && chosenCaps.getSampleBuffers() +++ - GLJPanel: - Remove SurfaceUpdatedListener mechanism in favor of default auto-swap-buffer via GLDrawableHelper. This removes complexity. - postGL does not need to perform explicit swapBuffer operation, but rely on GLDrawableHelper and the default mechanism. This is also compatible w/ J2D backend. - Use GLDrawableHelper for setAutoSwapBufferMode(..) and getAutoSwapBufferMode() +++ UnitTests: - UITestCase: - Add 'boolean swapBuffersBeforeRead(GLCapabilitiesImmutable chosenCaps)' to determine whether swapBuffers() must occure before read-pixels. See above. - GLReadBuffer00Base* - remove explicit addSnapshotGLEL/removeSnapshotGLEL - add TextRendererGLEL, to display frame-count and -dimension - SnapshotGLEL* - simply toggle auto-swap in their init(..) and dispose(..) method! - clear back-buffer if 'swapBuffersBeforeRead' to test whether the right buffer is being used for read-pixels.
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java30
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java146
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java51
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java52
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/UITestCase.java99
5 files changed, 265 insertions, 113 deletions
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 66a757d10..c80b405b5 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -60,7 +60,6 @@ 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;
@@ -355,7 +354,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
this.chooser = chooser;
helper = new GLDrawableHelper();
- helper.setAutoSwapBufferMode(false); /** Always handles buffer swapping in Backend! */
if( null != shareWith ) {
helper.setSharedContext(null, shareWith);
}
@@ -945,18 +943,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public void setAutoSwapBufferMode(boolean onOrOff) {
- // 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.
+ public void setAutoSwapBufferMode(boolean enable) {
+ helper.setAutoSwapBufferMode(enable);
}
@Override
public boolean getAutoSwapBufferMode() {
- // 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;
+ return helper.getAutoSwapBufferMode();
}
@Override
@@ -1402,8 +1395,6 @@ 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();
@@ -1439,12 +1430,6 @@ 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() ) {
@@ -1564,7 +1549,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public final boolean preGL(Graphics g) {
- needsSwapBuffers = true;
+ // Empty in this implementation
return true;
}
@@ -1579,6 +1564,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public final void postGL(Graphics g, boolean isDisplay) {
if (isDisplay) {
+ // offscreenDrawable is already swapped,
+ // either by GLDrawableHelper.invoke or user's GLEL according to auto-swap-buffer-mode.
+
final GL gl = offscreenContext.getGL();
final int componentCount;
@@ -1666,10 +1654,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
}
- if( needsSwapBuffers ) {
- offscreenDrawable.swapBuffers();
- }
-
if(null != glslTextureRaster) { // implies flippedVertical
final boolean viewportChange;
final int[] usrViewport = new int[] { 0, 0, 0, 0 };
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
index c5885d6b4..2ad622d14 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java
@@ -27,8 +27,10 @@
*/
package com.jogamp.opengl.test.junit.jogl.acore;
+import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
+import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
@@ -40,7 +42,15 @@ import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.RenderState;
+import com.jogamp.graph.curve.opengl.TextRenderer;
+import com.jogamp.graph.font.Font;
+import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.geom.opengl.SVertex;
+import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.glsl.ShaderState;
/**
* Multiple GLJPanels in a JFrame
@@ -48,24 +58,128 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public abstract class GLReadBuffer00Base extends UITestCase {
- @BeforeClass
- public static void initClass() {
- GLProfile.initSingleton();
+ public static abstract class TextRendererGLELBase implements GLEventListener {
+ final float[] textPosition = new float[] {0,0,0};
+ final int[] texSize = new int[] { 0 };
+ final int fontSize = 24;
+
+ final Font font;
+ final RenderState rs;
+ final TextRenderer renderer;
+
+ boolean flipVerticalInGLOrientation = false;
+
+ public TextRendererGLELBase() {
+ {
+ Font _font = null;
+ try {
+ _font = FontFactory.get(FontFactory.UBUNTU).getDefault();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ this.font = _font;
+ }
+ if( null != font ) {
+ this.rs = RenderState.createRenderState(new ShaderState(), SVertex.factory());
+ this.renderer = TextRenderer.create(rs, Region.VBAA_RENDERING_BIT);
+ } else {
+ this.rs = null;
+ this.renderer = null;
+ }
+ }
+
+ public void setFlipVerticalInGLOrientation(boolean v) { flipVerticalInGLOrientation=v; }
+ public final TextRenderer getRenderer() { return renderer; }
+
+ public void init(GLAutoDrawable drawable) {
+ if( null != renderer ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ renderer.init(gl);
+ renderer.setAlpha(gl, 0.99f);
+ renderer.setColorStatic(gl, 1.0f, 1.0f, 1.0f);
+ final ShaderState st = rs.getShaderState();
+ st.useProgram(gl, false);
+ }
+ }
+
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ if( null != renderer ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final ShaderState st = rs.getShaderState();
+ st.useProgram(gl, true);
+ // renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 1000.0f);
+ renderer.reshapeOrtho(gl, width, height, 0.1f, 1000.0f);
+ st.useProgram(gl, false);
+ texSize[0] = width * 2;
+ }
+ }
+
+ public abstract void display(GLAutoDrawable drawable);
+
+ public void dispose(GLAutoDrawable drawable) {
+ if( null != renderer ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ renderer.destroy(gl);
+ }
+ }
+
+ int lastRow = -1;
+
+ public void renderString(GLAutoDrawable drawable, String text, int column, int row, int z0) {
+ if( null != renderer ) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ final int height = drawable.getHeight();
+
+ int dx = 0;
+ int dy = height;
+ if(0>row) {
+ row = lastRow + 1;
+ }
+ AABBox textBox = font.getStringBounds(text, fontSize);
+ dx += font.getAdvanceWidth('X', fontSize) * column;
+ dy -= (int)textBox.getHeight() * ( row + 1 );
+
+ final ShaderState st = rs.getShaderState();
+ st.useProgram(gl, true);
+ gl.glEnable(GL2ES2.GL_BLEND);
+ renderer.resetModelview(null);
+ renderer.translate(gl, dx, dy, z0);
+ if( flipVerticalInGLOrientation && drawable.isGLOriented() ) {
+ renderer.scale(gl, 1f, -1f, 1f);
+ }
+ renderer.drawString3D(gl, font, text, textPosition, fontSize, texSize);
+ st.useProgram(gl, false);
+ gl.glDisable(GL2ES2.GL_BLEND);
+
+ lastRow = row;
+ }
+ }
}
+ public static class TextRendererGLEL extends TextRendererGLELBase {
+ int frameNo = 0;
- protected abstract void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip);
+ public TextRendererGLEL() {
+ super();
+ }
- private boolean defAutoSwapBufferMode = true;
- protected void addSnapshotGLEL(final GLAutoDrawable glad, final GLEventListener snapshotGLEL) {
- defAutoSwapBufferMode = glad.getAutoSwapBufferMode();
- glad.setAutoSwapBufferMode(false);
- glad.addGLEventListener(snapshotGLEL);
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ frameNo++;
+ final String text = String.format("Frame %04d: %04dx%04d", frameNo, drawable.getWidth(), drawable.getHeight());
+ if( null != renderer ) {
+ renderString(drawable, text, 0, 0, -1);
+ } else {
+ System.err.println(text);
+ }
+ }
}
- protected void removeSnapshotGLEL(final GLAutoDrawable glad, final GLEventListener snapshotGLEL) {
- glad.removeGLEventListener(snapshotGLEL);
- glad.setAutoSwapBufferMode(defAutoSwapBufferMode);
+
+ @BeforeClass
+ public static void initClass() throws IOException {
+ GLProfile.initSingleton();
}
+ protected abstract void test(final GLCapabilitiesImmutable caps, final boolean useSwingDoubleBuffer, final boolean skipGLOrientationVerticalFlip);
@Test
public void test00_MSAA0_DefFlip() throws InterruptedException, InvocationTargetException {
@@ -78,17 +192,17 @@ public abstract class GLReadBuffer00Base extends UITestCase {
}
@Test
- public void test10_MSAA4_DefFlip() throws InterruptedException, InvocationTargetException {
+ public void test10_MSAA8_DefFlip() throws InterruptedException, InvocationTargetException {
final GLCapabilities caps = new GLCapabilities(null);
- caps.setNumSamples(4);
+ caps.setNumSamples(8);
caps.setSampleBuffers(true);
test(caps, false /*useSwingDoubleBuffer*/, false /* skipGLOrientationVerticalFlip */);
}
@Test
- public void test11_MSAA4_UsrFlip() throws InterruptedException, InvocationTargetException {
+ public void test11_MSAA8_UsrFlip() throws InterruptedException, InvocationTargetException {
final GLCapabilities caps = new GLCapabilities(null);
- caps.setNumSamples(4);
+ caps.setNumSamples(8);
caps.setSampleBuffers(true);
test(caps, false /*useSwingDoubleBuffer*/, true /* skipGLOrientationVerticalFlip */);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java
index 4ad84aa73..ee9eea725 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLJPanelAWT.java
@@ -52,6 +52,7 @@ 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;
@@ -72,6 +73,7 @@ public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00Base {
final JFrame frame = new JFrame();
final Dimension d = new Dimension(320, 240);
final GLJPanel glad = createGLJPanel(skipGLOrientationVerticalFlip, useSwingDoubleBuffer, caps, d);
+ final SnapshotGLELAWT snapshotGLEL = new SnapshotGLELAWT(awtGLReadBufferUtil, skipGLOrientationVerticalFlip);
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
@@ -81,10 +83,14 @@ public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00Base {
panel.setDoubleBuffered(useSwingDoubleBuffer);
frame.getContentPane().add(panel);
- final GearsES2 gears = new GearsES2(0);
+ final GearsES2 gears = new GearsES2(1);
gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
gears.setVerbose(false);
glad.addGLEventListener(gears);
+ final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+ textRendererGLEL.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glad.addGLEventListener(textRendererGLEL);
+ glad.addGLEventListener(snapshotGLEL);
panel.add(glad);
frame.pack();
frame.setVisible(true);
@@ -93,18 +99,11 @@ public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00Base {
throwable.printStackTrace();
Assume.assumeNoException( throwable );
}
- final GLEventListener snapshotGLEL = new SnapshotGLEL(awtGLReadBufferUtil, skipGLOrientationVerticalFlip);
+ glad.display(); // trigger initialization to get chosen-caps!
final Dimension size0 = frame.getSize();
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() {
@@ -125,7 +124,8 @@ public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00Base {
} } );
try { Thread.sleep(duration); } catch (InterruptedException e) { }
- removeSnapshotGLEL(glad, snapshotGLEL);
+ glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+ final Animator anim = new Animator(glad);
anim.start();
try { Thread.sleep(2*duration); } catch (InterruptedException e) { }
anim.stop();
@@ -152,21 +152,31 @@ public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00Base {
return canvas;
}
- private class SnapshotGLEL implements GLEventListener {
+ private class SnapshotGLELAWT implements GLEventListener {
final AWTGLReadBufferUtil glReadBufferUtil;
final boolean skipGLOrientationVerticalFlip;
+ boolean defAutoSwapMode;
+ boolean swapBuffersBeforeRead;
int i;
- SnapshotGLEL(final AWTGLReadBufferUtil glReadBufferUtil, final boolean skipGLOrientationVerticalFlip) {
+ SnapshotGLELAWT(final AWTGLReadBufferUtil glReadBufferUtil, final boolean skipGLOrientationVerticalFlip) {
this.glReadBufferUtil = glReadBufferUtil;
this.skipGLOrientationVerticalFlip = skipGLOrientationVerticalFlip;
+ this.defAutoSwapMode = true;
+ this.swapBuffersBeforeRead = false;
i = 0;
}
@Override
- public void init(GLAutoDrawable drawable) { }
+ public void init(GLAutoDrawable drawable) {
+ defAutoSwapMode = drawable.getAutoSwapBufferMode();
+ swapBuffersBeforeRead = UITestCase.swapBuffersBeforeRead(drawable.getChosenGLCapabilities());
+ drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead );
+ }
@Override
- public void dispose(GLAutoDrawable drawable) { }
+ public void dispose(GLAutoDrawable drawable) {
+ drawable.setAutoSwapBufferMode( defAutoSwapMode );
+ }
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
@Override
@@ -178,10 +188,17 @@ public class TestGLReadBuffer01GLJPanelAWT extends GLReadBuffer00Base {
final String filenameAWT = getSnapshotFilename(sn, "awt",
drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
glReadBufferUtil.hasAlpha(), fileSuffix, destPath);
- // gl.glFinish(); // just make sure rendering finished ..
- drawable.swapBuffers();
+ if( swapBuffersBeforeRead ) {
+ drawable.swapBuffers();
+ // Just to test whether we use the right buffer,
+ // i.e. back-buffer shall no more be required ..
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ } else {
+ gl.glFinish(); // just make sure rendering finished ..
+ }
+
final boolean awtOrientation = !( drawable.isGLOriented() && skipGLOrientationVerticalFlip );
- System.err.println(Thread.currentThread().getName()+": ** screenshot: awtOrient/v-flip "+awtOrientation+", "+filenameAWT);
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: awtOrient/v-flip "+awtOrientation+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameAWT);
final BufferedImage image = glReadBufferUtil.readPixelsToBufferedImage(gl, awtOrientation);
final File fout = new File(filenameAWT);
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
index 598ec1021..dde4c32fa 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLReadBuffer01GLWindowNEWT.java
@@ -34,7 +34,6 @@ 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;
@@ -46,6 +45,7 @@ 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.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.texture.TextureIO;
@@ -67,29 +67,26 @@ public class TestGLReadBuffer01GLWindowNEWT extends GLReadBuffer00Base {
}
final GLReadBufferUtil glReadBufferUtil = new GLReadBufferUtil(false, false);
final GLWindow glad= GLWindow.create(caps);
+ final SnapshotGLEL snapshotGLEL = new SnapshotGLEL(glReadBufferUtil);
try {
glad.setPosition(64, 64);
glad.setSize(320, 240);
- final GearsES2 gears = new GearsES2(0);
+ final GearsES2 gears = new GearsES2(1);
gears.setVerbose(false);
glad.addGLEventListener(gears);
+ final TextRendererGLEL textRendererGLEL = new TextRendererGLEL();
+ textRendererGLEL.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
+ glad.addGLEventListener(textRendererGLEL);
+ glad.addGLEventListener(snapshotGLEL);
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) { }
@@ -98,7 +95,8 @@ public class TestGLReadBuffer01GLWindowNEWT extends GLReadBuffer00Base {
glad.setSize(size0.getWidth(), size0.getHeight());
try { Thread.sleep(duration); } catch (InterruptedException e) { }
- removeSnapshotGLEL(glad, snapshotGLEL);
+ glad.disposeGLEventListener(snapshotGLEL, true /* remove */);
+ final Animator anim = new Animator(glad);
anim.start();
try { Thread.sleep(2*duration); } catch (InterruptedException e) { }
anim.stop();
@@ -110,32 +108,48 @@ public class TestGLReadBuffer01GLWindowNEWT extends GLReadBuffer00Base {
private class SnapshotGLEL implements GLEventListener {
final GLReadBufferUtil glReadBufferUtil;
+ boolean defAutoSwapMode;
+ boolean swapBuffersBeforeRead;
int i;
SnapshotGLEL(final GLReadBufferUtil glReadBufferUtil) {
this.glReadBufferUtil = glReadBufferUtil;
+ this.defAutoSwapMode = true;
+ this.swapBuffersBeforeRead = false;
i = 0;
}
@Override
- public void init(GLAutoDrawable drawable) { }
+ public void init(GLAutoDrawable drawable) {
+ defAutoSwapMode = drawable.getAutoSwapBufferMode();
+ swapBuffersBeforeRead = UITestCase.swapBuffersBeforeRead(drawable.getChosenGLCapabilities());
+ drawable.setAutoSwapBufferMode( !swapBuffersBeforeRead );
+ }
@Override
- public void dispose(GLAutoDrawable drawable) { }
+ public void dispose(GLAutoDrawable drawable) {
+ drawable.setAutoSwapBufferMode( defAutoSwapMode );
+ }
@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);
+ snapshot(i++, drawable, TextureIO.PNG, null);
}
- public void snapshot(int sn, GL gl, String fileSuffix, String destPath) {
- final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ public void snapshot(int sn, GLAutoDrawable drawable, String fileSuffix, String destPath) {
+ final GL gl = drawable.getGL();
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();
+ if( swapBuffersBeforeRead ) {
+ drawable.swapBuffers();
+ // Just to test whether we use the right buffer,
+ // i.e. back-buffer shall no more be required ..
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+ } else {
+ gl.glFinish(); // just make sure rendering finished ..
+ }
final boolean mustFlipVertically = !drawable.isGLOriented();
- System.err.println(Thread.currentThread().getName()+": ** screenshot: v-flip "+mustFlipVertically+", "+filenameJGL);
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: v-flip "+mustFlipVertically+", swapBuffersBeforeRead "+swapBuffersBeforeRead+", "+filenameJGL);
if(glReadBufferUtil.readPixels(gl, mustFlipVertically)) {
glReadBufferUtil.write(new File(filenameJGL));
diff --git a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
index 82247a59b..79c76e49f 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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.util;
import java.io.BufferedReader;
@@ -69,15 +69,15 @@ public abstract class UITestCase {
public static final String SINGLE_INSTANCE_LOCK_FILE = "UITestCase.lock";
public static final int SINGLE_INSTANCE_LOCK_PORT = 59999;
-
+
public static final long SINGLE_INSTANCE_LOCK_TO = 6*60*1000; // wait up to 6 mins
public static final long SINGLE_INSTANCE_LOCK_POLL = 1000; // poll every 1s
private static volatile SingletonInstance singletonInstance;
-
+
private static volatile boolean testSupported = true;
private static volatile boolean resetXRandRIfX11AfterClass = false;
-
+
private static volatile int maxMethodNameLen = 0;
private static final synchronized void initSingletonInstance() {
@@ -89,11 +89,11 @@ public abstract class UITestCase {
}
}
}
-
+
public static boolean isTestSupported() {
return testSupported;
}
-
+
public static void setTestSupported(boolean v) {
System.err.println("setTestSupported: "+v);
testSupported = v;
@@ -102,13 +102,13 @@ public abstract class UITestCase {
public static void setResetXRandRIfX11AfterClass() {
resetXRandRIfX11AfterClass = true;
}
-
+
/**
* Iterates through all outputs and sets the preferred mode and normal rotation using RandR 1.3.
* <p>
* With NV drivers, one need to add the Modes in proper order to the Screen's Subsection "Display",
* otherwise they are either in unsorted resolution order or even n/a!
- * </p>
+ * </p>
*/
@SuppressWarnings("unused")
public static void resetXRandRIfX11() {
@@ -122,7 +122,7 @@ public abstract class UITestCase {
final ProcessBuilder pb = new ProcessBuilder("xrandr", "-q");
pb.redirectErrorStream(true);
System.err.println("XRandR Query: "+pb.command());
- final Process p = pb.start();
+ final Process p = pb.start();
final MiscUtils.StreamDump dump = new MiscUtils.StreamDump( out, p.getInputStream(), ioSync );
dump.start();
while( !dump.eos() ) {
@@ -185,7 +185,7 @@ public abstract class UITestCase {
}
return null;
}
-
+
public static int processCommand(String[] cmdline, OutputStream outstream, String outPrefix) {
int errorCode = 0;
final Object ioSync = new Object();
@@ -207,9 +207,9 @@ public abstract class UITestCase {
e.printStackTrace();
errorCode = Integer.MIN_VALUE;
}
- return errorCode;
+ return errorCode;
}
-
+
public int getMaxTestNameLen() {
if(0 == maxMethodNameLen) {
int ml = 0;
@@ -221,13 +221,13 @@ public abstract class UITestCase {
}
maxMethodNameLen = ml;
}
- return maxMethodNameLen;
+ return maxMethodNameLen;
}
-
+
public final String getTestMethodName() {
return _unitTestName.getMethodName();
}
-
+
public final String getSimpleTestName(String separator) {
return getClass().getSimpleName()+separator+getTestMethodName();
}
@@ -235,10 +235,10 @@ public abstract class UITestCase {
public final String getFullTestName(String separator) {
return getClass().getName()+separator+getTestMethodName();
}
-
+
@BeforeClass
public static void oneTimeSetUp() {
- // one-time initialization code
+ // one-time initialization code
initSingletonInstance();
}
@@ -259,14 +259,14 @@ public abstract class UITestCase {
System.err.println(" - "+unsupportedTestMsg);
Assume.assumeTrue(testSupported); // abort
}
- System.err.println();
+ System.err.println();
}
@After
public void tearDown() {
System.err.println("++++ UITestCase.tearDown: "+getFullTestName(" - "));
}
-
+
public static void waitForKey(String preMessage) {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.err.println(preMessage+"> Press enter to continue");
@@ -274,9 +274,32 @@ public abstract class UITestCase {
System.err.println(stdin.readLine());
} catch (IOException e) { }
}
-
+
static final String unsupportedTestMsg = "Test not supported on this platform.";
+ /**
+ * Determines whether the chosen {@link GLCapabilitiesImmutable}
+ * requires a {@link GLDrawable#swapBuffers() swap-buffers}
+ * before reading pixels.
+ * <p>
+ * Usually one uses the {@link GL#getDefaultReadBuffer() default-read-buffer}, i.e.
+ * {@link GL#GL_FRONT} for single-buffer and {@link GL#GL_BACK} for double-buffer {@link GLDrawable}s
+ * and {@link GL#GL_COLOR_ATTACHMENT0} for offscreen framebuffer objects.<br>
+ * Here {@link GLDrawable#swapBuffers() swap-buffers} shall happen <b>after</b> calling reading pixels, the default.
+ * </p>
+ * <p>
+ * However, <i>multisampling</i> offscreen {@link javax.media.opengl.GLFBODrawable}s
+ * utilize {@link GLDrawable#swapBuffers() swap-buffers} to <i>downsample</i>
+ * the multisamples into the readable sampling sink.
+ * In this case, we require a {@link GLDrawable#swapBuffers() swap-buffers} <b>before</b> reading pixels.
+ * </p>
+ * @param chosenCaps the chosen {@link GLCapabilitiesImmutable}
+ * @return chosenCaps.isFBO() && chosenCaps.getSampleBuffers()
+ */
+ public static final boolean swapBuffersBeforeRead(GLCapabilitiesImmutable chosenCaps) {
+ return chosenCaps.isFBO() && chosenCaps.getSampleBuffers();
+ }
+
public String getSnapshotFilename(int sn, String postSNDetail, GLCapabilitiesImmutable caps, int width, int height, boolean sinkHasAlpha, String fileSuffix, String destPath) {
if(null == fileSuffix) {
fileSuffix = TextureIO.PNG;
@@ -284,7 +307,7 @@ public abstract class UITestCase {
final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1;
final String simpleTestName = this.getSimpleTestName(".");
final String filenameBaseName;
- {
+ {
final String accel = caps.getHardwareAccelerated() ? "hw" : "sw" ;
final String scrnm;
if(caps.isOnscreen()) {
@@ -307,22 +330,22 @@ public abstract class UITestCase {
final String aaext = caps.getSampleExtension();
postSNDetail = null != postSNDetail ? "-"+postSNDetail : "";
- filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-D%02d-St%02d-Sa%02d_%s-%04dx%04d.%s",
- simpleTestName, sn, postSNDetail, caps.getGLProfile().getName(), accel,
- scrnm, dblb, F_pfmt, pfmt, depthBits, stencilBits, samples, aaext,
+ filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-D%02d-St%02d-Sa%02d_%s-%04dx%04d.%s",
+ simpleTestName, sn, postSNDetail, caps.getGLProfile().getName(), accel,
+ scrnm, dblb, F_pfmt, pfmt, depthBits, stencilBits, samples, aaext,
width, height, fileSuffix).replace(' ', '_');
}
- return null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName;
+ return null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName;
}
-
+
/**
- * Takes a snapshot of the drawable's current front framebuffer. Example filenames:
+ * Takes a snapshot of the drawable's current front framebuffer. Example filenames:
* <pre>
* TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgba8888_-D24-St00-Sa00_default-0400x0300.png
* TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgba8880-D24-St00-Sa00_default-0200x0150.png
* TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgba5551-D24-St00-Sa00_default-0200x0150.png
* </pre>
- * @param sn sequential number
+ * @param sn sequential number
* @param postSNDetail optional detail to be added to the filename after <code>sn</code>
* @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename.
* @param readBufferUtil the {@link GLReadBufferUtil} to be used to read the pixels for the screenshot.
@@ -330,20 +353,20 @@ public abstract class UITestCase {
* If <code>null</code> the <code>"png"</code> as defined in {@link TextureIO#PNG} is being used.
* @param destPath Optional platform dependent file path. It shall use {@link File#separatorChar} as is directory separator.
* It shall not end with a directory separator, {@link File#separatorChar}.
- * If <code>null</code> the current working directory is being used.
+ * If <code>null</code> the current working directory is being used.
*/
public void snapshot(int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
final GLDrawable drawable = gl.getContext().getGLReadDrawable();
- final String filename = getSnapshotFilename(sn, postSNDetail,
- drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
+ final String filename = getSnapshotFilename(sn, postSNDetail,
+ drawable.getChosenGLCapabilities(), drawable.getWidth(), drawable.getHeight(),
readBufferUtil.hasAlpha(), fileSuffix, destPath);
System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename);
gl.glFinish(); // just make sure rendering finished ..
if(readBufferUtil.readPixels(gl, false)) {
readBufferUtil.write(new File(filename));
- }
+ }
}
-
+
public class SnapshotGLEventListener implements GLEventListener {
private final GLReadBufferUtil screenshot;
private volatile boolean makeShot = false;
@@ -394,6 +417,6 @@ public abstract class UITestCase {
postSNDetail = v;
}
};
-
+
}