From 58682d84c09462b1f2798b847ade6624b89d962f Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Wed, 4 Sep 2013 19:23:23 +0200
Subject: TileRenderer*: Align impl. to common abstract superclass
 TileRendererBase (cleanup / API doc)

---
 .../com/jogamp/opengl/util/RandomTileRenderer.java | 233 +++++------------
 .../com/jogamp/opengl/util/TileRenderer.java       | 250 +++---------------
 .../com/jogamp/opengl/util/TileRendererBase.java   | 281 +++++++++++++++++++++
 3 files changed, 380 insertions(+), 384 deletions(-)
 create mode 100644 src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java

(limited to 'src/jogl/classes/com')

diff --git a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
index ac420da3d..0fba1170d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
@@ -27,8 +27,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;
@@ -38,128 +36,80 @@ import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
 /**
  * Variation of {@link TileRenderer} w/o using fixed tiles but arbitrary rectangular regions. 
  */
-public class RandomTileRenderer {
-    private final Dimension imageSize = new Dimension(0, 0);
-    private final GLPixelStorageModes psm = new GLPixelStorageModes();
-
-    private GLPixelBuffer imageBuffer;
-    private GLPixelBuffer tileBuffer;
-    private PMVMatrixCallback pmvMatrixCB = null;
-    private int tX = 0;
-    private int tY = 0;
-    private int tWidth = 0;
-    private int tHeight = 0;
-
-    private GLAutoDrawable glad;
-    private GLEventListener[] listeners;
-    private boolean[] listenersInit;
-    private GLEventListener glEventListenerPre = null;
-    private GLEventListener glEventListenerPost = null;
+public class RandomTileRenderer extends TileRendererBase {
+    private boolean tileRectSet = false;
     
-    public static interface PMVMatrixCallback {
-        void reshapePMVMatrix(GL gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight);      
-    }
-
     /**
      * Creates a new TileRenderer object
      */
     public RandomTileRenderer() {
+        super();
     }
 
-    public final void setPMVMatrixCallback(PMVMatrixCallback pmvMatrixCB) {
-        assert ( null != pmvMatrixCB );
-        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.
-     * 
-     * @param buffer The buffer itself. Must be large enough to contain a random tile
-     */
-    public final void setTileBuffer(GLPixelBuffer buffer) {
-        tileBuffer = buffer;
-    }
-
-    /** @see #setTileBuffer(GLPixelBuffer) */
-    public final GLPixelBuffer getTileBuffer() { return tileBuffer; }
-    
-    /**
-     * Sets the desired size of the final image
-     * 
-     * @param width
-     *           The width of the final image
-     * @param height
-     *           The height of the final image
-     */
-    public final void setImageSize(int width, int height) {
-        imageSize.setWidth(width);
-        imageSize.setHeight(height);
+    @Override
+    public final int getParam(int param) {
+        switch (param) {
+        case TR_IMAGE_WIDTH:
+            return imageSize.getWidth();
+        case TR_IMAGE_HEIGHT:
+            return imageSize.getHeight();
+        case TR_CURRENT_TILE_X_POS:
+            return currentTileXPos;
+        case TR_CURRENT_TILE_Y_POS:
+            return currentTileYPos;
+        case TR_CURRENT_TILE_WIDTH:
+            return currentTileWidth;
+        case TR_CURRENT_TILE_HEIGHT:
+            return currentTileHeight;
+        default:
+            throw new IllegalArgumentException("Invalid enumerant as argument");
+        }
     }
-    
-    /** @see #setImageSize(int, int) */
-    public final Dimension getImageSize() { return imageSize; }
 
     /**
-     * Sets the buffer in which to store the final image
+     * Set the tile rectangle for the subsequent rendering calls.
      * 
-     * @param buffer the buffer itself, must be large enough to hold the final image
+     * @throws IllegalArgumentException is tile x/y are < 0 or tile size is <= 0x0                              
      */
-    public final void setImageBuffer(GLPixelBuffer buffer) {
-        imageBuffer = buffer;
+    public void setTileRect(int tX, int tY, int tWidth, int tHeight) throws IllegalStateException, IllegalArgumentException {
+        if( 0 > tX || 0 > tX ) {
+            throw new IllegalArgumentException("Tile pos must be >= 0/0");        
+        }
+        if( 0 >= tWidth || 0 >= tHeight ) {
+            throw new IllegalArgumentException("Tile size must be > 0x0");        
+        }
+        this.currentTileXPos = tX;
+        this.currentTileYPos = tY;
+        this.currentTileWidth = tWidth;
+        this.currentTileHeight = tHeight;
+        tileRectSet = true;
     }
-
-    /** @see #setImageBuffer(GLPixelBuffer) */
-    public final GLPixelBuffer getImageBuffer() { return imageBuffer; }
     
     /**
-     * Begins rendering a tile.
-     * <p>
-     * Methods modifies the viewport, hence user shall reset the viewport when finishing tile rendering.
-     * </p>
-     * <p> 
-     * The projection matrix stack should be
-     * left alone after calling this method!
-     * </p>
-     * 
-     * @param gl The gl context
-     * @throws IllegalStateException
-     * @throws IllegalArgumentException
+     * {@inheritDoc}
+     * @throws IllegalStateException if image-size, pmvMatrixCB or tileRect has not been set
      */
-    public final void beginTile(GL2ES3 gl, int tX, int tY, int tWidth, int tHeight) throws IllegalStateException, IllegalArgumentException {
+    @Override
+    public final void beginTile(GL2ES3 gl) throws IllegalStateException {
         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( 0 > tX || 0 > tX ) {
-            throw new IllegalArgumentException("Tile pos must be >= 0/0");        
-        }
-        if( 0 >= tWidth || 0 >= tHeight ) {
-            throw new IllegalArgumentException("Tile size must be > 0x0");        
+        if( !tileRectSet ) {
+            throw new IllegalStateException("tileRect has not been set");
         }
         
-        gl.glViewport( 0, 0, tWidth, tHeight );
-        pmvMatrixCB.reshapePMVMatrix(gl, tX, tY, tWidth, tHeight, imageSize.getWidth(), imageSize.getHeight());
+        gl.glViewport( 0, 0, currentTileWidth, currentTileHeight );
+        pmvMatrixCB.reshapePMVMatrix(gl, currentTileXPos, currentTileYPos, currentTileWidth, currentTileHeight, imageSize.getWidth(), imageSize.getHeight());
         
-        this.tX = tX;
-        this.tY = tY;
-        this.tWidth = tWidth;
-        this.tHeight = tHeight;
+        beginCalled = true;
     }
-    
-    /**
-     * Must be called after rendering the scene
-     * 
-     * @param gl
-     *           the gl context
-     * @return true if there are more tiles to be rendered, false if
-     *         the final image is complete
-     */
-    public void endTile( GL2ES3 gl )  {
-        if( 0 >= tWidth || 0 >= tHeight ) {
+
+    @Override
+    public void endTile( GL2ES3 gl ) throws IllegalStateException {
+        if( !beginCalled ) {
             throw new IllegalStateException("beginTile(..) has not been called");
         }
         
@@ -175,8 +125,8 @@ public class RandomTileRenderer {
             final GLPixelAttributes pixelAttribs = tileBuffer.pixelAttributes;
             final int srcX = 0;
             final int srcY = 0;
-            final int srcWidth = tWidth;
-            final int srcHeight = tHeight;
+            final int srcWidth = currentTileWidth;
+            final int srcHeight = currentTileHeight;
             final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
             tileBuffer.clear();
             if( tileBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
@@ -193,8 +143,8 @@ public class RandomTileRenderer {
             final GLPixelAttributes pixelAttribs = imageBuffer.pixelAttributes;
             final int srcX = 0;
             final int srcY = 0;
-            final int srcWidth = tWidth;
-            final int srcHeight = tHeight;
+            final int srcWidth = currentTileWidth;
+            final int srcHeight = currentTileHeight;
 
             /* setup pixel store for glReadPixels */
             final int rowLength = imageSize.getWidth();
@@ -204,7 +154,7 @@ public class RandomTileRenderer {
             /* read the tile into the final image */
             final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
 
-            final int ibPos = ( tX + ( tY * rowLength ) ) * pixelAttribs.bytesPerPixel; // skipPixels + skipRows
+            final int ibPos = ( currentTileXPos + ( currentTileYPos * rowLength ) ) * pixelAttribs.bytesPerPixel; // skipPixels + skipRows
             final int ibLim = ibPos + readPixelSize;
             imageBuffer.clear();
             if( imageBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
@@ -221,87 +171,22 @@ public class RandomTileRenderer {
 
         /* restore previous glPixelStore values */
         psm.restore(gl);
-
-        this.tX = 0;
-        this.tY = 0;
-        this.tWidth = 0;
-        this.tHeight = 0;
-    }
-    
-    /**
-     * 
-     * <p>
-     * Sets the size of the tiles to use in rendering. The actual
-     * effective size of the tile depends on the border size, ie (
-     * width - 2*border ) * ( height - 2 * border )
-     * </p>
-     * @param glad
-     * @throws IllegalStateException if an {@link GLAutoDrawable} is already attached
-     */
-    public void attachAutoDrawable(GLAutoDrawable glad, PMVMatrixCallback pmvMatrixCB) 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];
-        listenersInit = new boolean[aSz];
-        for(int i=0; i<aSz; i++) {
-            final GLEventListener l = glad.getGLEventListener(0);
-            listenersInit[i] = glad.getGLEventListenerInitState(l);
-            listeners[i] = glad.removeGLEventListener( l );
-        }
-        glad.addGLEventListener(tiledGLEL);
-    }
-
-    public void detachAutoDrawable() {
-        if( null != glad ) {
-            glad.removeGLEventListener(tiledGLEL);
-            final int aSz = listenersInit.length;
-            for(int i=0; i<aSz; i++) {
-                final GLEventListener l = listeners[i];
-                glad.addGLEventListener(l);
-                glad.setGLEventListenerInitState(l, listenersInit[i]);
-            }
-            listeners = null;
-            listenersInit = null;
-            glad = null;
-            pmvMatrixCB = null;
-        }
-    }
-
-    /**
-     * Set {@link GLEventListener} for pre- and post operations when used w/ 
-     * {@link #attachAutoDrawable(GLAutoDrawable, int, PMVMatrixCallback)}
-     * for each {@link GLEventListener} callback.
-     * @param preTile the pre operations
-     * @param postTile the post operations
-     */
-    public void setGLEventListener(GLEventListener preTile, GLEventListener postTile) {
-        glEventListenerPre = preTile;
-        glEventListenerPost = postTile;
+        beginCalled = false;
     }
     
     /**
      * Rendering one tile, by simply calling {@link GLAutoDrawable#display()}.
      * 
-     * @return true if there are more tiles to be rendered, false if the final image is complete
-     * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachAutoDrawable(GLAutoDrawable, int) attached}
+     * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachToAutoDrawable(GLAutoDrawable, int) attached}
      *                               or imageSize is not set
      */
     public void display(int tX, int tY, int tWidth, int tHeight) throws IllegalStateException {
-        if( null == glad ) {
-            throw new IllegalStateException("No GLAutoDrawable attached");
-        }
-        this.tX = tX;
-        this.tY = tY;
-        this.tWidth = tWidth;
-        this.tHeight = tHeight;
-        glad.display();
+        setTileRect(tX, tY, tWidth, tHeight);
+        display();
     }
 
+    protected final GLEventListener getTiledGLEL() { return tiledGLEL; }
     private final GLEventListener tiledGLEL = new GLEventListener() {
         @Override
         public void init(GLAutoDrawable drawable) {
@@ -338,7 +223,7 @@ public class RandomTileRenderer {
             }
             final GL2ES3 gl = drawable.getGL().getGL2ES3();
 
-            beginTile(gl, tX, tY, tWidth, tHeight);
+            beginTile(gl);
 
             final int aSz = listenersInit.length;
             for(int i=0; i<aSz; i++) {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
index c7c94c8da..a63694207 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.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;
@@ -60,103 +59,69 @@ import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
  * 
  * @author ryanm, sgothel
  */
-public class TileRenderer {
+public class TileRenderer extends TileRendererBase {
     /**
      * The width of a tile
      */
-    public static final int TR_TILE_WIDTH = 0;
+    public static final int TR_TILE_WIDTH = 7;
     /**
      * The height of a tile
      */
-    public static final int TR_TILE_HEIGHT = 1;
+    public static final int TR_TILE_HEIGHT = 8;
     /**
      * The width of the border around the tiles
      */
-    public static final int TR_TILE_BORDER = 2;
-    /**
-     * The width of the final image
-     */
-    public static final int TR_IMAGE_WIDTH = 3;
-    /**
-     * The height of the final image
-     */
-    public static final int TR_IMAGE_HEIGHT = 4;
+    public static final int TR_TILE_BORDER = 9;
     /**
      * The number of rows of tiles
      */
-    public static final int TR_ROWS = 5;
+    public static final int TR_ROWS = 10;
     /**
      * The number of columns of tiles
      */
-    public static final int TR_COLUMNS = 6;
+    public static final int TR_COLUMNS = 11;
     /**
      * The current row number
      */
-    public static final int TR_CURRENT_ROW = 7;
+    public static final int TR_CURRENT_ROW = 12;
     /**
      * The current column number
      */
-    public static final int TR_CURRENT_COLUMN = 8;
-    /**
-     * The width of the current tile
-     */
-    public static final int TR_CURRENT_TILE_WIDTH = 9;
-    /**
-     * The height of the current tile
-     */
-    public static final int TR_CURRENT_TILE_HEIGHT = 10;
+    public static final int TR_CURRENT_COLUMN = 13;
     /**
      * The order that the rows are traversed
      */
-    public static final int TR_ROW_ORDER = 11;
+    public static final int TR_ROW_ORDER = 14;
     /**
      * Indicates we are traversing rows from the top to the bottom
      */
-    public static final int TR_TOP_TO_BOTTOM = 1;
+    public static final int TR_TOP_TO_BOTTOM = 15;
     /**
      * Indicates we are traversing rows from the bottom to the top
      */
-    public static final int TR_BOTTOM_TO_TOP = 2;
+    public static final int TR_BOTTOM_TO_TOP = 16;
 
     private static final boolean DEBUG = true;
     private static final int DEFAULT_TILE_WIDTH = 256;
     private static final int DEFAULT_TILE_HEIGHT = 256;
     private static final int DEFAULT_TILE_BORDER = 0;
 
-    private final Dimension imageSize = new Dimension(0, 0);
     private final Dimension tileSize = new Dimension(DEFAULT_TILE_WIDTH, DEFAULT_TILE_HEIGHT);
     private final Dimension tileSizeNB = new Dimension(DEFAULT_TILE_WIDTH - 2 * DEFAULT_TILE_BORDER, DEFAULT_TILE_HEIGHT - 2 * DEFAULT_TILE_BORDER);
-    private final int[] userViewport = new int[ 4 ];
-    private final GLPixelStorageModes psm = new GLPixelStorageModes();
 
     private int tileBorder = DEFAULT_TILE_BORDER;
-    private GLPixelBuffer imageBuffer;
-    private GLPixelBuffer tileBuffer;
     private int rowOrder = TR_BOTTOM_TO_TOP;
     private int rows;
     private int columns;
     private int currentTile = -1;
-    private int currentTileWidth;
-    private int currentTileHeight;
     private int currentRow;
     private int currentColumn;
-    private PMVMatrixCallback pmvMatrixCB = null;
-    private boolean beginCalled = false;
-
-    private GLAutoDrawable glad;
-    private GLEventListener[] listeners;
-    private boolean[] listenersInit;
-    private GLEventListener glEventListenerPre = null;
-    private GLEventListener glEventListenerPost = null;
-    
-    public static interface PMVMatrixCallback {
-        void reshapePMVMatrix(GL gl, int tileNum, int tileColumn, int tileRow, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight);      
-    }
 
     /**
      * Creates a new TileRenderer object
      */
     public TileRenderer() {
+        super();
     }
 
     /**
@@ -190,11 +155,6 @@ public class TileRenderer {
         setup();
     }
 
-    public final void setPMVMatrixCallback(PMVMatrixCallback pmvMatrixCB) {
-        assert ( null != pmvMatrixCB );
-        this.pmvMatrixCB = pmvMatrixCB; 
-    }
-
     /**
      * Sets up the number of rows and columns needed
      */
@@ -202,6 +162,8 @@ public class TileRenderer {
         columns = ( imageSize.getWidth() + tileSizeNB.getWidth() - 1 ) / tileSizeNB.getWidth();
         rows = ( imageSize.getHeight() + tileSizeNB.getHeight() - 1 ) / tileSizeNB.getHeight();
         currentTile = 0;
+        currentTileXPos = 0;
+        currentTileYPos = 0;
         currentTileWidth = 0;
         currentTileHeight = 0;
         currentRow = 0;
@@ -217,56 +179,7 @@ public class TileRenderer {
      */
     public final boolean eot() { return 0 > currentTile; }
 
-    /**
-     * 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.
-     * 
-     * @param buffer The buffer itself. Must be large enough to contain a tile, minus any borders
-     */
-    public final void setTileBuffer(GLPixelBuffer buffer) {
-        tileBuffer = buffer;
-    }
-
-    /** @see #setTileBuffer(GLPixelBuffer) */
-    public final GLPixelBuffer getTileBuffer() { return tileBuffer; }
-
-    /**
-     * Sets the desired size of the final image
-     * 
-     * @param width
-     *           The width of the final image
-     * @param height
-     *           The height of the final image
-     */
-    public final void setImageSize(int width, int height) {
-        imageSize.setWidth(width);
-        imageSize.setHeight(height);
-        setup();
-    }
-
-    /** @see #setImageSize(int, int) */
-    public final Dimension getImageSize() { return imageSize; }
-    
-    /**
-     * Sets the buffer in which to store the final image
-     * 
-     * @param image the buffer itself, must be large enough to hold the final image
-     */
-    public final void setImageBuffer(GLPixelBuffer buffer) {
-        imageBuffer = buffer;
-    }
-
-    /** @see #setImageBuffer(GLPixelBuffer) */
-    public final GLPixelBuffer getImageBuffer() { return imageBuffer; }
-    
-    /**
-     * Gets the parameters of this TileRenderer object
-     * 
-     * @param param
-     *           The parameter that is to be retrieved
-     * @return the value of the parameter
-     */
+    @Override
     public final int getParam(int param) {
         switch (param) {
         case TR_TILE_WIDTH:
@@ -284,15 +197,21 @@ public class TileRenderer {
         case TR_COLUMNS:
             return columns;
         case TR_CURRENT_ROW:
-            if( currentTile < 0 )
+            if( currentTile < 0 ) {
                 return -1;
-            else
+            } else {
                 return currentRow;
+            }
         case TR_CURRENT_COLUMN:
-            if( currentTile < 0 )
+            if( currentTile < 0 ) {
                 return -1;
-            else
+            } else {
                 return currentColumn;
+            }
+        case TR_CURRENT_TILE_X_POS:
+            return currentTileXPos;
+        case TR_CURRENT_TILE_Y_POS:
+            return currentTileYPos;
         case TR_CURRENT_TILE_WIDTH:
             return currentTileWidth;
         case TR_CURRENT_TILE_HEIGHT:
@@ -319,16 +238,7 @@ public class TileRenderer {
         }
     }
 
-    /**
-     * Begins rendering a tile.
-     * <p> 
-     * The projection matrix stack should be
-     * left alone after calling this method!
-     * </p>
-     * 
-     * @param gl The gl context
-     * @throws IllegalStateException
-     */
+    @Override
     public final void beginTile( GL2ES3 gl ) throws IllegalStateException {
         if( 0 >= imageSize.getWidth() || 0 >= imageSize.getHeight() ) {
             throw new IllegalStateException("Image size has not been set");        
@@ -338,11 +248,6 @@ public class TileRenderer {
         }
         if (currentTile <= 0) {
             setup();
-            /*
-             * Save user's viewport, will be restored after last tile
-             * rendered
-             */
-            gl.glGetIntegerv( GL.GL_VIEWPORT, userViewport, 0 );
         }
 
         final int preRow = currentRow;
@@ -376,8 +281,8 @@ public class TileRenderer {
             tW = imageSize.getWidth() - ( columns - 1 ) * ( tileSizeNB.getWidth()  ) + 2 * border;
         }
 
-        final int tX = currentColumn * tileSizeNB.getWidth();
-        final int tY = currentRow * tileSizeNB.getHeight();
+        currentTileXPos = currentColumn * tileSizeNB.getWidth();
+        currentTileYPos = currentRow * tileSizeNB.getHeight();
 
         final int preTileWidth = currentTileWidth;
         final int preTileHeight = currentTileHeight;
@@ -388,24 +293,16 @@ public class TileRenderer {
 
         if( DEBUG ) {
             System.err.println("Tile["+currentTile+"]: ["+preColumn+"]["+preRow+"] "+preTileWidth+"x"+preTileHeight+
-                    " -> ["+currentColumn+"]["+currentRow+"] "+tX+"/"+tY+", "+tW+"x"+tH+", image "+imageSize.getWidth()+"x"+imageSize.getHeight());
+                    " -> ["+currentColumn+"]["+currentRow+"] "+currentTileXPos+"/"+currentTileYPos+", "+tW+"x"+tH+", image "+imageSize.getWidth()+"x"+imageSize.getHeight());
         }
 
         gl.glViewport( 0, 0, tW, tH );
-        pmvMatrixCB.reshapePMVMatrix(gl, currentTile, currentColumn, currentRow, tX, tY, tW, tH, imageSize.getWidth(), imageSize.getHeight());
+        pmvMatrixCB.reshapePMVMatrix(gl, currentTileXPos, currentTileYPos, tW, tH, imageSize.getWidth(), imageSize.getHeight());
         beginCalled = true;
     }
 
-    /**
-     * Must be called after rendering the scene
-     * 
-     * @param gl
-     *           the gl context
-     * @return true if there are more tiles to be rendered, false if
-     *         the final image is complete
-     * @throws IllegalStateException
-     */
-    public boolean endTile( GL2ES3 gl ) throws IllegalStateException {
+    @Override
+    public void endTile( GL2ES3 gl ) throws IllegalStateException {
         if( !beginCalled ) {
             throw new IllegalStateException("beginTile(..) has not been called");
         }
@@ -476,91 +373,24 @@ public class TileRenderer {
         /* increment tile counter, return 1 if more tiles left to render */
         currentTile++;
         if( currentTile >= rows * columns ) {
-            /* restore user's viewport */
-            gl.glViewport( userViewport[ 0 ], userViewport[ 1 ], userViewport[ 2 ], userViewport[ 3 ] );
             currentTile = -1; /* all done */
-            return false;
-        } else {
-            return true;
         }
     }
     
     /**
-     * 
+     * {@inheritDoc}
      * <p>
-     * Sets the size of the tiles to use in rendering. The actual
-     * effective size of the tile depends on the border size, ie (
-     * width - 2*border ) * ( height - 2 * border )
+     * Sets the tile size of this renderer to the given {@link GLAutoDrawable} size
+     * with zero tile border. 
      * </p>
-     * @param glad
-     * @param border
-     *           The width of the borders on each tile. This is needed
-     *           to avoid artifacts when rendering lines or points with
-     *           thickness > 1.
-     * @throws IllegalStateException if an {@link GLAutoDrawable} is already attached
      */
-    public void attachAutoDrawable(GLAutoDrawable glad, int border, PMVMatrixCallback pmvMatrixCB) throws IllegalStateException {
-        if( null != this.glad ) {
-            throw new IllegalStateException("GLAutoDrawable already attached");
-        }
-        this.glad = glad;
-        setTileSize(glad.getWidth(), glad.getHeight(), border);
-        setPMVMatrixCallback(pmvMatrixCB);
-        
-        final int aSz = glad.getGLEventListenerCount();
-        listeners = new GLEventListener[aSz];
-        listenersInit = new boolean[aSz];
-        for(int i=0; i<aSz; i++) {
-            final GLEventListener l = glad.getGLEventListener(0);
-            listenersInit[i] = glad.getGLEventListenerInitState(l);
-            listeners[i] = glad.removeGLEventListener( l );
-        }
-        glad.addGLEventListener(tiledGLEL);
-    }
-
-    public void detachAutoDrawable() {
-        if( null != glad ) {
-            glad.removeGLEventListener(tiledGLEL);
-            final int aSz = listenersInit.length;
-            for(int i=0; i<aSz; i++) {
-                final GLEventListener l = listeners[i];
-                glad.addGLEventListener(l);
-                glad.setGLEventListenerInitState(l, listenersInit[i]);
-            }
-            listeners = null;
-            listenersInit = null;
-            glad = null;
-            pmvMatrixCB = null;
-        }
-    }
-
-    /**
-     * Set {@link GLEventListener} for pre- and post operations when used w/ 
-     * {@link #attachAutoDrawable(GLAutoDrawable, int, PMVMatrixCallback)}
-     * for each {@link GLEventListener} callback.
-     * @param preTile the pre operations
-     * @param postTile the post operations
-     */
-    public void setGLEventListener(GLEventListener preTile, GLEventListener postTile) {
-        glEventListenerPre = preTile;
-        glEventListenerPost = postTile;
+    @Override
+    public void attachToAutoDrawable(GLAutoDrawable glad, PMVMatrixCallback pmvMatrixCB) throws IllegalStateException {
+        super.attachToAutoDrawable(glad, pmvMatrixCB);
+        setTileSize(glad.getWidth(), glad.getHeight(), 0);
     }
     
-    /**
-     * Rendering one tile, by simply calling {@link GLAutoDrawable#display()}.
-     * 
-     * @return true if there are more tiles to be rendered, false if the final image is complete
-     * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachAutoDrawable(GLAutoDrawable, int) attached}
-     *                               or imageSize is not set
-     */
-    public boolean display() throws IllegalStateException {
-        if( null == glad ) {
-            throw new IllegalStateException("No GLAutoDrawable attached");
-        }
-        glad.display();
-        return !eot();
-    }
-
+    protected final GLEventListener getTiledGLEL() { return tiledGLEL; }
     private final GLEventListener tiledGLEL = new GLEventListener() {
         @Override
         public void init(GLAutoDrawable drawable) {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
new file mode 100644
index 000000000..3aa6ea786
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
@@ -0,0 +1,281 @@
+/**
+ * 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.
+ * 
+ * ---------------------
+ * 
+ * Based on Brian Paul's tile rendering library, found
+ * at <a href = "http://www.mesa3d.org/brianp/TR.html">http://www.mesa3d.org/brianp/TR.html</a>.
+ * 
+ * Copyright (C) 1997-2005 Brian Paul. 
+ * Licensed under BSD-compatible terms with permission of the author. 
+ * See LICENSE.txt for license information.
+ */
+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;
+
+/**
+ * A fairly direct port of Brian Paul's tile rendering library, found
+ * at <a href = "http://www.mesa3d.org/brianp/TR.html">
+ * http://www.mesa3d.org/brianp/TR.html </a> . I've java-fied it, but
+ * the functionality is the same.
+ * <p>
+ * Original code Copyright (C) 1997-2005 Brian Paul. Licensed under
+ * BSD-compatible terms with permission of the author. See LICENSE.txt
+ * for license information.
+ * </p>
+ * <p>
+ * Enhanced for {@link GL2ES3}, abstracted to suit {@link TileRenderer} and {@link RandomTileRenderer}.
+ * </p>
+ * 
+ * @author ryanm, sgothel
+ */
+public abstract class TileRendererBase {
+    /**
+     * The width of the final image
+     */
+    public static final int TR_IMAGE_WIDTH = 1;
+    /**
+     * The height of the final image
+     */
+    public static final int TR_IMAGE_HEIGHT = 2;
+    /**
+     * The width of the current tile
+     */
+    public static final int TR_CURRENT_TILE_X_POS = 3;
+    /**
+     * The height of the current tile
+     */
+    public static final int TR_CURRENT_TILE_Y_POS = 4;
+    /**
+     * The width of the current tile
+     */
+    public static final int TR_CURRENT_TILE_WIDTH = 5;
+    /**
+     * The height of the current tile
+     */
+    public static final int TR_CURRENT_TILE_HEIGHT = 6;
+    
+    protected final Dimension imageSize = new Dimension(0, 0);
+    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;
+    protected int currentTileWidth;
+    protected int currentTileHeight;
+    protected GLAutoDrawable glad;
+    protected GLEventListener[] listeners;
+    protected boolean[] listenersInit;
+    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
+     * @return the value of the parameter
+     * @throws IllegalArgumentException if <code>param</code> is not handled
+     */
+    public abstract int getParam(int param) 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.
+     * 
+     * @param buffer The buffer itself. Must be large enough to contain a random tile
+     */
+    public final void setTileBuffer(GLPixelBuffer buffer) {
+        tileBuffer = buffer;
+    }
+
+    /** @see #setTileBuffer(GLPixelBuffer) */
+    public final GLPixelBuffer getTileBuffer() { return tileBuffer; }
+
+    /**
+     * Sets the desired size of the final image
+     * 
+     * @param width The width of the final image
+     * @param height The height of the final image
+     */
+    public final void setImageSize(int width, int height) {
+        imageSize.setWidth(width);
+        imageSize.setHeight(height);
+    }
+
+    /** @see #setImageSize(int, int) */
+    public final Dimension getImageSize() { return imageSize; }
+
+    /**
+     * Sets the buffer in which to store the final image
+     * 
+     * @param buffer the buffer itself, must be large enough to hold the final image
+     */
+    public final void setImageBuffer(GLPixelBuffer buffer) {
+        imageBuffer = buffer;
+    }
+
+    /** @see #setImageBuffer(GLPixelBuffer) */
+    public final GLPixelBuffer getImageBuffer() { return imageBuffer; }
+
+    /**
+     * 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)}!
+     * </p>
+     * <p> 
+     * The projection matrix stack should be
+     * left alone after calling this method!
+     * </p>
+     * <p>
+     * Use shall render the scene afterwards, concluded with a call to
+     * this renderer {@link #endTile(GL2ES3)}. 
+     * </p>
+     * 
+     * @param gl The gl context
+     * @throws IllegalStateException if image-size or pmvMatrixCB has not been set
+     */
+    public abstract void beginTile(GL2ES3 gl) throws IllegalStateException;
+    
+    /**
+     * Must be called after rendering the scene,
+     * see {@link #beginTile(GL2ES3)}.
+     * 
+     * @param gl the gl context
+     * @throws IllegalStateException if beginTile(gl) has not been called
+     */
+    public abstract void endTile( GL2ES3 gl ) throws IllegalStateException;
+    
+    /**
+     * Attaches this renderer to the {@link GLAutoDrawable}.
+     * <p>
+     * The {@link GLAutoDrawable}'s {@link GLEventListener} are removed first and stored locally.
+     * This renderer {@link GLEventListener} is then added to handle the tile rendering
+     * for the original {@link GLEventListener}.
+     * </p>
+     * <p>
+     * Call {@link #detachFromAutoDrawable()} to remove this renderer from the {@link GLAutoDrawable} 
+     * and to restore it's original {@link GLEventListener}.
+     * </p>
+     * @param glad
+     * @throws IllegalStateException if an {@link GLAutoDrawable} is already attached
+     */
+    public void attachToAutoDrawable(GLAutoDrawable glad, PMVMatrixCallback pmvMatrixCB) 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];
+        listenersInit = new boolean[aSz];
+        for(int i=0; i<aSz; i++) {
+            final GLEventListener l = glad.getGLEventListener(0);
+            listenersInit[i] = glad.getGLEventListenerInitState(l);
+            listeners[i] = glad.removeGLEventListener( l );
+        }
+        glad.addGLEventListener(getTiledGLEL());
+    }
+
+    /**
+     * Detaches this renderer from the {@link GLAutoDrawable}.
+     * <p>
+     * See {@link #attachToAutoDrawable(GLAutoDrawable, PMVMatrixCallback)}.
+     * </p>
+     */
+    public void detachFromAutoDrawable() {
+        if( null != glad ) {
+            glad.removeGLEventListener(getTiledGLEL());
+            final int aSz = listenersInit.length;
+            for(int i=0; i<aSz; i++) {
+                final GLEventListener l = listeners[i];
+                glad.addGLEventListener(l);
+                glad.setGLEventListenerInitState(l, listenersInit[i]);
+            }
+            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)}
+     * for each {@link GLEventListener} callback.
+     * @param preTile the pre operations
+     * @param postTile the post operations
+     */
+    public void setGLEventListener(GLEventListener preTile, GLEventListener postTile) {
+        glEventListenerPre = preTile;
+        glEventListenerPost = postTile;
+    }
+    
+    /**
+     * Rendering one tile, by simply calling {@link GLAutoDrawable#display()}.
+     * 
+     * @throws IllegalStateException if no {@link GLAutoDrawable} is {@link #attachToAutoDrawable(GLAutoDrawable, int) attached}
+     *                               or imageSize is not set
+     */
+    public void display() throws IllegalStateException {
+        if( null == glad ) {
+            throw new IllegalStateException("No GLAutoDrawable attached");
+        }
+        glad.display();
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3