From 2634ce35031be322cb355e4d6055aace6a2c0619 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Sat, 12 Oct 2013 19:00:15 +0200
Subject: Bug 859: Let TileRenderer detect zero columns and rows in eot() where
 beginTile() throws an EOT IllegalStateException to avoid division by zero

---
 make/scripts/tests.sh                              |  4 +-
 .../com/jogamp/opengl/util/RandomTileRenderer.java | 23 +++++-
 .../com/jogamp/opengl/util/TileRenderer.java       | 95 ++++++++++++++++------
 .../com/jogamp/opengl/util/TileRendererBase.java   | 41 +++++++++-
 .../classes/javax/media/opengl/awt/GLCanvas.java   | 32 +++++---
 .../classes/javax/media/opengl/awt/GLJPanel.java   | 29 ++++---
 .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 24 ++++--
 .../opengl/test/junit/jogl/demos/gl2/Gears.java    | 23 +++---
 .../jogl/tile/TestTiledRendering1GL2NEWT.java      | 93 ++++++++++++++++++---
 .../junit/jogl/tile/TestTiledRendering2NEWT.java   |  4 +-
 10 files changed, 282 insertions(+), 86 deletions(-)

diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index eb8a119a7..4b96bd470 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -306,7 +306,7 @@ function testawtswt() {
 #testawtswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
-testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT $*
 #testswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $*
 #testswt com.jogamp.opengl.test.junit.jogl.demos.es2.swt.TestGearsES2SWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT $*
@@ -336,7 +336,7 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT
 #testawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledPrintingGearsSwingAWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledPrintingGearsSwingAWT2 $*
 #testawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledPrintingGearsNewtAWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledPrintingNIOImageSwingAWT $*
+testawt com.jogamp.opengl.test.junit.jogl.tile.TestTiledPrintingNIOImageSwingAWT $*
 
 #
 # core/newt (testnoawt and testawt)
diff --git a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
index 8fc7916c7..a2b7ba343 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
@@ -96,7 +96,28 @@ public class RandomTileRenderer extends TileRendererBase {
     
     /**
      * {@inheritDoc}
-     * @throws IllegalStateException if image-size or tileRect has not been set
+     * 
+     * <p> 
+     * <i>end of tiling</i> is never reached w/ {@link RandomRileRenderer},
+     * i.e. method always returns false.
+     * </p>
+     */
+    @Override
+    public final boolean eot() { return false; }
+    
+    /**
+     * {@inheritDoc}
+     * 
+     * Reset internal states of {@link RandomTileRenderer} are: <i>none</i>.
+     */
+    @Override
+    public final void reset() { }
+    
+    /**
+     * {@inheritDoc}
+     * 
+     * @throws IllegalStateException if {@link #setImageSize(int, int) image-size} has not been set or 
+     *         {@link #setTileRect(int, int, int, int) tile-rect} has not been set.
      */
     @Override
     public final void beginTile(GL gl) throws IllegalStateException, GLException {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
index f126eb7f5..deab8bc3e 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
@@ -101,7 +101,7 @@ public class TileRenderer extends TileRendererBase {
      */
     public static final int TR_COLUMNS = 15;
     /**
-     * The current tile number. See {@link #getParam(int)}.
+     * The current tile number. Has value -1 if {@link #eot()}. See {@link #getParam(int)}.
      */
     public static final int TR_CURRENT_TILE_NUM = 16;
     /**
@@ -132,12 +132,13 @@ public class TileRenderer extends TileRendererBase {
     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);
 
-    protected Dimension imageClippingDim = null; // not set - default
+    private boolean isInit = false;
+    private Dimension imageClippingDim = null; // not set - default
     private int tileBorder = DEFAULT_TILE_BORDER;
     private int rowOrder = TR_BOTTOM_TO_TOP;
     private int rows;
     private int columns;
-    private int currentTile = -1; 
+    private int currentTile = 0;
     private int currentRow;
     private int currentColumn;
     private int offsetX;
@@ -157,6 +158,18 @@ public class TileRenderer extends TileRendererBase {
         super();
     }
 
+    /**
+     * {@inheritDoc}
+     * <p>
+     * Implementation {@link #reset()} internal states.
+     * </p>
+     */
+    @Override
+    public final void setImageSize(int width, int height) {
+        super.setImageSize(width, height);
+        reset();
+    }
+    
     /**
      * Clips the image-size this tile-renderer iterates through,
      * which can be retrieved via {@link #getClippedImageSize()}.
@@ -164,7 +177,7 @@ public class TileRenderer extends TileRendererBase {
      * Original image-size stored in this tile-renderer is unmodified.
      * </p>
      * <p>
-     * Method resets internal state and {@link #TR_ROWS} {@link #TR_COLUMNS} count.
+     * Implementation {@link #reset()} internal states.
      * </p>
      * 
      * @param width The image-clipping.width
@@ -178,7 +191,7 @@ public class TileRenderer extends TileRendererBase {
             imageClippingDim.setWidth(width);
             imageClippingDim.setHeight(height);
         }
-        setup();
+        reset();
     }
 
     /**
@@ -210,7 +223,7 @@ public class TileRenderer extends TileRendererBase {
      * effective size of the tile depends on the border size, ie (
      * width - 2*border ) * ( height - 2 * border )
      * <p>
-     * Method resets internal state and {@link #TR_ROWS} {@link #TR_COLUMNS} count.
+     * Implementation {@link #reset()} internal states.
      * </p>
      * 
      * @param width
@@ -236,7 +249,7 @@ public class TileRenderer extends TileRendererBase {
         tileSize.setHeight( height );
         tileSizeNB.setWidth( width - 2 * border );
         tileSizeNB.setHeight( height - 2 * border );
-        setup();
+        reset();
     }
 
     /** 
@@ -251,32 +264,43 @@ public class TileRenderer extends TileRendererBase {
     }
     
     /**
-     * Sets up the number of rows and columns needed
+     * {@inheritDoc}
+     * 
+     * Reset internal states of {@link TileRenderer} are:
+     * <ul> 
+     *  <li>{@link #TR_ROWS}</li>
+     *  <li>{@link #TR_COLUMNS}</li>
+     *  <li>{@link #TR_CURRENT_COLUMN}</li>
+     *  <li>{@link #TR_CURRENT_ROW}</li>
+     *  <li>{@link #TR_CURRENT_TILE_NUM}</li>
+     *  <li>{@link #TR_CURRENT_TILE_X_POS}</li>
+     *  <li>{@link #TR_CURRENT_TILE_Y_POS}</li>
+     *  <li>{@link #TR_CURRENT_TILE_WIDTH}</li>
+     *  <li>{@link #TR_CURRENT_TILE_HEIGHT}</li>
+     *</ul>
      */
-    private final void setup() throws IllegalStateException {
+    @Override
+    public final void reset() {
         final DimensionImmutable clippedImageSize = getClippedImageSize();
         columns = ( clippedImageSize.getWidth() + tileSizeNB.getWidth() - 1 ) / tileSizeNB.getWidth();
         rows = ( clippedImageSize.getHeight() + tileSizeNB.getHeight() - 1 ) / tileSizeNB.getHeight();
+        currentRow = 0;
+        currentColumn = 0;
         currentTile = 0;
         currentTileXPos = 0;
         currentTileYPos = 0;
         currentTileWidth = 0;
         currentTileHeight = 0;
-        currentRow = 0;
-        currentColumn = 0;
 
         assert columns >= 0;
         assert rows >= 0;
+        
+        beginCalled = false;
+        isInit = true;
     }
 
     /* pp */ final int getCurrentTile() { return currentTile; }
     
-    /** 
-     * Returns <code>true</code> if all tiles have been rendered or {@link #setup()}
-     * has not been called, otherwise <code>false</code>.
-     */
-    public final boolean eot() { return 0 > currentTile; }
-
     @Override
     public final int getParam(int pname) {
         switch (pname) {
@@ -341,16 +365,41 @@ public class TileRenderer extends TileRendererBase {
         return 0 < imageSize.getWidth() && 0 < imageSize.getHeight();
     }
     
+    /**
+     * {@inheritDoc}
+     * 
+     * <p> 
+     * <i>end of tiling</i> is reached w/ {@link TileRenderer}, if at least one of the following is true:
+     * <ul>
+     *   <li>all tiles have been rendered, i.e. {@link #TR_CURRENT_TILE_NUM} is -1</li>
+     *   <li>no tiles to render, i.e. {@link #TR_COLUMNS} or {@link #TR_ROWS} is 0</li>
+     * </ul>
+     * </p>
+     */
+    @Override
+    public final boolean eot() {
+        if ( !isInit ) { // ensure at least one reset-call
+            reset();
+        }
+        return 0 > currentTile || 0 >= columns*rows; 
+    }
+    
+    /**
+     * {@inheritDoc}
+     * 
+     * @throws IllegalStateException if {@link #setImageSize(int, int) image-size} has not been set or 
+     *         {@link #eot() end-of-tiling} has been reached.
+     */
     @Override
     public final void beginTile( GL gl ) throws IllegalStateException, GLException {
         if( !isSetup() ) {
-            throw new IllegalStateException("Image size has not been set");        
+            throw new IllegalStateException("Image size has not been set: "+this);
         }
-        validateGL(gl);
-        if (currentTile <= 0) {
-            setup();
+        if ( eot() ) {
+            throw new IllegalStateException("EOT reached: "+this);
         }
-
+        validateGL(gl);
+        
         /* which tile (by row and column) we're about to render */
         if (rowOrder == TR_BOTTOM_TO_TOP) {
             currentRow = currentTile / columns;
@@ -390,7 +439,7 @@ public class TileRenderer extends TileRendererBase {
         gl.glViewport( 0, 0, tW, tH );
         
         if( DEBUG ) {
-            System.err.println("TileRenderer.begin.X: "+this.toString());
+            System.err.println("TileRenderer.begin: "+this.toString());
         }
         
         // Do not forget to issue:
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
index f15c79f68..d6c36aa14 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java
@@ -241,6 +241,7 @@ public abstract class TileRendererBase {
         tileDetails(sb);
         sb.append("], image[size "+imageSize+", buffer "+hashStr(imageBuffer)+"], glad["+
                 gladListenerCount+" listener, pre "+(null!=glEventListenerPre)+", post "+(null!=glEventListenerPost)+", preSwap "+gladRequiresPreSwap+"]");
+        sb.append(", isSetup "+isSetup());
         return sb;
     }
     public String toString() {
@@ -284,7 +285,7 @@ public abstract class TileRendererBase {
      * @param width The width of the final image
      * @param height The height of the final image
      */
-    public final void setImageSize(int width, int height) {
+    public void setImageSize(int width, int height) {
         imageSize.setWidth(width);
         imageSize.setHeight(height);
     }
@@ -320,6 +321,27 @@ public abstract class TileRendererBase {
      */
     public abstract boolean isSetup();
     
+    /**
+     * Returns true if <i>end of tiling</i> has been reached, otherwise false.
+     * <p>
+     * <i>end of tiling</i> criteria is implementation specific and may never be reached.
+     * </p>
+     * <p>
+     * User needs to {@link #reset()} tiling after reaching <i>end of tiling</i>
+     * before calling {@link #beginTile(GL)} again.
+     * </p>
+     */
+    public abstract boolean eot();
+    
+    /**
+     * Method resets implementation's internal state to <i>start of tiling</i>
+     * as required for {@link #beginTile(GL)} if {@link #eot() end of tiling} has been reached.
+     * <p>
+     * Implementation is a <i>nop</i> where {@link #eot() end of tiling} is never reached.
+     * </p>
+     */
+    public abstract void reset();
+    
     /**
      * Begins rendering a tile.
      * <p>
@@ -351,10 +373,19 @@ public abstract class TileRendererBase {
      * <p>
      * User has to comply with the <a href="#glprequirement">GL profile requirement</a>.
      * </p>
+     * <p>
+     * If {@link #eot() end of tiling} has been reached,
+     * user needs to {@link #reset()} tiling before calling this method.
+     * </p>
      * 
      * @param gl The gl context
-     * @throws IllegalStateException if image-size has not been set
+     * @throws IllegalStateException if {@link #setImageSize(int, int) image-size} is undefined,
+     *         an {@link #isSetup() implementation related setup} has not be performed 
+     *         or {@ link #eot()} has been reached. See implementing classes.
      * @throws GLException if {@link #setImageBuffer(GLPixelBuffer) image buffer} is used but <code>gl</code> instance is &lt; {@link GL2ES3}
+     * @see #isSetup()
+     * @see #eot()
+     * @see #reset()
      */
     public abstract void beginTile(GL gl) throws IllegalStateException, GLException;
     
@@ -594,6 +625,12 @@ public abstract class TileRendererBase {
                 }
                 return;
             }
+            if( eot() ) {
+                if( DEBUG ) {
+                    System.err.println("TileRenderer.glel.display: EOT: "+TileRendererBase.this);
+                }
+                return;
+            }
             final GL gl = drawable.getGL();
 
             beginTile(gl);
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index f86a6a347..20dd802fb 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -837,20 +837,26 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
       final Graphics2D g2d = (Graphics2D)graphics;
       try {
           printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
-          try {
-              final TileRenderer tileRenderer = printAWTTiles.renderer;
-              if( DEBUG ) {
-                  System.err.println("AWT print.0: "+tileRenderer);
-              }
-              do {
-                  if( printGLAD != GLCanvas.this ) {
-                      tileRenderer.display();
-                  } else {
-                      Threading.invoke(true, displayOnEDTAction, getTreeLock());
+          final TileRenderer tileRenderer = printAWTTiles.renderer;
+          if( DEBUG ) {
+              System.err.println("AWT print.0: "+tileRenderer);
+          }
+          if( !tileRenderer.eot() ) {
+              try {
+                  do {
+                      if( printGLAD != GLCanvas.this ) {
+                          tileRenderer.display();
+                      } else {
+                          Threading.invoke(true, displayOnEDTAction, getTreeLock());
+                      }
+                  } while ( !tileRenderer.eot() );
+                  if( DEBUG ) {
+                      System.err.println("AWT print.1: "+printAWTTiles);
                   }
-              } while ( !tileRenderer.eot() );
-          } finally {
-              printAWTTiles.resetGraphics2D();
+              } finally {
+                  tileRenderer.reset();
+                  printAWTTiles.resetGraphics2D();
+              }
           }
       } catch (NoninvertibleTransformException nte) {
           System.err.println("Catched: Inversion failed of: "+g2d.getTransform());
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index fb39143b4..673f22aff 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -646,17 +646,26 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
       final Graphics2D g2d = (Graphics2D)graphics;
       try {
           printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
-          try {
-              final TileRenderer tileRenderer = printAWTTiles.renderer; 
-              do {
-                  if( printGLAD != GLJPanel.this ) {
-                      tileRenderer.display();
-                  } else {
-                      backend.doPlainPaint();
+          final TileRenderer tileRenderer = printAWTTiles.renderer;
+          if( DEBUG ) {
+              System.err.println("AWT print.0: "+tileRenderer);
+          }
+          if( !tileRenderer.eot() ) {
+              try {
+                  do {
+                      if( printGLAD != GLJPanel.this ) {
+                          tileRenderer.display();
+                      } else {
+                          backend.doPlainPaint();
+                      }
+                  } while ( !tileRenderer.eot() );
+                  if( DEBUG ) {
+                      System.err.println("AWT print.1: "+printAWTTiles);
                   }
-              } while ( !tileRenderer.eot() );
-          } finally {
-              printAWTTiles.resetGraphics2D();
+              } finally {
+                  tileRenderer.reset();
+                  printAWTTiles.resetGraphics2D();
+              }
           }
       } catch (NoninvertibleTransformException nte) {
           System.err.println("Catched: Inversion failed of: "+g2d.getTransform());
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index 86faea35f..73b3bc368 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -598,16 +598,22 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
         final Graphics2D g2d = (Graphics2D)graphics;
         try {
             printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
-            try {
-                final TileRenderer tileRenderer = printAWTTiles.renderer;
-                if( DEBUG ) {
-                    System.err.println("AWT print.0: "+tileRenderer);
+            final TileRenderer tileRenderer = printAWTTiles.renderer;
+            if( DEBUG ) {
+                System.err.println("AWT print.0: "+tileRenderer);
+            }
+            if( !tileRenderer.eot() ) {
+                try {
+                    do {
+                        tileRenderer.display();
+                    } while ( !tileRenderer.eot() );
+                    if( DEBUG ) {
+                        System.err.println("AWT print.1: "+printAWTTiles);
+                    }
+                    tileRenderer.reset();
+                } finally {
+                    printAWTTiles.resetGraphics2D();
                 }
-                do {
-                    tileRenderer.display();
-                } while ( !tileRenderer.eot() );
-            } finally {
-                printAWTTiles.resetGraphics2D();
             }
         } catch (NoninvertibleTransformException nte) {
             System.err.println("Catched: Inversion failed of: "+g2d.getTransform());
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 74089c2fd..031d6a1c1 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
@@ -97,11 +97,6 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList
   public void init(GLAutoDrawable drawable) {
     GL2 gl = drawable.getGL().getGL2();
 
-    System.err.println(Thread.currentThread()+" Gears.init: tileRendererInUse "+tileRendererInUse);
-    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();
@@ -122,6 +117,14 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList
     float green[] = { 0.0f, 0.8f, 0.2f, 0.7f };
     float blue[] = { 0.2f, 0.2f, 1.0f, 0.7f };
 
+    System.err.println(Thread.currentThread()+" Gears.init: tileRendererInUse "+tileRendererInUse);
+    if(verbose) {
+        System.err.println("GearsES2 init on "+Thread.currentThread());
+        System.err.println("Chosen GLCapabilities: " + gl.getContext().getGLDrawable().getChosenGLCapabilities());
+        System.err.println("INIT GL IS: " + gl.getClass().getName());
+        System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+    }
+    
     gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, pos, 0);
     gl.glEnable(GL2.GL_CULL_FACE);
     gl.glEnable(GL2.GL_LIGHTING);
@@ -171,11 +174,7 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList
       if(-1 != swapInterval) {        
           gl.setSwapInterval(swapInterval);
       }
-      reshapeImpl(gl, x, y, width, height, width, height);
-  }
-
-  public void reshape(GL2 gl, int x, int y, int width, int height) {
-      reshapeImpl(gl, x, y, width, height, width, height);
+      reshape(gl, x, y, width, height, width, height);
   }
 
   @Override
@@ -184,10 +183,10 @@ public class Gears implements GLEventListener, TileRendererBase.TileRendererList
           int imageWidth, int imageHeight) {
       final GL2 gl = tr.getAttachedDrawable().getGL().getGL2();
       gl.setSwapInterval(0);
-      reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
+      reshape(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
   }
 
-  void reshapeImpl(GL2 gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) {
+  public void reshape(GL2 gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) {
     final boolean msaa = gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers();
     System.err.println(Thread.currentThread()+" Gears.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", msaa "+msaa+", tileRendererInUse "+tileRendererInUse);
 
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java
index c38140ce0..e0fabc3cc 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java
@@ -46,7 +46,6 @@ import javax.media.opengl.GLContext;
 import javax.media.opengl.GLDrawable;
 import javax.media.opengl.GLDrawableFactory;
 import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLException;
 import javax.media.opengl.GLProfile;
 
 import org.junit.Assert;
@@ -67,11 +66,6 @@ import org.junit.runners.MethodSorters;
 public class TestTiledRendering1GL2NEWT extends UITestCase {
     static long duration = 500; // ms
 
-    @Test
-    public void test01() throws IOException {
-        doTest();
-    }
-    
     static class DrawableContext {
         DrawableContext(GLDrawable d, GLContext glc) {
             this.d = d;
@@ -102,7 +96,8 @@ public class TestTiledRendering1GL2NEWT extends UITestCase {
         }
     }
     
-    void doTest() throws GLException, IOException {
+    @Test
+    public void test01() throws IOException {
         GLProfile glp = GLProfile.getMaxFixedFunc(true);
         GLCapabilities caps = new GLCapabilities(glp);
         caps.setOnscreen(false);
@@ -132,15 +127,19 @@ public class TestTiledRendering1GL2NEWT extends UITestCase {
         flipVertically[0] = false;
         
         final Gears gears = new Gears();
+        gears.setVerbose(false);
         gears.init(gl);
 
         gears.addTileRendererNotify(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));
+        while( !renderer.eot() ) { 
+            renderer.beginTile(gl);
+            gears.reshape(gl,
+                    renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_Y_POS),
+                    renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT),
+                    renderer.getParam(TileRendererBase.TR_IMAGE_WIDTH), renderer.getParam(TileRendererBase.TR_IMAGE_HEIGHT));
             gears.display(gl);
-            renderer.endTile(dc.glc.getGL().getGL2ES3());
-        } while ( !renderer.eot() );
+            renderer.endTile(gl);
+        }
         gears.removeTileRendererNotify(renderer);
 
         destroyDrawableContext(dc);
@@ -160,6 +159,76 @@ public class TestTiledRendering1GL2NEWT extends UITestCase {
         TextureIO.write(textureData, file);
     }
     
+    @Test
+    public void test02_EOT_01() throws IOException {
+        GLProfile glp = GLProfile.getMaxFixedFunc(true);
+        GLCapabilities caps = new GLCapabilities(glp);
+        caps.setOnscreen(false);
+        
+        final int maxTileSize = 256;
+        DrawableContext dc = createDrawableAndCurrentCtx(caps, maxTileSize, maxTileSize);
+        final GL2 gl = dc.glc.getGL().getGL2();
+        
+        // Fix the image size for now
+        final int imageWidth = dc.d.getWidth() * 6;
+        final int imageHeight = dc.d.getHeight() * 4;
+        
+        // Initialize the tile rendering library
+        final TileRenderer renderer = new com.jogamp.opengl.util.TileRenderer();
+        renderer.setTileSize(dc.d.getWidth(), dc.d.getHeight(), 0);
+        
+        IllegalStateException ise = null;
+        try {
+            renderer.beginTile(gl); // Image size has not been set
+        } catch (IllegalStateException _ise) {
+            ise = _ise;
+            System.err.println("Expected "+ise.getClass().getSimpleName()+": "+ise.getMessage());
+        }
+        Assert.assertNotNull("TileRenderer.beginTile: Image-size exception missing", ise);
+        
+        renderer.setImageSize(imageWidth, imageHeight);
+        
+        renderer.clipImageSize(0, 0);
+        try {
+            renderer.beginTile(gl); // EOT reached (1)
+        } catch (IllegalStateException _ise) {
+            ise = _ise;
+            System.err.println("Expected "+ise.getClass().getSimpleName()+": "+ise.getMessage());
+        }
+        Assert.assertNotNull("TileRenderer.beginTile: EOT (1) exception missing", ise);
+        
+        renderer.clipImageSize(imageWidth, imageHeight); // back to full size
+        
+        final Gears gears = new Gears();
+        gears.setVerbose(false);
+        gears.init(gl);
+
+        gears.addTileRendererNotify(renderer);
+        int numTiles = 0;
+        while( !renderer.eot() ) { 
+            renderer.beginTile(gl);
+            gears.reshape(gl,
+                    renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_Y_POS),
+                    renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH), renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT),
+                    renderer.getParam(TileRendererBase.TR_IMAGE_WIDTH), renderer.getParam(TileRendererBase.TR_IMAGE_HEIGHT));
+            gears.display(gl);
+            renderer.endTile(gl);
+            numTiles++;
+        }
+        try {
+            renderer.beginTile(gl); // EOT reached (2)
+        } catch (IllegalStateException _ise) {
+            ise = _ise;
+            System.err.println("Expected "+ise.getClass().getSimpleName()+": "+ise.getMessage());
+        }
+        Assert.assertNotNull("TileRenderer.beginTile: EOT (2) exception missing", ise);
+        gears.removeTileRendererNotify(renderer);
+        
+        Assert.assertTrue("TileRenderer not rendered more than one tile but "+numTiles, numTiles > 1);
+
+        destroyDrawableContext(dc);
+    }
+    
     public static void main(String args[]) {
         for(int i=0; i<args.length; i++) {
             if(args[i].equals("-time")) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java
index f0819a43d..74909dc8c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java
@@ -215,9 +215,9 @@ public class TestTiledRendering2NEWT extends UITestCase {
         };
         renderer.setGLEventListener(preTileGLEL, null);
 
-        do {
+        while ( !renderer.eot() ) {
             renderer.display();
-        } while ( !renderer.eot() );
+        }
 
         renderer.detachAutoDrawable();
         
-- 
cgit v1.2.3