/**
* 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.acore;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLCapabilitiesImmutable;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLFBODrawable;
import com.jogamp.opengl.GLOffscreenAutoDrawable;
import com.jogamp.opengl.GLProfile;
import org.junit.Assert;
import org.junit.Test;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2;
import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
/**
* Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the
* {@link GLDrawableFactory#createOffscreenAutoDrawable(com.jogamp.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, com.jogamp.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}.
* <p>
* The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}.
* </p>
* <p>
* Extensive FBO reconfiguration (size and sample buffer count) and validation are performed.
* </p>
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestFBOAutoDrawableFactoryNEWT extends UITestCase {
static final int widthStep = 800/4;
static final int heightStep = 600/4;
volatile int szStep = 2;
interface MyGLEventListener extends GLEventListener {
void setMakeSnapshot();
}
@Test
public void test01a_GL2ES2_Demo1_SingleBuffer_Normal() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
caps.setDoubleBuffered(false);
testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0));
}
@Test
public void test01b_GL2ES2_Demo1_SingleBuffer_NoTex() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
caps.setDoubleBuffered(false);
testGLFBODrawableImpl(caps, 0, new GearsES2(0));
}
@Test
public void test01c_GL2ES2_Demo1_SingleBuffer_NoTexNoDepth() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
caps.setDoubleBuffered(false);
caps.setDepthBits(0);
testGLFBODrawableImpl(caps, 0, new GearsES2(0));
}
@Test
public void test02a_GL2ES2_Demo1_DoubleBuffer_Normal() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
caps.setDoubleBuffered(true); // default
testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0));
}
@Test
public void test03a_GL2ES2_Demo2MSAA4_Normal() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new MultisampleDemoES2(true));
}
@Test
public void test03b_GL2ES2_Demo2MSAA4_NoTex() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
testGLFBODrawableImpl(caps, 0, new MultisampleDemoES2(true));
}
@Test
public void test03c_GL2ES2_Demo2MSAA4_NoTexNoDepth() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
caps.setDepthBits(0);
testGLFBODrawableImpl(caps, 0, new MultisampleDemoES2(true));
}
@Test
public void test04_GL2ES2_FBODemoMSAA4_Normal() throws InterruptedException {
final GLProfile glp = GLProfile.getGL2ES2();
final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0);
demo.setDoRotation(false);
final GLCapabilities caps = new GLCapabilities(glp);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, demo);
}
@Test
public void test11_EGLES2_Demo0Normal() throws InterruptedException {
if( GLProfile.isAvailable(GLProfile.GLES2) ) {
final GLProfile glp = GLProfile.get(GLProfile.GLES2);
final GLCapabilities caps = new GLCapabilities(glp);
testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0));
} else {
System.err.println("EGL ES2 n/a");
}
}
@Test
public void test13_EGLES2_Demo0MSAA4() throws InterruptedException {
if( GLProfile.isAvailable(GLProfile.GLES2) ) {
final GLProfile glp = GLProfile.get(GLProfile.GLES2);
final GLCapabilities caps = new GLCapabilities(glp);
caps.setSampleBuffers(true);
caps.setNumSamples(4);
testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0));
} else {
System.err.println("EGL ES2 n/a");
}
}
@Test
public void test21_GL3_Demo0Normal() throws InterruptedException {
if( GLProfile.isAvailable(GLProfile.GL3) ) {
final GLProfile glp = GLProfile.get(GLProfile.GL3);
final GLCapabilities caps = new GLCapabilities(glp);
testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0));
} else {
System.err.println("GL3 n/a");
}
}
void testGLFBODrawableImpl(final GLCapabilities caps, final int fboMode, final GLEventListener demo) throws InterruptedException {
caps.setFBO(true);
final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
final GLOffscreenAutoDrawable.FBO glad = (GLOffscreenAutoDrawable.FBO)
factory.createOffscreenAutoDrawable(null, caps, null, widthStep*szStep, heightStep*szStep);
Assert.assertNotNull(glad);
System.out.println("Requested: "+caps);
System.out.println("Realized GLAD: "+glad);
System.out.println("Realized GLAD: "+glad.getChosenGLCapabilities());
Assert.assertTrue("FBO drawable is initialized before ctx creation", !glad.isInitialized());
glad.setFBOMode(fboMode);
glad.display(); // initial display incl. init!
{
final GLContext context = glad.getContext();
Assert.assertNotNull(context);
Assert.assertTrue(context.isCreated());
}
Assert.assertTrue("FBO drawable is not initialized after ctx creation", glad.isInitialized());
final boolean expDepth = caps.getDepthBits() > 0;
final boolean reqDepth = glad.getRequestedGLCapabilities().getDepthBits() > 0;
final boolean hasDepth = glad.getChosenGLCapabilities().getDepthBits() > 0;
System.out.println("Depth: exp "+expDepth+", req "+reqDepth+", has "+hasDepth);
Assert.assertEquals("Depth: expected not passed to requested", expDepth, reqDepth);
Assert.assertEquals("Depth: requested not passed to chosen", reqDepth, hasDepth);
//
// FBO incl. MSAA is fully initialized now
//
final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
System.out.println("Init GLAD: "+glad);
System.out.println("Init GLAD: "+chosenCaps);
final FBObject fboFront = glad.getFBObject(GL.GL_FRONT);
final FBObject fboBack = glad.getFBObject(GL.GL_BACK);
System.out.println("Init front FBO: "+fboFront);
System.out.println("Init back FBO: "+fboBack);
Assert.assertTrue("FBO drawable is not initialized before ctx creation", glad.isInitialized());
Assert.assertTrue("FBO Front is not initialized before ctx creation", fboFront.isInitialized());
Assert.assertTrue("FBO Back is not initialized before ctx creation", fboBack.isInitialized());
if( chosenCaps.getDoubleBuffered() ) {
Assert.assertNotEquals("FBO are equal: "+fboFront+" == "+fboBack, fboFront, fboBack);
Assert.assertNotSame(fboFront, fboBack);
} else {
Assert.assertEquals("FBO are not equal: "+fboFront+" != "+fboBack, fboFront, fboBack);
Assert.assertSame(fboFront, fboBack);
}
final FBObject.Colorbuffer color0, color1;
color0 = glad.getColorbuffer(GL.GL_FRONT);
if(0==glad.getNumSamples()) {
color1 = glad.getColorbuffer(GL.GL_BACK);
} else {
color1 = null;
}
final boolean expTexture = 0 != ( GLFBODrawable.FBOMODE_USE_TEXTURE & glad.getFBOMode() );
System.out.println("Texture: exp "+expTexture+", hasFront "+color0.isTextureAttachment());
Assert.assertEquals("Texture: Front", expTexture, color0.isTextureAttachment());
if(0==glad.getNumSamples()) {
Assert.assertEquals("Texture: Back", expTexture, color1.isTextureAttachment());
}
final FBObject.Colorbuffer colorA, colorB;
final FBObject.RenderAttachment depthA, depthB;
colorA = fboFront.getColorbuffer(0);
Assert.assertNotNull(colorA);
colorB = fboBack.getColorbuffer(0);
Assert.assertNotNull(colorB);
Assert.assertEquals("Texture: Front", expTexture, colorA.isTextureAttachment());
if(0==glad.getNumSamples()) {
Assert.assertEquals("Texture: Back", expTexture, colorB.isTextureAttachment());
} else {
Assert.assertEquals("Texture: MSAA Back is Texture", false, colorB.isTextureAttachment());
}
if( hasDepth ) {
depthA = fboFront.getDepthAttachment();
Assert.assertNotNull(depthA);
depthB = fboBack.getDepthAttachment();
Assert.assertNotNull(depthB);
} else {
depthA = null;
depthB = null;
}
glad.display(); // SWAP_ODD
if( chosenCaps.getDoubleBuffered() ) {
// double buffer or MSAA
Assert.assertNotEquals("Color attachments are equal: "+colorB+" == "+colorA, colorA, colorB);
Assert.assertNotSame(colorB, colorA);
if( hasDepth ) {
Assert.assertNotEquals("Depth attachments are equal: "+depthB+" == "+depthA, depthA, depthB);
Assert.assertNotSame(depthB, depthA);
}
} else {
// single buffer
Assert.assertEquals(colorA, colorB);
Assert.assertSame(colorA, colorB);
Assert.assertEquals(depthA, depthB);
Assert.assertSame(depthA, depthB);
}
Assert.assertEquals(color0, colorA);
Assert.assertSame(color0, colorA);
if(0==glad.getNumSamples()) {
Assert.assertEquals(color1, colorB);
Assert.assertSame(color1, colorB);
}
if( chosenCaps.getNumSamples() > 0 ) {
// MSAA
final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
final FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront, _fboFront);
Assert.assertSame(fboFront, _fboFront);
Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack, _fboBack);
Assert.assertSame(fboBack, _fboBack);
} else if( chosenCaps.getDoubleBuffered() ) {
// real double buffer
final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
final FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack, _fboFront);
Assert.assertSame(fboBack, _fboFront);
Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront, _fboBack);
Assert.assertSame(fboFront, _fboBack);
} else {
// single buffer
final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
final FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront, _fboFront);
Assert.assertSame(fboFront, _fboFront);
Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack, _fboFront);
Assert.assertSame(fboBack, _fboFront);
Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack, _fboBack);
Assert.assertSame(fboBack, _fboBack);
Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront, _fboBack);
Assert.assertSame(fboFront, _fboBack);
}
glad.addGLEventListener(demo);
final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
glad.addGLEventListener(snapshotGLEventListener);
glad.display(); // - SWAP_EVEN
// 1 - szStep = 2
snapshotGLEventListener.setMakeSnapshot();
glad.display(); // - SWAP_ODD
// 2, 3 (resize + display)
szStep = 1;
glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); // SWAP_EVEN
Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
snapshotGLEventListener.setMakeSnapshot();
glad.display(); // - SWAP_ODD
glad.display(); // - SWAP_EVEN
{
// Check whether the attachment reference are still valid!
final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
final FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
System.out.println("Resize1.oldFront: "+fboFront);
System.out.println("Resize1.nowFront: "+_fboFront);
System.out.println("Resize1.oldBack : "+fboBack);
System.out.println("Resize1.nowBack : "+_fboBack);
Assert.assertEquals(fboFront, _fboFront);
Assert.assertSame(fboFront, _fboFront);
Assert.assertEquals(fboBack, _fboBack);
Assert.assertSame(fboBack, _fboBack);
FBObject.Colorbuffer _color = _fboFront.getColorbuffer(0);
Assert.assertNotNull(_color);
Assert.assertEquals(colorA, _color);
Assert.assertSame(colorA, _color);
FBObject.RenderAttachment _depth = _fboFront.getDepthAttachment();
System.err.println("Resize1.oldDepth "+depthA);
System.err.println("Resize1.newDepth "+_depth);
if( hasDepth ) {
Assert.assertNotNull(_depth);
}
Assert.assertEquals(depthA, _depth);
Assert.assertSame(depthA, _depth);
_depth = _fboBack.getDepthAttachment();
if( hasDepth ) {
Assert.assertNotNull(_depth);
}
Assert.assertEquals(depthB, _depth);
Assert.assertSame(depthB, _depth);
_color = _fboFront.getColorbuffer(colorA);
Assert.assertNotNull(_color);
Assert.assertEquals(colorA, _color);
Assert.assertSame(colorA, _color);
}
// 4, 5 (resize + display)
szStep = 4;
glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); // SWAP_ODD
Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
snapshotGLEventListener.setMakeSnapshot();
glad.display(); // - SWAP_EVEN
glad.display(); // - SWAP_ODD
{
// Check whether the attachment reference are still valid!
final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT);
final FBObject _fboBack = glad.getFBObject(GL.GL_BACK);
System.out.println("Resize2.oldFront: "+fboFront);
System.out.println("Resize2.nowFront: "+_fboFront);
System.out.println("Resize2.oldBack : "+fboBack);
System.out.println("Resize2.nowBack : "+_fboBack);
if(chosenCaps.getDoubleBuffered() && 0==chosenCaps.getNumSamples()) {
// real double buffer
Assert.assertEquals(fboBack, _fboFront);
Assert.assertEquals(fboFront, _fboBack);
} else {
// single or MSAA
Assert.assertEquals(fboFront, _fboFront);
Assert.assertEquals(fboBack, _fboBack);
}
FBObject.Colorbuffer _color = fboBack.getColorbuffer(0);
Assert.assertNotNull(_color);
Assert.assertEquals(colorB, _color);
Assert.assertSame(colorB, _color);
FBObject.RenderAttachment _depth = fboBack.getDepthAttachment();
if( hasDepth ) {
Assert.assertNotNull(_depth); // MSAA back w/ depth
}
Assert.assertEquals(depthB, _depth);
Assert.assertSame(depthB, _depth);
_depth = fboFront.getDepthAttachment();
if( hasDepth ) {
Assert.assertNotNull(_depth);
}
Assert.assertEquals(depthA, _depth);
Assert.assertSame(depthA, _depth);
_color = fboBack.getColorbuffer(colorB);
Assert.assertNotNull(_color);
Assert.assertEquals(colorB, _color);
Assert.assertSame(colorB, _color);
}
// 6 + 7 (samples + display)
final int oldSampleCount = chosenCaps.getNumSamples();
final int newSampleCount = oldSampleCount > 0 ? 0 : 4;
System.out.println("Resize3.sampleCount: "+oldSampleCount+" -> "+newSampleCount);
glad.setNumSamples(glad.getGL(), newSampleCount); // triggers repaint
snapshotGLEventListener.setMakeSnapshot();
glad.display(); // actual screenshot
// 8, 9 (resize + samples + display)
szStep = 3;
glad.setSurfaceSize(widthStep*szStep, heightStep*szStep);
Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(),
AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep));
snapshotGLEventListener.setMakeSnapshot();
glad.display();
glad.destroy();
System.out.println("Fin: "+glad);
}
public static void main(final String args[]) throws Exception {
org.junit.runner.JUnitCore.main(TestFBOAutoDrawableFactoryNEWT.class.getName());
}
}