From d3033e42faa909f6c1055f5ba3c7925766a3e583 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 6 Oct 2012 04:57:13 +0200 Subject: Adding unit test for Bug 605 - WORKSFORME, i.e. no unwanted y-flip, so I can just assume it's the SW renderer, flipping. --- .../junit/jogl/caps/TestBug605FlippedImageAWT.java | 185 +++++++++++++++++++++ .../jogl/caps/TestBug605FlippedImageNEWT.java | 176 ++++++++++++++++++++ .../jogamp/opengl/test/junit/util/UITestCase.java | 59 ++++--- 3 files changed, 393 insertions(+), 27 deletions(-) create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java (limited to 'src/test') diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java new file mode 100644 index 000000000..b949bc34d --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageAWT.java @@ -0,0 +1,185 @@ +/** + * Copyright 2012 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.caps; + +import java.io.File; +import java.io.IOException; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.util.awt.Screenshot; +import com.jogamp.opengl.util.texture.TextureIO; + +import java.awt.image.BufferedImage; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.jogamp.opengl.test.junit.util.UITestCase; + +public class TestBug605FlippedImageAWT extends UITestCase { + class FlippedImageTest implements GLEventListener { + public void display(GLAutoDrawable drawable) { + GL2 gl = drawable.getGL().getGL2(); + + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT | GL2.GL_ACCUM_BUFFER_BIT ); + + gl.glMatrixMode(GL2.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glMatrixMode(GL2.GL_MODELVIEW); + gl.glLoadIdentity(); + + // red below + gl.glColor3f(1, 0, 0); + gl.glRectf(-1, -1, 1, 0); + + // green above + gl.glColor3f(0, 1, 0); + gl.glRectf(-1, 0, 1, 1); + gl.glFinish(); + + final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + if(caps.getAccumGreenBits() > 0) { + gl.glAccum(GL2.GL_ACCUM, 1.0f); + gl.glAccum(GL2.GL_RETURN, 1.0f); + } + gl.glFinish(); + + final int width = drawable.getWidth(); + final int height = drawable.getHeight(); + + final String fname = getSnapshotFilename(0, null, caps, width, height, false, TextureIO.PNG, null); + try { + Screenshot.writeToFile(new File(fname), width, height, false); + } catch (GLException e) { + throw e; + } catch (IOException e) { + throw new GLException(e); + } + testFlipped(width, height); + } + + public void init(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + System.err.println("GL_RENDERER: "+gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: "+gl.glGetString(GL.GL_VERSION)); + } + public void reshape(GLAutoDrawable glDrawable, int x, int y, int w, int h) {} + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} + public void dispose(GLAutoDrawable drawable) {} + } + + static final int green = 0x0000ff00; // above + static final int red = 0x00ff0000; // below + + private void testFlipped(int width, int height) { + // Default origin 0/0 is lower left corner, so is the memory layout + // However AWT origin 0/0 is upper left corner + final BufferedImage image = Screenshot.readToBufferedImage(width, height); + + final int below = image.getRGB(0, height-1) & 0x00ffffff; + System.err.println("below: 0x"+Integer.toHexString(below)); + + final int above = image.getRGB(0, 0) & 0x00ffffff; + System.err.println("above: 0x"+Integer.toHexString(above)); + + if (above == green && below == red) { + System.out.println("Image right side up"); + } else if (above == red && below == green) { + Assert.assertTrue("Image is flipped", false); + } else { + Assert.assertTrue("Error in test", false); + } + } + + private void test(GLCapabilitiesImmutable caps) { + + final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLAutoDrawable glad = glFactory.createOffscreenAutoDrawable(null, caps, null, 256, 256, null); + final FlippedImageTest tglel = new FlippedImageTest(); + glad.addGLEventListener(tglel); + + // 1 frame incl. snapshot to memory & file + glad.display(); + System.err.println("XXX "+glad.getChosenGLCapabilities()); + System.err.println("XXX "+glad.getContext().getGLVersion()); + + glad.destroy(); + } + + @Test + public void test01DefaultFBO() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setFBO(true); + test(caps); + } + + @Test + public void test01StencilFBO() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setStencilBits(8); + caps.setFBO(true); + test(caps); + } + + @Test + public void test01DefaultPBuffer() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setPBuffer(true); + test(caps); + } + + @Test + public void test01AccumStencilPBuffer() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAccumRedBits(16); + caps.setAccumGreenBits(16); + caps.setAccumBlueBits(16); + caps.setStencilBits(8); + caps.setPBuffer(true); + test(caps); + } + + public static void main(String[] args) { + org.junit.runner.JUnitCore.main(TestBug605FlippedImageAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java new file mode 100644 index 000000000..837d94cb3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java @@ -0,0 +1,176 @@ +/** + * Copyright 2012 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.caps; + +import java.nio.ByteBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLReadBufferUtil; + +public class TestBug605FlippedImageNEWT extends UITestCase { + static class FlippedImageTest implements GLEventListener { + public void display(GLAutoDrawable drawable) { + GL2 gl = drawable.getGL().getGL2(); + + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT | GL2.GL_ACCUM_BUFFER_BIT ); + + gl.glMatrixMode(GL2.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glMatrixMode(GL2.GL_MODELVIEW); + gl.glLoadIdentity(); + + // red below + gl.glColor3f(1, 0, 0); + gl.glRectf(-1, -1, 1, 0); + + // green above + gl.glColor3f(0, 1, 0); + gl.glRectf(-1, 0, 1, 1); + gl.glFinish(); + + final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + if(caps.getAccumGreenBits() > 0) { + gl.glAccum(GL2.GL_ACCUM, 1.0f); + gl.glAccum(GL2.GL_RETURN, 1.0f); + } + gl.glFinish(); + } + + public void init(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + System.err.println("GL_RENDERER: "+gl.glGetString(GL.GL_RENDERER)); + System.err.println("GL_VERSION: "+gl.glGetString(GL.GL_VERSION)); + } + public void reshape(GLAutoDrawable glDrawable, int x, int y, int w, int h) {} + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} + public void dispose(GLAutoDrawable drawable) {} + } + + static final int green = 0x0000ff00; // above + static final int red = 0x00ff0000; // below + + private int getRGB(ByteBuffer bb, int o) { + return ( (int)bb.get(o+0) & 0x000000ff ) << 16 | + ( (int)bb.get(o+1) & 0x000000ff ) << 8 | + ( (int)bb.get(o+2) & 0x000000ff ); + } + + private void testFlipped(ByteBuffer bb, int width, int height, int comp) { + // Default origin 0/0 is lower left corner, so is the memory layout + + // x=0, y=0: RGB -> _RGB [high-byte .. low-byte] + final int below = getRGB(bb, 0); + System.err.println("below: 0x"+Integer.toHexString(below)); + + // x=0, y=height-1: RGB -> _RGB [high-byte .. low-byte] + final int above= getRGB(bb, ( height - 1 ) * ( width * comp )); + System.err.println("above: 0x"+Integer.toHexString(above)); + + if (above == green && below == red) { + System.out.println("Image right side up"); + } else if (above == red && below == green) { + Assert.assertTrue("Image is flipped", false); + } else { + Assert.assertTrue("Error in test", false); + } + } + + private void test(GLCapabilitiesImmutable caps) { + final GLReadBufferUtil rbu = new GLReadBufferUtil(false, false); + final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLAutoDrawable glad = glFactory.createOffscreenAutoDrawable(null, caps, null, 256, 256, null); + final FlippedImageTest tglel = new FlippedImageTest(); + glad.addGLEventListener(tglel); + final SnapshotGLEventListener snap = new SnapshotGLEventListener(rbu); + glad.addGLEventListener(snap); + snap.setMakeSnapshotAlways(true); + + // 1 frame incl. snapshot to memory & file + glad.display(); + System.err.println("XXX "+glad.getChosenGLCapabilities()); + System.err.println("XXX "+glad.getContext().getGLVersion()); + testFlipped(rbu.getPixelBuffer(), glad.getWidth(), glad.getHeight(), 3); + + glad.destroy(); + } + + @Test + public void test01DefaultFBO() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setFBO(true); + test(caps); + } + + @Test + public void test01StencilFBO() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setStencilBits(8); + caps.setFBO(true); + test(caps); + } + + @Test + public void test01DefaultPBuffer() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setPBuffer(true); + test(caps); + } + + @Test + public void test01AccumStencilPBuffer() { + final GLProfile glp = GLProfile.get(GLProfile.GL2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setAccumRedBits(16); + caps.setAccumGreenBits(16); + caps.setAccumBlueBits(16); + caps.setStencilBits(8); + caps.setPBuffer(true); + test(caps); + } + + public static void main(String[] args) { + org.junit.runner.JUnitCore.main(TestBug605FlippedImageNEWT.class.getName()); + } +} 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 b48f027bb..bd9cd0966 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java +++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java @@ -142,25 +142,8 @@ public abstract class UITestCase { } static final String unsupportedTestMsg = "Test not supported on this platform."; - - /** - * Takes a snapshot of the drawable's current front framebuffer. Example filenames: - *
-     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgb_-S00_default-0400x0300.png
-     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgb_-S00_default-0200x0150.png
-     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgb_-S00_default-0200x0150.png
-     * 
- * @param sn sequential number - * @param postSNDetail optional detail to be added to the filename after sn - * @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. - * @param fileSuffix Optional file suffix without a dot defining the file type, i.e. "png". - * If null the "png" 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 null the current working directory is being used. - */ - public void snapshot(int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) { + + 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; } @@ -168,8 +151,6 @@ public abstract class UITestCase { final String simpleTestName = this.getSimpleTestName("."); final String filenameBaseName; { - final GLDrawable drawable = gl.getContext().getGLReadDrawable(); - final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); final String accel = caps.getHardwareAccelerated() ? "hw" : "sw" ; final String scrnm; if(caps.isOnscreen()) { @@ -184,7 +165,7 @@ public abstract class UITestCase { scrnm = "unknown_"; } final String dblb = caps.getDoubleBuffered() ? "dbl" : "one"; - final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_"; + final String F_pfmt = sinkHasAlpha ? "rgba" : "rgb_"; final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_"; final int depthBits = caps.getDepthBits(); final int stencilBits = caps.getStencilBits(); @@ -193,12 +174,36 @@ public abstract class UITestCase { 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, drawable.getGLProfile().getName(), accel, + simpleTestName, sn, postSNDetail, caps.getGLProfile().getName(), accel, scrnm, dblb, F_pfmt, pfmt, depthBits, stencilBits, samples, aaext, - drawable.getWidth(), drawable.getHeight(), fileSuffix).replace(' ', '_'); + width, height, fileSuffix).replace(' ', '_'); } - final String filename = null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName; - System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename+", maxTestNameLen "+maxSimpleTestNameLen+", <"+simpleTestName+">"); + return null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName; + } + + /** + * Takes a snapshot of the drawable's current front framebuffer. Example filenames: + *
+     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgb_-D24-St00-Sa00_default-0400x0300.png
+     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgb_-D24-St00-Sa00_default-0200x0150.png
+     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgb_-D24-St00-Sa00_default-0200x0150.png
+     * 
+ * @param sn sequential number + * @param postSNDetail optional detail to be added to the filename after sn + * @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. + * @param fileSuffix Optional file suffix without a dot defining the file type, i.e. "png". + * If null the "png" 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 null 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(), + 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)); @@ -219,7 +224,7 @@ public abstract class UITestCase { } public int getDisplayCount() { return displayCount; } public int getReshapeCount() { return reshapeCount; } - + public GLReadBufferUtil getGLReadBufferUtil() { return screenshot; } public void init(GLAutoDrawable drawable) {} public void dispose(GLAutoDrawable drawable) {} public void display(GLAutoDrawable drawable) { -- cgit v1.2.3