diff options
author | Sven Gothel <[email protected]> | 2013-09-05 08:32:31 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-09-05 08:32:31 +0200 |
commit | 604434f8a1ea43f306e21fe81ac7471f27e3c9cf (patch) | |
tree | 97818c8a9d50dff97804be45531ad69c18763596 /src | |
parent | 58682d84c09462b1f2798b847ade6624b89d962f (diff) |
TileRenderer*: Enhance API Doc; Cleanup OO; Remove PMVMatrixCallback, use GLEventListener reshape(..) or manual reshape after beginTile(..) method.
GLEventListener reshape(..) method should be aware of TileRenderer usage
and get the missing tile position and image size from it (-> see Gears example).
TestRandomTiledRendering3GL2AWT demos AWT GLCanvas onscreen
being used for random tile rendering to produce a PNG file.
TestTiledRendering1GL2 is now GLAutoDrawable/GLEventListener agnostic,
hence demos plain GLDrawable tile rendering usage.
Diffstat (limited to 'src')
9 files changed, 843 insertions, 408 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java index 0fba1170d..4fcf0b6cc 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java @@ -29,12 +29,14 @@ package com.jogamp.opengl.util; import javax.media.opengl.GL2ES3; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLEventListener; import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; /** * Variation of {@link TileRenderer} w/o using fixed tiles but arbitrary rectangular regions. + * <p> + * See {@link TileRendererBase} for details. + * </p> */ public class RandomTileRenderer extends TileRendererBase { private boolean tileRectSet = false; @@ -47,8 +49,8 @@ public class RandomTileRenderer extends TileRendererBase { } @Override - public final int getParam(int param) { - switch (param) { + public final int getParam(int pname) { + switch (pname) { case TR_IMAGE_WIDTH: return imageSize.getWidth(); case TR_IMAGE_HEIGHT: @@ -62,7 +64,7 @@ public class RandomTileRenderer extends TileRendererBase { case TR_CURRENT_TILE_HEIGHT: return currentTileHeight; default: - throw new IllegalArgumentException("Invalid enumerant as argument"); + throw new IllegalArgumentException("Invalid pname: "+pname); } } @@ -94,15 +96,14 @@ public class RandomTileRenderer extends TileRendererBase { if( 0 >= imageSize.getWidth() || 0 >= imageSize.getHeight() ) { throw new IllegalStateException("Image size has not been set"); } - if( null == this.pmvMatrixCB ) { - throw new IllegalStateException("pmvMatrixCB has not been set"); - } if( !tileRectSet ) { throw new IllegalStateException("tileRect has not been set"); } gl.glViewport( 0, 0, currentTileWidth, currentTileHeight ); - pmvMatrixCB.reshapePMVMatrix(gl, currentTileXPos, currentTileYPos, currentTileWidth, currentTileHeight, imageSize.getWidth(), imageSize.getHeight()); + // Do not forget to issue: + // reshape( 0, 0, tW, tH ); + // which shall reflect tile renderer fileds: currentTileXPos, currentTileYPos and imageSize beginCalled = true; } @@ -178,75 +179,11 @@ public class RandomTileRenderer extends TileRendererBase { /** * Rendering one tile, by simply calling {@link GLAutoDrawable#display()}. * - * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachToAutoDrawable(GLAutoDrawable, int) attached} + * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachToAutoDrawable(GLAutoDrawable) attached} * or imageSize is not set */ public void display(int tX, int tY, int tWidth, int tHeight) throws IllegalStateException { setTileRect(tX, tY, tWidth, tHeight); display(); } - - protected final GLEventListener getTiledGLEL() { return tiledGLEL; } - private final GLEventListener tiledGLEL = new GLEventListener() { - @Override - public void init(GLAutoDrawable drawable) { - if( null != glEventListenerPre ) { - glEventListenerPre.init(drawable); - } - final int aSz = listenersInit.length; - for(int i=0; i<aSz; i++) { - final GLEventListener l = listeners[i]; - l.init(drawable); - listenersInit[i] = true; - } - if( null != glEventListenerPost ) { - glEventListenerPost.init(drawable); - } - } - @Override - public void dispose(GLAutoDrawable drawable) { - if( null != glEventListenerPre ) { - glEventListenerPre.dispose(drawable); - } - final int aSz = listenersInit.length; - for(int i=0; i<aSz; i++) { - listeners[i].dispose(drawable); - } - if( null != glEventListenerPost ) { - glEventListenerPost.dispose(drawable); - } - } - @Override - public void display(GLAutoDrawable drawable) { - if( null != glEventListenerPre ) { - glEventListenerPre.display(drawable); - } - final GL2ES3 gl = drawable.getGL().getGL2ES3(); - - beginTile(gl); - - final int aSz = listenersInit.length; - for(int i=0; i<aSz; i++) { - listeners[i].display(drawable); - } - - endTile(gl); - if( null != glEventListenerPost ) { - glEventListenerPost.display(drawable); - } - } - @Override - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - if( null != glEventListenerPre ) { - glEventListenerPre.reshape(drawable, x, y, width, height); - } - final int aSz = listenersInit.length; - for(int i=0; i<aSz; i++) { - listeners[i].reshape(drawable, x, y, width, height); - } - if( null != glEventListenerPost ) { - glEventListenerPost.reshape(drawable, x, y, width, height); - } - } - }; }
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java index a63694207..3bb9dc169 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java @@ -39,7 +39,6 @@ package com.jogamp.opengl.util; import javax.media.nativewindow.util.Dimension; import javax.media.opengl.GL2ES3; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLEventListener; import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; @@ -56,48 +55,51 @@ import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; * <p> * Enhanced for {@link GL2ES3}. * </p> + * <p> + * See {@link TileRendererBase} for details. + * </p> * * @author ryanm, sgothel */ public class TileRenderer extends TileRendererBase { /** - * The width of a tile + * The width of a tile. See {@link #getParam(int)}. */ public static final int TR_TILE_WIDTH = 7; /** - * The height of a tile + * The height of a tile. See {@link #getParam(int)}. */ public static final int TR_TILE_HEIGHT = 8; /** - * The width of the border around the tiles + * The width of the border around the tiles. See {@link #getParam(int)}. */ public static final int TR_TILE_BORDER = 9; /** - * The number of rows of tiles + * The number of rows of tiles. See {@link #getParam(int)}. */ public static final int TR_ROWS = 10; /** - * The number of columns of tiles + * The number of columns of tiles. See {@link #getParam(int)}. */ public static final int TR_COLUMNS = 11; /** - * The current row number + * The current row number. See {@link #getParam(int)}. */ public static final int TR_CURRENT_ROW = 12; /** - * The current column number + * The current column number. See {@link #getParam(int)}. */ public static final int TR_CURRENT_COLUMN = 13; /** - * The order that the rows are traversed + * The order that the rows are traversed. See {@link #getParam(int)}. */ public static final int TR_ROW_ORDER = 14; /** - * Indicates we are traversing rows from the top to the bottom + * Indicates we are traversing rows from the top to the bottom. See {@link #getParam(int)}. */ public static final int TR_TOP_TO_BOTTOM = 15; /** - * Indicates we are traversing rows from the bottom to the top + * Indicates we are traversing rows from the bottom to the top. See {@link #getParam(int)}. */ public static final int TR_BOTTOM_TO_TOP = 16; @@ -180,8 +182,8 @@ public class TileRenderer extends TileRendererBase { public final boolean eot() { return 0 > currentTile; } @Override - public final int getParam(int param) { - switch (param) { + public final int getParam(int pname) { + switch (pname) { case TR_TILE_WIDTH: return tileSize.getWidth(); case TR_TILE_HEIGHT: @@ -219,7 +221,7 @@ public class TileRenderer extends TileRendererBase { case TR_ROW_ORDER: return rowOrder; default: - throw new IllegalArgumentException("Invalid enumerant as argument"); + throw new IllegalArgumentException("Invalid pname: "+pname); } } @@ -243,9 +245,6 @@ public class TileRenderer extends TileRendererBase { if( 0 >= imageSize.getWidth() || 0 >= imageSize.getHeight() ) { throw new IllegalStateException("Image size has not been set"); } - if( null == this.pmvMatrixCB ) { - throw new IllegalStateException("pmvMatrixCB has not been set"); - } if (currentTile <= 0) { setup(); } @@ -297,7 +296,9 @@ public class TileRenderer extends TileRendererBase { } gl.glViewport( 0, 0, tW, tH ); - pmvMatrixCB.reshapePMVMatrix(gl, currentTileXPos, currentTileYPos, tW, tH, imageSize.getWidth(), imageSize.getHeight()); + // Do not forget to issue: + // reshape( 0, 0, tW, tH ); + // which shall reflect tile renderer fileds: currentTileXPos, currentTileYPos and imageSize beginCalled = true; } @@ -385,72 +386,8 @@ public class TileRenderer extends TileRendererBase { * </p> */ @Override - public void attachToAutoDrawable(GLAutoDrawable glad, PMVMatrixCallback pmvMatrixCB) throws IllegalStateException { - super.attachToAutoDrawable(glad, pmvMatrixCB); + public void attachToAutoDrawable(GLAutoDrawable glad) throws IllegalStateException { + super.attachToAutoDrawable(glad); setTileSize(glad.getWidth(), glad.getHeight(), 0); } - - protected final GLEventListener getTiledGLEL() { return tiledGLEL; } - private final GLEventListener tiledGLEL = new GLEventListener() { - @Override - public void init(GLAutoDrawable drawable) { - if( null != glEventListenerPre ) { - glEventListenerPre.init(drawable); - } - final int aSz = listenersInit.length; - for(int i=0; i<aSz; i++) { - final GLEventListener l = listeners[i]; - l.init(drawable); - listenersInit[i] = true; - } - if( null != glEventListenerPost ) { - glEventListenerPost.init(drawable); - } - } - @Override - public void dispose(GLAutoDrawable drawable) { - if( null != glEventListenerPre ) { - glEventListenerPre.dispose(drawable); - } - final int aSz = listenersInit.length; - for(int i=0; i<aSz; i++) { - listeners[i].dispose(drawable); - } - if( null != glEventListenerPost ) { - glEventListenerPost.dispose(drawable); - } - } - @Override - public void display(GLAutoDrawable drawable) { - if( null != glEventListenerPre ) { - glEventListenerPre.display(drawable); - } - final GL2ES3 gl = drawable.getGL().getGL2ES3(); - - beginTile(gl); - - final int aSz = listenersInit.length; - for(int i=0; i<aSz; i++) { - listeners[i].display(drawable); - } - - endTile(gl); - if( null != glEventListenerPost ) { - glEventListenerPost.display(drawable); - } - } - @Override - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - if( null != glEventListenerPre ) { - glEventListenerPre.reshape(drawable, x, y, width, height); - } - final int aSz = listenersInit.length; - for(int i=0; i<aSz; i++) { - listeners[i].reshape(drawable, x, y, width, height); - } - if( null != glEventListenerPost ) { - glEventListenerPost.reshape(drawable, x, y, width, height); - } - } - }; }
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java index 3aa6ea786..8779fa59f 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java +++ b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java @@ -37,7 +37,6 @@ package com.jogamp.opengl.util; import javax.media.nativewindow.util.Dimension; -import javax.media.opengl.GL; import javax.media.opengl.GL2ES3; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; @@ -55,32 +54,43 @@ import javax.media.opengl.GLEventListener; * <p> * Enhanced for {@link GL2ES3}, abstracted to suit {@link TileRenderer} and {@link RandomTileRenderer}. * </p> + * <a name="pmvmatrix"><h5>PMV Matrix Considerations</h5></a> + * <p> + * The PMV matrix needs to be reshaped in user code + * after calling {@link #beginTile(GL2ES3)}, See {@link #beginTile(GL2ES3)}. + * </p> + * <p> + * If {@link #attachToAutoDrawable(GLAutoDrawable) attaching to} an {@link GLAutoDrawable}, + * the {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int)} method + * is being called after {@link #beginTile(GL2ES3)}. + * It's implementation shall reshape the PMV matrix according to {@link #beginTile(GL2ES3)}. + * </p> * * @author ryanm, sgothel */ public abstract class TileRendererBase { /** - * The width of the final image + * The width of the final image. See {@link #getParam(int)}. */ public static final int TR_IMAGE_WIDTH = 1; /** - * The height of the final image + * The height of the final image. See {@link #getParam(int)}. */ public static final int TR_IMAGE_HEIGHT = 2; /** - * The width of the current tile + * The width of the current tile. See {@link #getParam(int)}. */ public static final int TR_CURRENT_TILE_X_POS = 3; /** - * The height of the current tile + * The height of the current tile. See {@link #getParam(int)}. */ public static final int TR_CURRENT_TILE_Y_POS = 4; /** - * The width of the current tile + * The width of the current tile. See {@link #getParam(int)}. */ public static final int TR_CURRENT_TILE_WIDTH = 5; /** - * The height of the current tile + * The height of the current tile. See {@link #getParam(int)}. */ public static final int TR_CURRENT_TILE_HEIGHT = 6; @@ -88,7 +98,6 @@ public abstract class TileRendererBase { protected final GLPixelStorageModes psm = new GLPixelStorageModes(); protected GLPixelBuffer imageBuffer; protected GLPixelBuffer tileBuffer; - protected PMVMatrixCallback pmvMatrixCB = null; protected boolean beginCalled = false; protected int currentTileXPos; protected int currentTileYPos; @@ -100,34 +109,19 @@ public abstract class TileRendererBase { protected GLEventListener glEventListenerPre = null; protected GLEventListener glEventListenerPost = null; - public static interface PMVMatrixCallback { - void reshapePMVMatrix(GL gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight); - } - protected TileRendererBase() { } /** * Gets the parameters of this TileRenderer object * - * @param param The parameter that is to be retrieved + * @param pname The parameter name that is to be retrieved * @return the value of the parameter - * @throws IllegalArgumentException if <code>param</code> is not handled + * @throws IllegalArgumentException if <code>pname</code> is not handled */ - public abstract int getParam(int param) throws IllegalArgumentException; + public abstract int getParam(int pname) throws IllegalArgumentException; /** - * @param pmvMatrixCB - * @throws IllegalArgumentException if <code>pmvMatrixCB</code> is null - */ - public final void setPMVMatrixCallback(PMVMatrixCallback pmvMatrixCB) throws IllegalArgumentException { - if( null == pmvMatrixCB ) { - throw new IllegalArgumentException("pmvMatrixCB is null"); - } - this.pmvMatrixCB = pmvMatrixCB; - } - - /** * Specify a buffer the tiles to be copied to. This is not * necessary for the creation of the final image, but useful if you * want to inspect each tile in turn. @@ -170,13 +164,26 @@ public abstract class TileRendererBase { /** * Begins rendering a tile. * <p> - * Methods modifies the viewport. - * User shall reset the viewport when finishing tile rendering, - * i.e. after last call of {@link #endTile(GL2ES3)}! + * Methods modifies the viewport, see below. + * User shall reset the viewport when finishing all tile rendering, + * i.e. after very last call of {@link #endTile(GL2ES3)}! * </p> - * <p> - * The projection matrix stack should be - * left alone after calling this method! + * <p> + * The <a href="#pmvmatrix">PMV Matrix</a> + * must be reshaped after this call using: + * <ul> + * <li>Current Viewport + * <ul> + * <li>x 0</li> + * <li>y 0</li> + * <li>{@link #TR_CURRENT_TILE_WIDTH tile width}</li> + * <li>{@link #TR_CURRENT_TILE_HEIGHT tile height}</li> + * </ul></li> + * <li>{@link #TR_CURRENT_TILE_X_POS tile x-pos}</li> + * <li>{@link #TR_CURRENT_TILE_Y_POS tile y-pos}</li> + * <li>{@link #TR_IMAGE_WIDTH image width}</li> + * <li>{@link #TR_IMAGE_HEIGHT image height}</li> + * </ul> * </p> * <p> * Use shall render the scene afterwards, concluded with a call to @@ -200,23 +207,46 @@ public abstract class TileRendererBase { /** * Attaches this renderer to the {@link GLAutoDrawable}. * <p> - * The {@link GLAutoDrawable}'s {@link GLEventListener} are removed first and stored locally. + * The {@link GLAutoDrawable}'s original {@link GLEventListener} are moved to local storage. * This renderer {@link GLEventListener} is then added to handle the tile rendering - * for the original {@link GLEventListener}. + * for the original {@link GLEventListener}, i.e. it's {@link GLEventListener#display(GLAutoDrawable) display} issues: + * <ul> + * <li>Optional {@link #setGLEventListener(GLEventListener, GLEventListener) pre-glel}.{@link GLEventListener#display(GLAutoDrawable) display(..)}</li> + * <li>{@link #beginTile(GL2ES3)}</li> + * <li>for all original {@link GLEventListener}: + * <ul> + * <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 #endTile(GL2ES3)}</li> + * <li>Optional {@link #setGLEventListener(GLEventListener, GLEventListener) post-glel}.{@link GLEventListener#display(GLAutoDrawable) display(..)}</li> + * </ul> + * </p> + * <p> + * Consider using {@link #setGLEventListener(GLEventListener, GLEventListener)} to add pre- and post + * hooks to be performed on this renderer {@link GLEventListener}.<br> + * The pre-hook is able to allocate memory and setup parameters, since it's called before {@link #beginTile(GL2ES3)}.<br> + * The post-hook is able to use the rendering result and can even shutdown tile-rendering, + * since it's called after {@link #endTile(GL2ES3)}. * </p> * <p> * Call {@link #detachFromAutoDrawable()} to remove this renderer from the {@link GLAutoDrawable} * and to restore it's original {@link GLEventListener}. * </p> + * <p> + * The <a href="#pmvmatrix">PMV Matrix</a> shall be reshaped in the + * original {@link GLEventListener}'s {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape} + * method. The latter is called for each tile w/ the current viewport. + * The tile's position and image size can be utilized. See details in {@link #beginTile(GL2ES3)}. + * </p> * @param glad * @throws IllegalStateException if an {@link GLAutoDrawable} is already attached */ - public void attachToAutoDrawable(GLAutoDrawable glad, PMVMatrixCallback pmvMatrixCB) throws IllegalStateException { + public void attachToAutoDrawable(GLAutoDrawable glad) throws IllegalStateException { if( null != this.glad ) { throw new IllegalStateException("GLAutoDrawable already attached"); } this.glad = glad; - setPMVMatrixCallback(pmvMatrixCB); final int aSz = glad.getGLEventListenerCount(); listeners = new GLEventListener[aSz]; @@ -226,18 +256,18 @@ public abstract class TileRendererBase { listenersInit[i] = glad.getGLEventListenerInitState(l); listeners[i] = glad.removeGLEventListener( l ); } - glad.addGLEventListener(getTiledGLEL()); + glad.addGLEventListener(tiledGLEL); } /** * Detaches this renderer from the {@link GLAutoDrawable}. * <p> - * See {@link #attachToAutoDrawable(GLAutoDrawable, PMVMatrixCallback)}. + * See {@link #attachToAutoDrawable(GLAutoDrawable)}. * </p> */ public void detachFromAutoDrawable() { if( null != glad ) { - glad.removeGLEventListener(getTiledGLEL()); + glad.removeGLEventListener(tiledGLEL); final int aSz = listenersInit.length; for(int i=0; i<aSz; i++) { final GLEventListener l = listeners[i]; @@ -247,13 +277,9 @@ public abstract class TileRendererBase { listeners = null; listenersInit = null; glad = null; - pmvMatrixCB = null; } } - /** Return this rendere {@link GLEventListener} implementation. */ - protected abstract GLEventListener getTiledGLEL(); - /** * Set {@link GLEventListener} for pre- and post operations when used w/ * {@link #attachAutoDrawable(GLAutoDrawable, int, PMVMatrixCallback)} @@ -269,7 +295,7 @@ public abstract class TileRendererBase { /** * Rendering one tile, by simply calling {@link GLAutoDrawable#display()}. * - * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachToAutoDrawable(GLAutoDrawable, int) attached} + * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachToAutoDrawable(GLAutoDrawable) attached} * or imageSize is not set */ public void display() throws IllegalStateException { @@ -278,4 +304,68 @@ public abstract class TileRendererBase { } glad.display(); } + + private final GLEventListener tiledGLEL = new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + if( null != glEventListenerPre ) { + glEventListenerPre.init(drawable); + } + final int aSz = listenersInit.length; + for(int i=0; i<aSz; i++) { + final GLEventListener l = listeners[i]; + l.init(drawable); + listenersInit[i] = true; + } + if( null != glEventListenerPost ) { + glEventListenerPost.init(drawable); + } + } + @Override + public void dispose(GLAutoDrawable drawable) { + if( null != glEventListenerPre ) { + glEventListenerPre.dispose(drawable); + } + final int aSz = listenersInit.length; + for(int i=0; i<aSz; i++) { + listeners[i].dispose(drawable); + } + if( null != glEventListenerPost ) { + glEventListenerPost.dispose(drawable); + } + } + @Override + public void display(GLAutoDrawable drawable) { + if( null != glEventListenerPre ) { + glEventListenerPre.display(drawable); + } + final GL2ES3 gl = drawable.getGL().getGL2ES3(); + + beginTile(gl); + + final int aSz = listenersInit.length; + for(int i=0; i<aSz; i++) { + listeners[i].reshape(drawable, 0, 0, currentTileWidth, currentTileHeight); + listeners[i].display(drawable); + } + + endTile(gl); + if( null != glEventListenerPost ) { + glEventListenerPost.display(drawable); + } + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + if( null != glEventListenerPre ) { + glEventListenerPre.reshape(drawable, x, y, width, height); + } + final int aSz = listenersInit.length; + for(int i=0; i<aSz; i++) { + listeners[i].reshape(drawable, x, y, width, height); + } + if( null != glEventListenerPost ) { + glEventListenerPost.reshape(drawable, x, y, width, height); + } + } + }; }
\ No newline at end of file diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index b7a24a777..e04051cc0 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -52,10 +52,14 @@ import java.awt.Frame; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; +import java.awt.Rectangle; import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; import java.awt.EventQueue; import java.lang.reflect.InvocationTargetException; +import java.nio.IntBuffer; import java.util.ArrayList; import java.util.List; @@ -95,6 +99,11 @@ import com.jogamp.nativewindow.awt.AWTGraphicsScreen; import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol; import com.jogamp.nativewindow.awt.JAWTWindow; import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.util.GLPixelBuffer; +import com.jogamp.opengl.util.RandomTileRenderer; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.awt.AWTGLPixelBuffer; +import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; @@ -719,6 +728,107 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing paint(g); } + private static SingleAWTGLPixelBufferProvider singleAWTGLPixelBufferProvider = null; + private static synchronized SingleAWTGLPixelBufferProvider getSingleAWTGLPixelBufferProvider() { + if( null == singleAWTGLPixelBufferProvider ) { + singleAWTGLPixelBufferProvider = new SingleAWTGLPixelBufferProvider( true /* allowRowStride */ ); + } + return singleAWTGLPixelBufferProvider; + } + private boolean animatorPaused = false; + private RandomTileRenderer tileRenderer; + private SingleAWTGLPixelBufferProvider printBufferProvider; + private IntBuffer cpuVFlipIntBbuffer; + + public void setupPrint(final int printWidth, final int printHeight, RandomTileRenderer.PMVMatrixCallback pmvMatrixCB) { + final GLAnimatorControl animator = helper.getAnimator(); + if( animator.isAnimating() ) { + animator.pause(); + animatorPaused = true; + } + printBufferProvider = getSingleAWTGLPixelBufferProvider(); + tileRenderer = new RandomTileRenderer(); + tileRenderer.setImageSize(printWidth, printHeight); + tileRenderer.attachToAutoDrawable(this); + final GLEventListener preTileGLEL = new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, 3); + GLPixelBuffer pixelBuffer = printBufferProvider.allocate(gl, pixelAttribs, drawable.getWidth(), drawable.getHeight(), 1, true, 0); + tileRenderer.setTileBuffer(pixelBuffer); + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) {} + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }; + tileRenderer.setGLEventListener(preTileGLEL, null); + } + public void releasePrint() { + tileRenderer.detachFromAutoDrawable(); + tileRenderer = null; + printBufferProvider = null; + singleAWTGLPixelBufferProvider = null; + final GLAnimatorControl animator = animatorPaused ? helper.getAnimator() : null; + if( null != animator ) { + animator.resume(); + } + animatorPaused = false; + } + + @Override + public void print(Graphics graphics) { + if( null != tileRenderer ) { + final Rectangle clip = graphics.getClipBounds(); + System.err.println("AWT print clip: "+clip); + tileRenderer.setTileRect(clip.x, clip.y, clip.width, clip.height); + } + super.print(graphics); + } + private void print(GL gl) { + final int componentCount; + if( isOpaque() ) { + // w/o alpha + componentCount = 3; + } else { + // with alpha + componentCount = 4; + } + final GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, componentCount); + final int imageWidth = tileRenderer.getImageSize().getWidth(); + final int imageHeight = tileRenderer.getImageSize().getHeight(); + AWTGLPixelBuffer pixelBuffer = printBufferProvider.getSingleBuffer(pixelAttribs); + if( null != pixelBuffer && pixelBuffer.requiresNewBuffer(gl, imageWidth, imageHeight, 0) ) { + pixelBuffer.dispose(); + pixelBuffer = null; + } + if ( null == pixelBuffer ) { + pixelBuffer = printBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + } + if( null == cpuVFlipIntBbuffer || pixelBuffer.width * pixelBuffer.height > cpuVFlipIntBbuffer.remaining() ) { + cpuVFlipIntBbuffer = IntBuffer.allocate(pixelBuffer.width * pixelBuffer.height); + } + + tileRenderer.setImageBuffer(pixelBuffer); + + // Copy temporary data into raster of BufferedImage for faster + // blitting Note that we could avoid this copy in the cases + // where !offscreenDrawable.isGLOriented(), + // but that's the software rendering path which is very slow anyway. + final BufferedImage image = pixelBuffer.image; + final int[] src = cpuVFlipIntBbuffer.array(); + final int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + final int incr = pixelBuffer.width; + int srcPos = 0; + int destPos = (imageHeight - 1) * pixelBuffer.width; + for (; destPos >= 0; srcPos += incr, destPos -= incr) { + System.arraycopy(src, srcPos, dest, destPos, incr); + } + } + @Override public void addGLEventListener(GLEventListener listener) { helper.addGLEventListener(listener); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java index d3ab05e82..0c84fac39 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java @@ -17,6 +17,7 @@ import com.jogamp.newt.event.MouseListener; import com.jogamp.newt.event.awt.AWTKeyAdapter; import com.jogamp.newt.event.awt.AWTMouseAdapter; import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.util.TileRendererBase; /** * Gears.java <BR> @@ -33,7 +34,8 @@ public class Gears implements GLEventListener { private int swapInterval; private MouseListener gearsMouse = new GearsMouseAdapter(); private KeyListener gearsKeys = new GearsKeyAdapter(); - + private TileRendererBase tileRendererInUse = null; + // private boolean mouseRButtonDown = false; private int prevMouseX, prevMouseY; @@ -45,6 +47,10 @@ public class Gears implements GLEventListener { this.swapInterval = 1; } + public void setTileRenderer(TileRendererBase tileRenderer) { + tileRendererInUse = tileRenderer; + } + public void setDoRotation(boolean rotate) { this.doRotate = rotate; } public void setGears(int g1, int g2, int g3) { @@ -75,7 +81,22 @@ public class Gears implements GLEventListener { System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); System.err.println("INIT GL IS: " + gl.getClass().getName()); System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); + + init(gl); + + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; + window.addMouseListener(gearsMouse); + window.addKeyListener(gearsKeys); + } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { + final java.awt.Component comp = (java.awt.Component) upstreamWidget; + new AWTMouseAdapter(gearsMouse).addTo(comp); + new AWTKeyAdapter(gearsKeys).addTo(comp); + } + } + public void init(GL2 gl) { float pos[] = { 5.0f, 5.0f, 10.0f, 0.0f }; float red[] = { 0.8f, 0.1f, 0.0f, 0.7f }; float green[] = { 0.0f, 0.8f, 0.2f, 0.7f }; @@ -122,36 +143,64 @@ public class Gears implements GLEventListener { } gl.glEnable(GL2.GL_NORMALIZE); - - final Object upstreamWidget = drawable.getUpstreamWidget(); - if (upstreamWidget instanceof Window) { - final Window window = (Window) upstreamWidget; - window.addMouseListener(gearsMouse); - window.addKeyListener(gearsKeys); - } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { - final java.awt.Component comp = (java.awt.Component) upstreamWidget; - new AWTMouseAdapter(gearsMouse).addTo(comp); - new AWTKeyAdapter(gearsKeys).addTo(comp); - } } - + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - System.err.println("Gears: Reshape "+x+"/"+y+" "+width+"x"+height); - GL2 gl = drawable.getGL().getGL2(); - - gl.setSwapInterval(swapInterval); + GL2 gl = drawable.getGL().getGL2(); + this.reshape(gl, x, y, width, height); + } + + public void reshape(GL2 gl, int x, int y, int width, int height) { + System.err.println("Gears: Reshape "+x+"/"+y+" "+width+"x"+height+", tileRendererInUse "+tileRendererInUse); gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); - if(height>width) { - float h = (float)height / (float)width; - gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f); + + final int tileWidth = width; + final int tileHeight = height; + final int tileX, tileY, imageWidth, imageHeight; + if( null == tileRendererInUse ) { + gl.setSwapInterval(swapInterval); + tileX = 0; + tileY = 0; + imageWidth = width; + imageHeight = height; + } else { + gl.setSwapInterval(0); + tileX = tileRendererInUse.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS); + tileY = tileRendererInUse.getParam(TileRendererBase.TR_CURRENT_TILE_Y_POS); + imageWidth = tileRendererInUse.getParam(TileRendererBase.TR_IMAGE_WIDTH); + imageHeight = tileRendererInUse.getParam(TileRendererBase.TR_IMAGE_HEIGHT); + } + /* compute projection parameters */ + float left, right, bottom, top; + if( imageHeight > imageWidth ) { + float a = (float)imageHeight / (float)imageWidth; + left = -1.0f; + right = 1.0f; + bottom = -a; + top = a; } else { - float h = (float)width / (float)height; - gl.glFrustum(-h, h, -1.0f, 1.0f, 5.0f, 60.0f); + float a = (float)imageWidth / (float)imageHeight; + left = -a; + right = a; + bottom = -1.0f; + top = 1.0f; } - gl.glMatrixMode(GL2.GL_MODELVIEW); + final float w = right - left; + final float h = top - bottom; + final float l = left + w * tileX / imageWidth; + final float r = l + w * tileWidth / imageWidth; + final float b = bottom + h * tileY / imageHeight; + final float t = b + h * tileHeight / imageHeight; + + final float _w = r - l; + final float _h = t - b; + System.err.println(">> angle "+angle+", [l "+left+", r "+right+", b "+bottom+", t "+top+"] "+w+"x"+h+" -> [l "+l+", r "+r+", b "+b+", t "+t+"] "+_w+"x"+_h); + gl.glFrustum(l, r, b, t, 5.0f, 60.0f); + + gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -40.0f); } @@ -170,11 +219,6 @@ public class Gears implements GLEventListener { } public void display(GLAutoDrawable drawable) { - if( doRotate ) { - // Turn the gears' teeth - angle += 2.0f; - } - // Get the GL corresponding to the drawable we are animating GL2 gl = drawable.getGL().getGL2(); @@ -190,7 +234,18 @@ public class Gears implements GLEventListener { } else { gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); } - + displayImpl(gl); + } + public void display(GL2 gl) { + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); + displayImpl(gl); + } + private void displayImpl(GL2 gl) { + if( doRotate ) { + // Turn the gears' teeth + angle += 2.0f; + } // Rotate the entire assembly of gears based on how the user // dragged the mouse around gl.glPushMatrix(); @@ -221,7 +276,7 @@ public class Gears implements GLEventListener { // Remember that every push needs a pop; this one is paired with // rotating the entire gear assembly - gl.glPopMatrix(); + gl.glPopMatrix(); } public static void gear(GL2 gl, diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2.java index d1fabfa6b..1efc95c9e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2.java @@ -1,9 +1,37 @@ +/** + * Copyright 2013 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.tile; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.GLPixelBuffer; import com.jogamp.opengl.util.RandomTileRenderer; +import com.jogamp.opengl.util.TileRendererBase; import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; import com.jogamp.opengl.util.texture.TextureData; import com.jogamp.opengl.util.texture.TextureIO; @@ -11,19 +39,35 @@ import com.jogamp.opengl.util.texture.TextureIO; 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.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLRunnable; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; -/** Demonstrates the RandomTileRenderer class by rendering a large version - of the Gears demo to the specified file. */ +/** + * Demos offscreen {@link GLAutoDrawable} being used for + * {@link RandomTileRenderer} rendering to produce a PNG file. + * <p> + * {@link RandomTileRenderer} is being kicked off from the main thread. + * </p> + * <p> + * {@link RandomTileRenderer} buffer allocation is performed + * within the pre {@link GLEventListener} + * set via {@link TileRendererBase#setGLEventListener(GLEventListener, GLEventListener)} + * on the main thread. + * </p> + * <p> + * At tile rendering finish, the viewport and + * and the original {@link GLEventListener}'s PMV matrix as well. + * The latter is done by calling it's {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape} method. + * </p> +*/ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestRandomTiledRendering2GL2 extends UITestCase { static long duration = 500; // ms @@ -37,7 +81,6 @@ public class TestRandomTiledRendering2GL2 extends UITestCase { GLCapabilities caps = new GLCapabilities(null); caps.setDoubleBuffered(false); - // Use a pbuffer for rendering final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, caps, null, 256, 256, null); @@ -54,43 +97,8 @@ public class TestRandomTiledRendering2GL2 extends UITestCase { // Initialize the tile rendering library final RandomTileRenderer renderer = new RandomTileRenderer(); - final RandomTileRenderer.PMVMatrixCallback pmvMatrixCallback = new RandomTileRenderer.PMVMatrixCallback() { - public void reshapePMVMatrix(GL _gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) { - final GL2 gl = _gl.getGL2(); - gl.glMatrixMode( GL2.GL_PROJECTION ); - gl.glLoadIdentity(); - - /* compute projection parameters */ - float left, right, bottom, top; - if( imageHeight > imageWidth ) { - float a = (float)imageHeight / (float)imageWidth; - left = -1.0f; - right = 1.0f; - bottom = -a; - top = a; - } else { - float a = (float)imageWidth / (float)imageHeight; - left = -a; - right = a; - bottom = -1.0f; - top = 1.0f; - } - final float w = right - left; - final float h = top - bottom; - final float l = left + w * tileX / imageWidth; - final float r = l + w * tileWidth / imageWidth; - final float b = bottom + h * tileY / imageHeight; - final float t = b + h * tileHeight / imageHeight; - - final float _w = r - l; - final float _h = t - b; - System.err.println(">> [l "+left+", r "+right+", b "+bottom+", t "+top+"] "+w+"x"+h+" -> [l "+l+", r "+r+", b "+b+", t "+t+"] "+_w+"x"+_h); - gl.glFrustum(l, r, b, t, 5.0f, 60.0f); - - gl.glMatrixMode(GL2.GL_MODELVIEW); - } - }; - renderer.attachToAutoDrawable(glad, pmvMatrixCallback); + gears.setTileRenderer(renderer); + renderer.attachToAutoDrawable(glad); renderer.setImageSize(imageWidth, imageHeight); final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride; @@ -130,6 +138,18 @@ public class TestRandomTiledRendering2GL2 extends UITestCase { } renderer.detachFromAutoDrawable(); + gears.setTileRenderer(null); + + // Restore viewport and Gear's PMV matrix + // .. even though we close the demo, this is for documentation! + glad.invoke(true, new GLRunnable() { + @Override + public boolean run(GLAutoDrawable drawable) { + drawable.getGL().glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); + gears.reshape(drawable, 0, 0, drawable.getWidth(), drawable.getHeight()); + return false; + } + }); glad.destroy(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java new file mode 100644 index 000000000..26e53c17b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java @@ -0,0 +1,261 @@ +/** + * Copyright 2013 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.tile; + +import com.jogamp.newt.event.TraceKeyAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLPixelBuffer; +import com.jogamp.opengl.util.RandomTileRenderer; +import com.jogamp.opengl.util.TileRendererBase; +import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +import java.awt.Dimension; +import java.awt.Frame; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.awt.GLCanvas; + +import org.junit.Assert; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +/** + * Demos an onscreen AWT {@link GLCanvas} being used for + * {@link RandomTileRenderer} rendering to produce a PNG file. + * <p> + * {@link RandomTileRenderer} is being kicked off from the main thread. + * </p> + * <p> + * {@link RandomTileRenderer} setup and finishing is performed + * within the pre- and post {@link GLEventListener} + * set via {@link TileRendererBase#setGLEventListener(GLEventListener, GLEventListener)} + * on the animation thread. + * </p> + * <p> + * At tile rendering finish, the viewport and + * and the original {@link GLEventListener}'s PMV matrix as well. + * The latter is done by calling it's {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape} method. + * </p> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestRandomTiledRendering3GL2AWT extends UITestCase { + static long duration = 3500; // ms + static int width = 640; + static int height = 480; + + @Test + public void test01() throws IOException, InterruptedException, InvocationTargetException { + doTest(); + } + + void doTest() throws IOException, InterruptedException, InvocationTargetException { + final GLCapabilities caps = new GLCapabilities(null); + caps.setDoubleBuffered(false); + + final Frame frame = new Frame("Gears AWT Test"); + Assert.assertNotNull(frame); + + final GLCanvas glad = new GLCanvas(caps); + Assert.assertNotNull(glad); + Dimension glc_sz = new Dimension(width, height); + glad.setMinimumSize(glc_sz); + glad.setPreferredSize(glc_sz); + glad.setSize(glc_sz); + frame.add(glad); + + final Gears gears = new Gears(); + glad.addGLEventListener( gears ); + + final Animator animator = new Animator(glad); + final QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glad); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + // Fix the image size for now + final int imageWidth = glad.getWidth() * 3; + final int imageHeight = glad.getHeight() * 2; + + // Initialize the tile rendering library + final RandomTileRenderer renderer = new RandomTileRenderer(); + renderer.setImageSize(imageWidth, imageHeight); + final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride; + final boolean[] flipVertically = { false }; + final boolean[] rendererActive = { true }; + + final GLEventListener preTileGLEL = new GLEventListener() { + final int w = 50, h = 50; + int dx = 0, dy = 0; + + @Override + public void init(GLAutoDrawable drawable) { + gears.setDoRotation(false); + final GL gl = drawable.getGL(); + GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); + GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + renderer.setImageBuffer(pixelBuffer); + if( drawable.isGLOriented() ) { + flipVertically[0] = false; + } else { + flipVertically[0] = true; + } + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) { + if( dx+w <= imageWidth && dy+h <= imageHeight ) { + System.err.println("XXX setTileRect["+dx+"/"+dy+" "+w+"x"+h+"]"); + renderer.setTileRect(dx, dy, w, h); + dx+=w+w/2; + if( dx + w > imageWidth ) { + dx = 0; + dy+=h+h/2; + } + } else if( rendererActive[0] ) { + System.err.println("XXX active -> false"); + rendererActive[0] = false; + } + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }; + final GLEventListener postTileGLEL = new GLEventListener() { + @Override + public void init(GLAutoDrawable drawable) {} + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void display(GLAutoDrawable drawable) { + if( !rendererActive[0] ) { + final GLPixelBuffer imageBuffer = renderer.getImageBuffer(); + imageBuffer.clear(); // full size available + System.err.println("XXX !active -> save"); + System.err.println("XXX2: "+imageBuffer); + final TextureData textureData = new TextureData( + caps.getGLProfile(), + 0 /* internalFormat */, + imageWidth, imageHeight, + 0, + imageBuffer.pixelAttributes, + false, false, + flipVertically[0], + imageBuffer.buffer, + null /* Flusher */); + System.err.println("XXX3: "+textureData.getPixelFormat()+", "+textureData.getPixelAttributes()); + try { + final String filename = getSnapshotFilename(0, "-tile", glad.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null); + final File file = new File(filename); + TextureIO.write(textureData, file); + } catch (IOException e) { + e.printStackTrace(); + } + gears.setTileRenderer(null); + renderer.detachFromAutoDrawable(); + System.err.println("XXX detach: glel "+glad.getGLEventListener(0)); + System.err.println("XXX detach: "+animator); + drawable.getGL().glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); + glad.getGLEventListener(0).reshape(drawable, 0, 0, drawable.getWidth(), drawable.getHeight()); + gears.setDoRotation(true); + } + } + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + }; + renderer.setGLEventListener(preTileGLEL, postTileGLEL); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + + boolean signalTileRenderer = true; + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && + ( rendererActive[0] || animator.getTotalFPSDuration()<duration ) ) + { + if( signalTileRenderer && animator.getTotalFPSDuration() > 90 ) { + signalTileRenderer = false; + // tile rendering ! + System.err.println("XXX START TILE RENDERING"); + gears.setTileRenderer(renderer); + renderer.attachToAutoDrawable(glad); + System.err.println("XXX attach: glel "+glad.getGLEventListener(0)); + System.err.println("XXX attach: "+animator); + } + Thread.sleep(100); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glad); + Assert.assertNotNull(animator); + + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.remove(glad); + frame.dispose(); + }}); + } + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + org.junit.runner.JUnitCore.main(TestRandomTiledRendering3GL2AWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2.java index 5b628091b..24466e32e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2.java @@ -1,3 +1,30 @@ +/** + * Copyright 2013 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.tile; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; @@ -5,26 +32,37 @@ import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.GLPixelBuffer; import com.jogamp.opengl.util.TileRenderer; import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; +import com.jogamp.opengl.util.TileRendererBase; import com.jogamp.opengl.util.texture.TextureData; import com.jogamp.opengl.util.texture.TextureIO; 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.GLContext; +import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; +import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; -/** Demonstrates the TileRenderer class by rendering a large version - of the Gears demo to the specified file. */ +/** + * Demos offscreen {@link GLDrawable} being used for + * {@link TileRenderer} rendering to produce a PNG file. + * <p> + * All {@link TileRenderer} operations are + * being performed from the main thread sequentially + * without {@link GLAutoDrawable} or {@link GLEventListener}. + * </p> +*/ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestTiledRendering1GL2 extends UITestCase { static long duration = 500; // ms @@ -34,110 +72,78 @@ public class TestTiledRendering1GL2 extends UITestCase { doTest(); } - void doTest() throws IOException { - GLCapabilities caps = new GLCapabilities(null); - caps.setDoubleBuffered(false); + static class DrawableContext { + DrawableContext(GLDrawable d, GLContext glc) { + this.d = d; + this.glc = glc; + } + GLDrawable d; + GLContext glc; + } + + private static DrawableContext createDrawableAndCurrentCtx(GLCapabilities glCaps, int width, int height) { + GLDrawableFactory factory = GLDrawableFactory.getFactory(glCaps.getGLProfile()); + GLDrawable d = factory.createOffscreenDrawable(null, glCaps, null, width, height); + d.setRealized(true); + GLContext glc = null; + glc = d.createContext(null); + Assert.assertTrue("Context could not be made current", GLContext.CONTEXT_NOT_CURRENT < glc.makeCurrent()); + return new DrawableContext(d, glc); + } + + private static void destroyDrawableContext(DrawableContext dc) { + if(null != dc.glc) { + dc.glc.destroy(); + dc.glc = null; + } + if(null != dc.d) { + dc.d.setRealized(false); + dc.d = null; + } + } - // Use a pbuffer for rendering - final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); - final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, caps, null, 256, 256, null); - + void doTest() throws GLException, IOException { + GLProfile glp = GLProfile.getMaxFixedFunc(true); + GLCapabilities caps = new GLCapabilities(glp); + caps.setOnscreen(false); + + DrawableContext dc = createDrawableAndCurrentCtx(caps, 256, 256); + final GL2 gl = dc.glc.getGL().getGL2(); + // Fix the image size for now - final int imageWidth = glad.getWidth() * 6; - final int imageHeight = glad.getHeight() * 4; + final int imageWidth = dc.d.getWidth() * 6; + final int imageHeight = dc.d.getHeight() * 4; - final String filename = this.getSnapshotFilename(0, "-tile", glad.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null); + final String filename = this.getSnapshotFilename(0, "-tile", dc.d.getChosenGLCapabilities(), imageWidth, imageHeight, false, TextureIO.PNG, null); final File file = new File(filename); // Initialize the tile rendering library - final TileRenderer renderer = new com.jogamp.opengl.util.TileRenderer(); - final TileRenderer.PMVMatrixCallback pmvMatrixCallback = new TileRenderer.PMVMatrixCallback() { - public void reshapePMVMatrix(GL _gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) { - final GL2 gl = _gl.getGL2(); - gl.glMatrixMode( GL2.GL_PROJECTION ); - gl.glLoadIdentity(); - - /* compute projection parameters */ - float left, right, bottom, top; - if( imageHeight > imageWidth ) { - float a = (float)imageHeight / (float)imageWidth; - left = -1.0f; - right = 1.0f; - bottom = -a; - top = a; - } else { - float a = (float)imageWidth / (float)imageHeight; - left = -a; - right = a; - bottom = -1.0f; - top = 1.0f; - } - final float w = right - left; - final float h = top - bottom; - final float l = left + w * tileX / imageWidth; - final float r = l + w * tileWidth / imageWidth; - final float b = bottom + h * tileY / imageHeight; - final float t = b + h * tileHeight / imageHeight; - - final float _w = r - l; - final float _h = t - b; - System.err.println(">> [l "+left+", r "+right+", b "+bottom+", t "+top+"] "+w+"x"+h+" -> [l "+l+", r "+r+", b "+b+", t "+t+"] "+_w+"x"+_h); - gl.glFrustum(l, r, b, t, 5.0f, 60.0f); - - gl.glMatrixMode(GL2.GL_MODELVIEW); - } - }; - - renderer.setTileSize(glad.getWidth(), glad.getHeight(), 0); - renderer.setPMVMatrixCallback(pmvMatrixCallback); + final TileRenderer renderer = new com.jogamp.opengl.util.TileRenderer(); + renderer.setTileSize(dc.d.getWidth(), dc.d.getHeight(), 0); renderer.setImageSize(imageWidth, imageHeight); final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride; final boolean[] flipVertically = { false }; - glad.addGLEventListener( new GLEventListener() { - @Override - public void init(GLAutoDrawable drawable) { - final GL gl = drawable.getGL(); - GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); - GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); - renderer.setImageBuffer(pixelBuffer); - if( drawable.isGLOriented() ) { - flipVertically[0] = false; - } else { - flipVertically[0] = true; - } - } - @Override - public void dispose(GLAutoDrawable drawable) {} - @Override - public void display(GLAutoDrawable drawable) { - renderer.beginTile(drawable.getGL().getGL2()); - } - @Override - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} - }); + GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3); + GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0); + renderer.setImageBuffer(pixelBuffer); + flipVertically[0] = false; + final Gears gears = new Gears(); gears.setDoRotation(false); - glad.addGLEventListener( gears ); - glad.addGLEventListener( new GLEventListener() { - @Override - public void init(GLAutoDrawable drawable) {} - @Override - public void dispose(GLAutoDrawable drawable) {} - @Override - public void display(GLAutoDrawable drawable) { - renderer.endTile(drawable.getGL().getGL2()); - } - @Override - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} - }); - - do { - glad.display(); + gears.init(gl); + + gears.setTileRenderer(renderer); + do { + renderer.beginTile(dc.glc.getGL().getGL2ES3()); + gears.reshape(gl, 0, 0, renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT)); + gears.display(gl); + renderer.endTile(dc.glc.getGL().getGL2ES3()); } while ( !renderer.eot() ); - - glad.destroy(); + gears.setTileRenderer(null); + + destroyDrawableContext(dc); final GLPixelBuffer imageBuffer = renderer.getImageBuffer(); final TextureData textureData = new TextureData( diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2GL2.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2GL2.java index d750ca853..6fd13538b 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2GL2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2GL2.java @@ -1,9 +1,37 @@ +/** + * Copyright 2013 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.tile; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.util.GLPixelBuffer; import com.jogamp.opengl.util.TileRenderer; +import com.jogamp.opengl.util.TileRendererBase; import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes; import com.jogamp.opengl.util.texture.TextureData; import com.jogamp.opengl.util.texture.TextureIO; @@ -11,19 +39,35 @@ import com.jogamp.opengl.util.texture.TextureIO; 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.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLRunnable; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; -/** Demonstrates the TileRenderer class by rendering a large version - of the Gears demo to the specified file. */ +/** + * Demos offscreen {@link GLAutoDrawable} being used for + * {@link TileRenderer} rendering to produce a PNG file. + * <p> + * {@link TileRenderer} is being kicked off from the main thread. + * </p> + * <p> + * {@link TileRenderer} buffer allocation is performed + * within the pre {@link GLEventListener} + * set via {@link TileRendererBase#setGLEventListener(GLEventListener, GLEventListener)} + * on the main thread. + * </p> + * <p> + * At tile rendering finish, the viewport and + * and the original {@link GLEventListener}'s PMV matrix as well. + * The latter is done by calling it's {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int) reshape} method. + * </p> +*/ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestTiledRendering2GL2 extends UITestCase { static long duration = 500; // ms @@ -37,7 +81,6 @@ public class TestTiledRendering2GL2 extends UITestCase { GLCapabilities caps = new GLCapabilities(null); caps.setDoubleBuffered(false); - // Use a pbuffer for rendering final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, caps, null, 256, 256, null); @@ -54,44 +97,8 @@ public class TestTiledRendering2GL2 extends UITestCase { // Initialize the tile rendering library final TileRenderer renderer = new TileRenderer(); - final TileRenderer.PMVMatrixCallback pmvMatrixCallback = new TileRenderer.PMVMatrixCallback() { - public void reshapePMVMatrix(GL _gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) { - final GL2 gl = _gl.getGL2(); - gl.glMatrixMode( GL2.GL_PROJECTION ); - gl.glLoadIdentity(); - - /* compute projection parameters */ - float left, right, bottom, top; - if( imageHeight > imageWidth ) { - float a = (float)imageHeight / (float)imageWidth; - left = -1.0f; - right = 1.0f; - bottom = -a; - top = a; - } else { - float a = (float)imageWidth / (float)imageHeight; - left = -a; - right = a; - bottom = -1.0f; - top = 1.0f; - } - final float w = right - left; - final float h = top - bottom; - final float l = left + w * tileX / imageWidth; - final float r = l + w * tileWidth / imageWidth; - final float b = bottom + h * tileY / imageHeight; - final float t = b + h * tileHeight / imageHeight; - - final float _w = r - l; - final float _h = t - b; - System.err.println(">> [l "+left+", r "+right+", b "+bottom+", t "+top+"] "+w+"x"+h+" -> [l "+l+", r "+r+", b "+b+", t "+t+"] "+_w+"x"+_h); - gl.glFrustum(l, r, b, t, 5.0f, 60.0f); - - gl.glMatrixMode(GL2.GL_MODELVIEW); - } - }; - - renderer.attachToAutoDrawable(glad, pmvMatrixCallback); + gears.setTileRenderer(renderer); + renderer.attachToAutoDrawable(glad); renderer.setImageSize(imageWidth, imageHeight); final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride; @@ -124,6 +131,18 @@ public class TestTiledRendering2GL2 extends UITestCase { } while ( !renderer.eot() ); renderer.detachFromAutoDrawable(); + gears.setTileRenderer(null); + + // Restore viewport and Gear's PMV matrix + // .. even though we close the demo, this is for documentation! + glad.invoke(true, new GLRunnable() { + @Override + public boolean run(GLAutoDrawable drawable) { + drawable.getGL().glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); + gears.reshape(drawable, 0, 0, drawable.getWidth(), drawable.getHeight()); + return false; + } + }); glad.destroy(); |