1 /** 2 * Copyright 2012 JogAmp Community. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without modification, are 5 * permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, this list of 8 * conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 * of conditions and the following disclaimer in the documentation and/or other materials 12 * provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 * The views and conclusions contained in the software and documentation are those of the 25 * authors and should not be interpreted as representing official policies, either expressed 26 * or implied, of JogAmp Community. 27 */ 28 29 package com.jogamp.opengl.test.junit.jogl.acore; 30 31 import com.jogamp.opengl.GL; 32 import com.jogamp.opengl.GLCapabilities; 33 import com.jogamp.opengl.GLCapabilitiesImmutable; 34 import com.jogamp.opengl.GLContext; 35 import com.jogamp.opengl.GLDrawableFactory; 36 import com.jogamp.opengl.GLEventListener; 37 import com.jogamp.opengl.GLFBODrawable; 38 import com.jogamp.opengl.GLOffscreenAutoDrawable; 39 import com.jogamp.opengl.GLProfile; 40 41 import org.junit.Assert; 42 import org.junit.Test; 43 import org.junit.FixMethodOrder; 44 import org.junit.runners.MethodSorters; 45 46 import com.jogamp.opengl.FBObject; 47 import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; 48 import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; 49 import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; 50 import com.jogamp.opengl.test.junit.util.AWTRobotUtil; 51 import com.jogamp.opengl.test.junit.util.UITestCase; 52 53 /** 54 * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the 55 * {@link GLDrawableFactory#createOffscreenAutoDrawable(com.jogamp.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, com.jogamp.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. 56 * <p> 57 * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. 58 * </p> 59 * <p> 60 * Extensive FBO reconfiguration (size and sample buffer count) and validation are performed. 61 * </p> 62 */ 63 @FixMethodOrder(MethodSorters.NAME_ASCENDING) 64 public class TestFBOAutoDrawableFactoryNEWT extends UITestCase { 65 66 static final int widthStep = 800/4; 67 static final int heightStep = 600/4; 68 volatile int szStep = 2; 69 70 interface MyGLEventListener extends GLEventListener { setMakeSnapshot()71 void setMakeSnapshot(); 72 } 73 74 @Test test01a_GL2ES2_Demo1_SingleBuffer_Normal()75 public void test01a_GL2ES2_Demo1_SingleBuffer_Normal() throws InterruptedException { 76 final GLProfile glp = GLProfile.getGL2ES2(); 77 final GLCapabilities caps = new GLCapabilities(glp); 78 caps.setDoubleBuffered(false); 79 testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0)); 80 } 81 @Test test01b_GL2ES2_Demo1_SingleBuffer_NoTex()82 public void test01b_GL2ES2_Demo1_SingleBuffer_NoTex() throws InterruptedException { 83 final GLProfile glp = GLProfile.getGL2ES2(); 84 final GLCapabilities caps = new GLCapabilities(glp); 85 caps.setDoubleBuffered(false); 86 testGLFBODrawableImpl(caps, 0, new GearsES2(0)); 87 } 88 @Test test01c_GL2ES2_Demo1_SingleBuffer_NoTexNoDepth()89 public void test01c_GL2ES2_Demo1_SingleBuffer_NoTexNoDepth() throws InterruptedException { 90 final GLProfile glp = GLProfile.getGL2ES2(); 91 final GLCapabilities caps = new GLCapabilities(glp); 92 caps.setDoubleBuffered(false); 93 caps.setDepthBits(0); 94 testGLFBODrawableImpl(caps, 0, new GearsES2(0)); 95 } 96 97 @Test test02a_GL2ES2_Demo1_DoubleBuffer_Normal()98 public void test02a_GL2ES2_Demo1_DoubleBuffer_Normal() throws InterruptedException { 99 final GLProfile glp = GLProfile.getGL2ES2(); 100 final GLCapabilities caps = new GLCapabilities(glp); 101 caps.setDoubleBuffered(true); // default 102 testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0)); 103 } 104 105 @Test test03a_GL2ES2_Demo2MSAA4_Normal()106 public void test03a_GL2ES2_Demo2MSAA4_Normal() throws InterruptedException { 107 final GLProfile glp = GLProfile.getGL2ES2(); 108 final GLCapabilities caps = new GLCapabilities(glp); 109 caps.setSampleBuffers(true); 110 caps.setNumSamples(4); 111 testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new MultisampleDemoES2(true)); 112 } 113 @Test test03b_GL2ES2_Demo2MSAA4_NoTex()114 public void test03b_GL2ES2_Demo2MSAA4_NoTex() throws InterruptedException { 115 final GLProfile glp = GLProfile.getGL2ES2(); 116 final GLCapabilities caps = new GLCapabilities(glp); 117 caps.setSampleBuffers(true); 118 caps.setNumSamples(4); 119 testGLFBODrawableImpl(caps, 0, new MultisampleDemoES2(true)); 120 } 121 @Test test03c_GL2ES2_Demo2MSAA4_NoTexNoDepth()122 public void test03c_GL2ES2_Demo2MSAA4_NoTexNoDepth() throws InterruptedException { 123 final GLProfile glp = GLProfile.getGL2ES2(); 124 final GLCapabilities caps = new GLCapabilities(glp); 125 caps.setSampleBuffers(true); 126 caps.setNumSamples(4); 127 caps.setDepthBits(0); 128 testGLFBODrawableImpl(caps, 0, new MultisampleDemoES2(true)); 129 } 130 131 @Test test04_GL2ES2_FBODemoMSAA4_Normal()132 public void test04_GL2ES2_FBODemoMSAA4_Normal() throws InterruptedException { 133 final GLProfile glp = GLProfile.getGL2ES2(); 134 final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); 135 demo.setDoRotation(false); 136 final GLCapabilities caps = new GLCapabilities(glp); 137 caps.setSampleBuffers(true); 138 caps.setNumSamples(4); 139 testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, demo); 140 } 141 142 @Test test11_EGLES2_Demo0Normal()143 public void test11_EGLES2_Demo0Normal() throws InterruptedException { 144 if( GLProfile.isAvailable(GLProfile.GLES2) ) { 145 final GLProfile glp = GLProfile.get(GLProfile.GLES2); 146 final GLCapabilities caps = new GLCapabilities(glp); 147 testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0)); 148 } else { 149 System.err.println("EGL ES2 n/a"); 150 } 151 } 152 153 @Test test13_EGLES2_Demo0MSAA4()154 public void test13_EGLES2_Demo0MSAA4() throws InterruptedException { 155 if( GLProfile.isAvailable(GLProfile.GLES2) ) { 156 final GLProfile glp = GLProfile.get(GLProfile.GLES2); 157 final GLCapabilities caps = new GLCapabilities(glp); 158 caps.setSampleBuffers(true); 159 caps.setNumSamples(4); 160 testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0)); 161 } else { 162 System.err.println("EGL ES2 n/a"); 163 } 164 } 165 166 @Test test21_GL3_Demo0Normal()167 public void test21_GL3_Demo0Normal() throws InterruptedException { 168 if( GLProfile.isAvailable(GLProfile.GL3) ) { 169 final GLProfile glp = GLProfile.get(GLProfile.GL3); 170 final GLCapabilities caps = new GLCapabilities(glp); 171 testGLFBODrawableImpl(caps, GLFBODrawable.FBOMODE_USE_TEXTURE, new GearsES2(0)); 172 } else { 173 System.err.println("GL3 n/a"); 174 } 175 } 176 testGLFBODrawableImpl(final GLCapabilities caps, final int fboMode, final GLEventListener demo)177 void testGLFBODrawableImpl(final GLCapabilities caps, final int fboMode, final GLEventListener demo) throws InterruptedException { 178 caps.setFBO(true); 179 final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); 180 final GLOffscreenAutoDrawable.FBO glad = (GLOffscreenAutoDrawable.FBO) 181 factory.createOffscreenAutoDrawable(null, caps, null, widthStep*szStep, heightStep*szStep); 182 Assert.assertNotNull(glad); 183 184 System.out.println("Requested: "+caps); 185 System.out.println("Realized GLAD: "+glad); 186 System.out.println("Realized GLAD: "+glad.getChosenGLCapabilities()); 187 Assert.assertTrue("FBO drawable is initialized before ctx creation", !glad.isInitialized()); 188 glad.setFBOMode(fboMode); 189 190 glad.display(); // initial display incl. init! 191 { 192 final GLContext context = glad.getContext(); 193 Assert.assertNotNull(context); 194 Assert.assertTrue(context.isCreated()); 195 } 196 Assert.assertTrue("FBO drawable is not initialized after ctx creation", glad.isInitialized()); 197 198 final boolean expDepth = caps.getDepthBits() > 0; 199 final boolean reqDepth = glad.getRequestedGLCapabilities().getDepthBits() > 0; 200 final boolean hasDepth = glad.getChosenGLCapabilities().getDepthBits() > 0; 201 System.out.println("Depth: exp "+expDepth+", req "+reqDepth+", has "+hasDepth); 202 Assert.assertEquals("Depth: expected not passed to requested", expDepth, reqDepth); 203 Assert.assertEquals("Depth: requested not passed to chosen", reqDepth, hasDepth); 204 205 // 206 // FBO incl. MSAA is fully initialized now 207 // 208 209 final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); 210 System.out.println("Init GLAD: "+glad); 211 System.out.println("Init GLAD: "+chosenCaps); 212 213 final FBObject fboFront = glad.getFBObject(GL.GL_FRONT); 214 final FBObject fboBack = glad.getFBObject(GL.GL_BACK); 215 216 System.out.println("Init front FBO: "+fboFront); 217 System.out.println("Init back FBO: "+fboBack); 218 219 Assert.assertTrue("FBO drawable is not initialized before ctx creation", glad.isInitialized()); 220 Assert.assertTrue("FBO Front is not initialized before ctx creation", fboFront.isInitialized()); 221 Assert.assertTrue("FBO Back is not initialized before ctx creation", fboBack.isInitialized()); 222 223 if( chosenCaps.getDoubleBuffered() ) { 224 Assert.assertNotEquals("FBO are equal: "+fboFront+" == "+fboBack, fboFront, fboBack); 225 Assert.assertNotSame(fboFront, fboBack); 226 } else { 227 Assert.assertEquals("FBO are not equal: "+fboFront+" != "+fboBack, fboFront, fboBack); 228 Assert.assertSame(fboFront, fboBack); 229 } 230 231 final FBObject.Colorbuffer color0, color1; 232 233 color0 = glad.getColorbuffer(GL.GL_FRONT); 234 if(0==glad.getNumSamples()) { 235 color1 = glad.getColorbuffer(GL.GL_BACK); 236 } else { 237 color1 = null; 238 } 239 240 final boolean expTexture = 0 != ( GLFBODrawable.FBOMODE_USE_TEXTURE & glad.getFBOMode() ); 241 System.out.println("Texture: exp "+expTexture+", hasFront "+color0.isTextureAttachment()); 242 Assert.assertEquals("Texture: Front", expTexture, color0.isTextureAttachment()); 243 if(0==glad.getNumSamples()) { 244 Assert.assertEquals("Texture: Back", expTexture, color1.isTextureAttachment()); 245 } 246 247 final FBObject.Colorbuffer colorA, colorB; 248 final FBObject.RenderAttachment depthA, depthB; 249 250 colorA = fboFront.getColorbuffer(0); 251 Assert.assertNotNull(colorA); 252 colorB = fboBack.getColorbuffer(0); 253 Assert.assertNotNull(colorB); 254 255 Assert.assertEquals("Texture: Front", expTexture, colorA.isTextureAttachment()); 256 if(0==glad.getNumSamples()) { 257 Assert.assertEquals("Texture: Back", expTexture, colorB.isTextureAttachment()); 258 } else { 259 Assert.assertEquals("Texture: MSAA Back is Texture", false, colorB.isTextureAttachment()); 260 } 261 262 if( hasDepth ) { 263 depthA = fboFront.getDepthAttachment(); 264 Assert.assertNotNull(depthA); 265 depthB = fboBack.getDepthAttachment(); 266 Assert.assertNotNull(depthB); 267 } else { 268 depthA = null; 269 depthB = null; 270 } 271 272 glad.display(); // SWAP_ODD 273 274 if( chosenCaps.getDoubleBuffered() ) { 275 // double buffer or MSAA 276 Assert.assertNotEquals("Color attachments are equal: "+colorB+" == "+colorA, colorA, colorB); 277 Assert.assertNotSame(colorB, colorA); 278 if( hasDepth ) { 279 Assert.assertNotEquals("Depth attachments are equal: "+depthB+" == "+depthA, depthA, depthB); 280 Assert.assertNotSame(depthB, depthA); 281 } 282 } else { 283 // single buffer 284 Assert.assertEquals(colorA, colorB); 285 Assert.assertSame(colorA, colorB); 286 Assert.assertEquals(depthA, depthB); 287 Assert.assertSame(depthA, depthB); 288 } 289 290 Assert.assertEquals(color0, colorA); 291 Assert.assertSame(color0, colorA); 292 if(0==glad.getNumSamples()) { 293 Assert.assertEquals(color1, colorB); 294 Assert.assertSame(color1, colorB); 295 } 296 297 if( chosenCaps.getNumSamples() > 0 ) { 298 // MSAA 299 final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); 300 final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); 301 Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront, _fboFront); 302 Assert.assertSame(fboFront, _fboFront); 303 Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack, _fboBack); 304 Assert.assertSame(fboBack, _fboBack); 305 } else if( chosenCaps.getDoubleBuffered() ) { 306 // real double buffer 307 final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); 308 final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); 309 Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack, _fboFront); 310 Assert.assertSame(fboBack, _fboFront); 311 Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront, _fboBack); 312 Assert.assertSame(fboFront, _fboBack); 313 } else { 314 // single buffer 315 final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); 316 final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); 317 Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront, _fboFront); 318 Assert.assertSame(fboFront, _fboFront); 319 Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack, _fboFront); 320 Assert.assertSame(fboBack, _fboFront); 321 Assert.assertEquals("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack, _fboBack); 322 Assert.assertSame(fboBack, _fboBack); 323 Assert.assertEquals("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront, _fboBack); 324 Assert.assertSame(fboFront, _fboBack); 325 } 326 327 glad.addGLEventListener(demo); 328 329 final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); 330 glad.addGLEventListener(snapshotGLEventListener); 331 332 glad.display(); // - SWAP_EVEN 333 334 // 1 - szStep = 2 335 snapshotGLEventListener.setMakeSnapshot(); 336 glad.display(); // - SWAP_ODD 337 338 // 2, 3 (resize + display) 339 szStep = 1; 340 glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); // SWAP_EVEN 341 Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), 342 AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); 343 snapshotGLEventListener.setMakeSnapshot(); 344 glad.display(); // - SWAP_ODD 345 glad.display(); // - SWAP_EVEN 346 { 347 // Check whether the attachment reference are still valid! 348 final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); 349 final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); 350 System.out.println("Resize1.oldFront: "+fboFront); 351 System.out.println("Resize1.nowFront: "+_fboFront); 352 System.out.println("Resize1.oldBack : "+fboBack); 353 System.out.println("Resize1.nowBack : "+_fboBack); 354 Assert.assertEquals(fboFront, _fboFront); 355 Assert.assertSame(fboFront, _fboFront); 356 Assert.assertEquals(fboBack, _fboBack); 357 Assert.assertSame(fboBack, _fboBack); 358 359 FBObject.Colorbuffer _color = _fboFront.getColorbuffer(0); 360 Assert.assertNotNull(_color); 361 Assert.assertEquals(colorA, _color); 362 Assert.assertSame(colorA, _color); 363 364 FBObject.RenderAttachment _depth = _fboFront.getDepthAttachment(); 365 System.err.println("Resize1.oldDepth "+depthA); 366 System.err.println("Resize1.newDepth "+_depth); 367 if( hasDepth ) { 368 Assert.assertNotNull(_depth); 369 } 370 371 Assert.assertEquals(depthA, _depth); 372 Assert.assertSame(depthA, _depth); 373 _depth = _fboBack.getDepthAttachment(); 374 if( hasDepth ) { 375 Assert.assertNotNull(_depth); 376 } 377 Assert.assertEquals(depthB, _depth); 378 Assert.assertSame(depthB, _depth); 379 380 _color = _fboFront.getColorbuffer(colorA); 381 Assert.assertNotNull(_color); 382 Assert.assertEquals(colorA, _color); 383 Assert.assertSame(colorA, _color); 384 } 385 386 // 4, 5 (resize + display) 387 szStep = 4; 388 glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); // SWAP_ODD 389 Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), 390 AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); 391 snapshotGLEventListener.setMakeSnapshot(); 392 glad.display(); // - SWAP_EVEN 393 glad.display(); // - SWAP_ODD 394 { 395 // Check whether the attachment reference are still valid! 396 final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); 397 final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); 398 System.out.println("Resize2.oldFront: "+fboFront); 399 System.out.println("Resize2.nowFront: "+_fboFront); 400 System.out.println("Resize2.oldBack : "+fboBack); 401 System.out.println("Resize2.nowBack : "+_fboBack); 402 if(chosenCaps.getDoubleBuffered() && 0==chosenCaps.getNumSamples()) { 403 // real double buffer 404 Assert.assertEquals(fboBack, _fboFront); 405 Assert.assertEquals(fboFront, _fboBack); 406 } else { 407 // single or MSAA 408 Assert.assertEquals(fboFront, _fboFront); 409 Assert.assertEquals(fboBack, _fboBack); 410 } 411 412 FBObject.Colorbuffer _color = fboBack.getColorbuffer(0); 413 Assert.assertNotNull(_color); 414 Assert.assertEquals(colorB, _color); 415 Assert.assertSame(colorB, _color); 416 417 FBObject.RenderAttachment _depth = fboBack.getDepthAttachment(); 418 if( hasDepth ) { 419 Assert.assertNotNull(_depth); // MSAA back w/ depth 420 } 421 Assert.assertEquals(depthB, _depth); 422 Assert.assertSame(depthB, _depth); 423 424 _depth = fboFront.getDepthAttachment(); 425 if( hasDepth ) { 426 Assert.assertNotNull(_depth); 427 } 428 Assert.assertEquals(depthA, _depth); 429 Assert.assertSame(depthA, _depth); 430 431 _color = fboBack.getColorbuffer(colorB); 432 Assert.assertNotNull(_color); 433 Assert.assertEquals(colorB, _color); 434 Assert.assertSame(colorB, _color); 435 } 436 437 // 6 + 7 (samples + display) 438 final int oldSampleCount = chosenCaps.getNumSamples(); 439 final int newSampleCount = oldSampleCount > 0 ? 0 : 4; 440 System.out.println("Resize3.sampleCount: "+oldSampleCount+" -> "+newSampleCount); 441 glad.setNumSamples(glad.getGL(), newSampleCount); // triggers repaint 442 snapshotGLEventListener.setMakeSnapshot(); 443 glad.display(); // actual screenshot 444 445 // 8, 9 (resize + samples + display) 446 szStep = 3; 447 glad.setSurfaceSize(widthStep*szStep, heightStep*szStep); 448 Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getSurfaceWidth()+"x"+glad.getSurfaceHeight(), 449 AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); 450 snapshotGLEventListener.setMakeSnapshot(); 451 glad.display(); 452 453 glad.destroy(); 454 System.out.println("Fin: "+glad); 455 } 456 main(final String args[])457 public static void main(final String args[]) throws Exception { 458 org.junit.runner.JUnitCore.main(TestFBOAutoDrawableFactoryNEWT.class.getName()); 459 } 460 461 } 462