diff options
Diffstat (limited to 'src/jogl')
4 files changed, 275 insertions, 201 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); |