diff options
author | Sven Gothel <[email protected]> | 2013-09-08 15:13:00 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-09-08 15:13:00 +0200 |
commit | 8313200af6da93f83bc70a645e79bfdeb22f05d4 (patch) | |
tree | 7d5618c9d3face58de56a8a08fdbfa660e845a8b | |
parent | 78b65d52385f4a15e4357d0444ea9daec54fb173 (diff) |
TileRenderer*: Fix pre-swap and post-swap in regards to endTile(..), i.e. pre-swap only for FBO && MSAA. See TileRendererBase.reqPreSwapBuffers(..) API doc.
4 files changed, 122 insertions, 36 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java index 55b31b692..afc57fa30 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java @@ -126,19 +126,21 @@ public class RandomTileRenderer extends TileRendererBase { // be sure OpenGL rendering is finished gl.glFlush(); - if( DEBUG ) { - System.err.println("TileRenderer.end.0: "+this.toString()); - } - // save current glPixelStore values psm.save(gl); psm.setPackAlignment(gl, 1); final GL2ES3 gl2es3; + final int readBuffer; if( gl.isGL2ES3() ) { gl2es3 = gl.getGL2ES3(); - gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer()); + readBuffer = gl2es3.getDefaultReadBuffer(); + gl2es3.glReadBuffer(readBuffer); } else { gl2es3 = null; + readBuffer = 0; // undef. probably default: GL_FRONT (single buffering) GL_BACK (double buffering) + } + if( DEBUG ) { + System.err.println("TileRenderer.end.0: readBuffer 0x"+Integer.toHexString(readBuffer)+", "+this.toString()); } final int tmp[] = new int[1]; diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java index e24fa9706..bb6cf70f4 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java @@ -314,20 +314,22 @@ public class TileRenderer extends TileRendererBase { // be sure OpenGL rendering is finished gl.glFlush(); - - if( DEBUG ) { - System.err.println("TileRenderer.end.0: "+this.toString()); - } // save current glPixelStore values psm.save(gl); psm.setPackAlignment(gl, 1); final GL2ES3 gl2es3; + final int readBuffer; if( gl.isGL2ES3() ) { gl2es3 = gl.getGL2ES3(); - gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer()); + readBuffer = gl2es3.getDefaultReadBuffer(); + gl2es3.glReadBuffer(readBuffer); } else { gl2es3 = null; + readBuffer = 0; // undef. probably default: GL_FRONT (single buffering) GL_BACK (double buffering) + } + if( DEBUG ) { + System.err.println("TileRenderer.end.0: readBuffer 0x"+Integer.toHexString(readBuffer)+", "+this.toString()); } final int tmp[] = new int[1]; diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java index 70e68b97f..411d33881 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java +++ b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java @@ -41,10 +41,11 @@ import javax.media.nativewindow.util.DimensionImmutable; import javax.media.opengl.GL; import javax.media.opengl.GL2ES3; import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; - +import javax.media.opengl.GLFBODrawable; import jogamp.opengl.Debug; /** @@ -138,6 +139,7 @@ public abstract class TileRendererBase { protected int currentTileWidth; protected int currentTileHeight; protected GLAutoDrawable glad; + protected boolean gladRequiresPreSwap; protected boolean gladAutoSwapBufferMode = true; protected GLEventListener[] listeners; protected boolean[] listenersInit; @@ -156,7 +158,7 @@ public abstract class TileRendererBase { sb.append("tile["); tileDetails(sb); sb.append("], image[size "+imageSize+", buffer "+hashStr(imageBuffer)+"], glad["+ - gladListenerCount+" listener, pre "+(null!=glEventListenerPre)+", post "+(null!=glEventListenerPost)+"]"); + gladListenerCount+" listener, pre "+(null!=glEventListenerPre)+", post "+(null!=glEventListenerPost)+", preSwap "+gladRequiresPreSwap+"]"); return sb; } public String toString() { @@ -271,9 +273,9 @@ public abstract class TileRendererBase { * Must be called after rendering the scene, * see {@link #beginTile(GL)}. * <p> - * Is is highly recommended to perform {@link GLDrawable#swapBuffers() swapBuffers()} before calling this method.<br> - * This is especially true in regards to multisampling offscreen FBO drawables, - * where {@link GLDrawable#swapBuffers() swapBuffers()} triggers the <i>downsampling</i> to the readable sampling sink. + * Please consider {@link #reqPreSwapBuffers(GLCapabilitiesImmutable)} to determine + * whether you need to perform {@link GLDrawable#swapBuffers() swap-buffers} before or after + * calling this method! * </p> * <p> * User has to comply with the <a href="#glprequirement">GL profile requirement</a>. @@ -286,6 +288,29 @@ public abstract class TileRendererBase { public abstract void endTile( GL gl ) throws IllegalStateException, GLException; /** + * Determines whether the chosen {@link GLCapabilitiesImmutable} + * requires a <i>pre-{@link GLDrawable#swapBuffers() swap-buffers}</i> + * before accessing the results, i.e. before {@link #endTile(GL)}. + * <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 {@link #endTile(GL)}, the default. + * </p> + * <p> + * However, <i>multisampling</i> offscreen {@link 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> calling {@link #endTile(GL)}. + * </p> + * @param chosenCaps the chosen {@link GLCapabilitiesImmutable} + * @return chosenCaps.isFBO() && chosenCaps.getSampleBuffers() + */ + public final boolean reqPreSwapBuffers(GLCapabilitiesImmutable chosenCaps) { + return chosenCaps.isFBO() && chosenCaps.getSampleBuffers(); + } + + /** * Attaches this renderer to the {@link GLAutoDrawable}. * <p> * The {@link GLAutoDrawable}'s original {@link GLEventListener} are moved to this tile renderer.<br> @@ -295,7 +320,8 @@ public abstract class TileRendererBase { * </p> * <p> * The {@link GLAutoDrawable}'s {@link GLAutoDrawable#getAutoSwapBufferMode() auto-swap mode} is cached - * and set to <code>false</code>, since {@link GLAutoDrawable#swapBuffers() swapBuffers()} must be issued before {@link #endTile(GL)}. + * and set to <code>false</code>, since {@link GLAutoDrawable#swapBuffers() swapBuffers()} maybe issued before {@link #endTile(GL)}, + * see {@link #reqPreSwapBuffers(GLCapabilitiesImmutable)}. * </p> * <p> * This tile renderer's {@link GLEventListener} is then added to handle the tile rendering, @@ -309,8 +335,9 @@ public abstract class TileRendererBase { * <li>{@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape(0, 0, tile-width, tile-height)}</li> * <li>{@link GLEventListener#display(GLAutoDrawable) display(autoDrawable)}</li> * </ul></li> - * <li>{@link GLAutoDrawable#swapBuffers() swapBuffers()}</li> + * <li>if ( {@link #reqPreSwapBuffers(GLCapabilitiesImmutable) pre-swap} ) { {@link GLAutoDrawable#swapBuffers() swapBuffers()} }</li> * <li>{@link #endTile(GL)}</li> + * <li>if ( !{@link #reqPreSwapBuffers(GLCapabilitiesImmutable) pre-swap} ) { {@link GLAutoDrawable#swapBuffers() swapBuffers()} }</li> * <li>Optional {@link #setGLEventListener(GLEventListener, GLEventListener) post-glel}.{@link GLEventListener#display(GLAutoDrawable) display(..)}</li> * </ul> * </p> @@ -357,7 +384,12 @@ public abstract class TileRendererBase { } glad.addGLEventListener(tiledGLEL); gladAutoSwapBufferMode = glad.getAutoSwapBufferMode(); + gladRequiresPreSwap = this.reqPreSwapBuffers(glad.getChosenGLCapabilities()); glad.setAutoSwapBufferMode(false); + if( DEBUG ) { + System.err.println("TileRenderer: attached: "+glad); + System.err.println("TileRenderer: preSwap "+gladRequiresPreSwap+", "+glad.getChosenGLCapabilities()+", cached "+listeners.length+" listener"); + } } /** @@ -384,6 +416,10 @@ public abstract class TileRendererBase { glad.setGLEventListenerInitState(l, listenersInit[i]); } glad.setAutoSwapBufferMode(gladAutoSwapBufferMode); + if( DEBUG ) { + System.err.println("TileRenderer: detached: "+glad); + System.err.println("TileRenderer: "+glad.getChosenGLCapabilities()); + } listeners = null; listenersInit = null; @@ -459,9 +495,15 @@ public abstract class TileRendererBase { listeners[i].reshape(drawable, 0, 0, currentTileWidth, currentTileHeight); listeners[i].display(drawable); } - glad.swapBuffers(); - - endTile(gl); + + if( gladRequiresPreSwap ) { + glad.swapBuffers(); + endTile(gl); + } else { + endTile(gl); + glad.swapBuffers(); + } + if( null != glEventListenerPost ) { glEventListenerPost.display(drawable); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java index be209412e..26ac34d5a 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java @@ -27,6 +27,7 @@ */ package com.jogamp.opengl.test.junit.jogl.tile; +import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; import com.jogamp.opengl.test.junit.util.UITestCase; @@ -44,7 +45,6 @@ import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; @@ -91,49 +91,89 @@ public class TestTiledRendering2NEWT extends UITestCase { } @Test - public void test01_gl2___aa0() throws IOException { + public void test001_off_gl2___aa0() throws IOException { GLProfile glp = getGLProfile(GLProfile.GL2); if( null == glp ) { return; } - doTest(new Gears(), glp, 0); + doTest(false, new Gears(), glp, 0); } @Test - public void test02_gl2___aa8() throws IOException { + public void test002_off_gl2___aa8() throws IOException { GLProfile glp = getGLProfile(GLProfile.GL2); if( null == glp ) { return; } - doTest(new Gears(), glp, 8); + doTest(false, new Gears(), glp, 8); } @Test - public void test11_gl2es3_aa0() throws IOException { + public void test011_off_gl2es3_aa0() throws IOException { GLProfile glp = getGL2ES3(); if( null == glp ) { return; } - doTest(new GearsES2(), glp, 0); + doTest(false, new GearsES2(), glp, 0); } @Test - public void test12_gl2es3_aa8() throws IOException { + public void test012_off_gl2es3_aa8() throws IOException { GLProfile glp = getGL2ES3(); if( null == glp ) { return; } - doTest(new GearsES2(), glp, 8); + doTest(false, new GearsES2(), glp, 8); + } + @Test + public void test101_on__gl2___aa0() throws IOException { + GLProfile glp = getGLProfile(GLProfile.GL2); + if( null == glp ) { + return; + } + doTest(true, new Gears(), glp, 0); + } + @Test + public void test102_on__gl2___aa8() throws IOException { + GLProfile glp = getGLProfile(GLProfile.GL2); + if( null == glp ) { + return; + } + doTest(true, new Gears(), glp, 8); + } + @Test + public void test111_on__gl2es3_aa0() throws IOException { + GLProfile glp = getGL2ES3(); + if( null == glp ) { + return; + } + doTest(true, new GearsES2(), glp, 0); + } + @Test + public void test112_on__gl2es3_aa8() throws IOException { + GLProfile glp = getGL2ES3(); + if( null == glp ) { + return; + } + doTest(true, new GearsES2(), glp, 8); } - void doTest(final GLEventListener demo, GLProfile glp, final int msaaCount) throws IOException { - GLCapabilities caps = new GLCapabilities(glp); - caps.setDoubleBuffered(false); + void doTest(boolean onscreen, final GLEventListener demo, GLProfile glp, final int msaaCount) throws IOException { + GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(onscreen); if( msaaCount > 0 ) { caps.setSampleBuffers(true); caps.setNumSamples(msaaCount); } final int maxTileSize = 256; - final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp); - final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, caps, null, maxTileSize, maxTileSize, null); + final GLAutoDrawable glad; + if( onscreen ) { + final GLWindow glWin = GLWindow.create(caps); + glWin.setSize(maxTileSize, maxTileSize); + glWin.setVisible(true); + glad = glWin; + } else { + final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp); + glad = factory.createOffscreenAutoDrawable(null, caps, null, maxTileSize, maxTileSize, null); + } glad.addGLEventListener( demo ); @@ -192,8 +232,6 @@ public class TestTiledRendering2NEWT extends UITestCase { } }); - glad.destroy(); - final GLPixelBuffer imageBuffer = renderer.getImageBuffer(); final TextureData textureData = new TextureData( caps.getGLProfile(), @@ -207,6 +245,8 @@ public class TestTiledRendering2NEWT extends UITestCase { null /* Flusher */); TextureIO.write(textureData, file); + + glad.destroy(); } public static void main(String args[]) { |