From 4d35eaa766071fd8dedab8b6e2ee53710831c567 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Sat, 27 Apr 2013 08:47:24 +0200
Subject: GLReadBufferUtil: Utilizing PixelBufferProvider; Adding
 AWTGLReadBufferUtil adding BufferedImage support; Demonstrating w/ unit
 tests.

---
 .../com/jogamp/opengl/util/GLReadBufferUtil.java   | 146 +++++++++++-------
 .../opengl/util/awt/AWTGLReadBufferUtil.java       |  89 +++++++++++
 .../com/jogamp/opengl/util/awt/Screenshot.java     |   2 +
 .../awt/TestBug461FBOSupersamplingSwingAWT.java    |  31 +++-
 .../jogl/caps/TestBug605FlippedImageNEWT.java      |   2 +-
 .../junit/jogl/util/texture/TestTexture01AWT.java  |  85 +++++++++--
 .../junit/jogl/util/texture/TestTexture02AWT.java  | 165 +++++++++++++++++++++
 7 files changed, 444 insertions(+), 76 deletions(-)
 create mode 100644 src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
 create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java

(limited to 'src')

diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index e7c323c87..140c8691f 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -28,16 +28,22 @@
  
 package com.jogamp.opengl.util;
 
-import com.jogamp.common.nio.Buffers;
-
 import java.io.File;
 import java.io.IOException;
-import java.nio.*;
-import javax.media.opengl.*;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
 
-import com.jogamp.opengl.GLExtensions;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
+
+import com.jogamp.common.nio.Buffers;
 import com.jogamp.opengl.util.texture.Texture;
 import com.jogamp.opengl.util.texture.TextureData;
+import com.jogamp.opengl.util.texture.TextureData.DefPixelBufferProvider;
+import com.jogamp.opengl.util.texture.TextureData.PixelAttributes;
+import com.jogamp.opengl.util.texture.TextureData.PixelBufferProvider;
 import com.jogamp.opengl.util.texture.TextureIO;
 
 /**
@@ -45,12 +51,13 @@ import com.jogamp.opengl.util.texture.TextureIO;
  * <p>May be used directly to write the TextureData to file (screenshot).</p>
  */
 public class GLReadBufferUtil {
-    protected final int components, alignment; 
+    protected final PixelBufferProvider pixelBufferProvider;
+    protected final int componentCount, alignment; 
     protected final Texture readTexture;
-    protected final GLPixelStorageModes psm;
+    protected final GLPixelStorageModes psm;    
     
     protected int readPixelSizeLast = 0;
-    protected ByteBuffer readPixelBuffer = null;
+    protected Buffer readPixelBuffer = null;
     protected TextureData readTextureData = null;
 
     /**
@@ -58,24 +65,37 @@ public class GLReadBufferUtil {
      * @param write2Texture true if readPixel's TextureData shall be written to a 2d Texture
      */
     public GLReadBufferUtil(boolean alpha, boolean write2Texture) {
-        components = alpha ? 4 : 3 ;
-        alignment = alpha ? 4 : 1 ; 
-        readTexture = write2Texture ? new Texture(GL.GL_TEXTURE_2D) : null ;
-        psm = new GLPixelStorageModes();
+        this(new DefPixelBufferProvider(), alpha, write2Texture);
     }
     
+    public GLReadBufferUtil(PixelBufferProvider pixelBufferProvider, boolean alpha, boolean write2Texture) {
+        this.pixelBufferProvider = pixelBufferProvider;
+        this.componentCount = alpha ? 4 : 3 ;
+        this.alignment = alpha ? 4 : 1 ; 
+        this.readTexture = write2Texture ? new Texture(GL.GL_TEXTURE_2D) : null ;
+        this.psm = new GLPixelStorageModes();
+    }
+    
+    /** Returns the {@link PixelBufferProvider} used by this instance. */
+    public PixelBufferProvider getPixelBufferProvider() { return pixelBufferProvider; }
+    
     public boolean isValid() {
       return null!=readTextureData && null!=readPixelBuffer ;
     }
     
-    public boolean hasAlpha() { return 4 == components ? true : false ; }
+    public boolean hasAlpha() { return 4 == componentCount ? true : false ; }
     
     public GLPixelStorageModes getGLPixelStorageModes() { return psm; }
     
     /**
-     * @return the raw pixel ByteBuffer, filled by {@link #readPixels(GLAutoDrawable, boolean)}
+     * Returns the raw pixel Buffer, filled by {@link #readPixels(GLAutoDrawable, boolean)}.
+     * <p>
+     * By default the {@link Buffer} is a {@link ByteBuffer}, due to {@link DefPixelBufferProvider#allocate(int, int, int)}.
+     * If the {@link PixelBufferProvider} has changed via {@link #setPixelBufferProvider(PixelBufferProvider)}.
+     * the {@link Buffer} type maybe different.
+     * </p>
      */
-    public ByteBuffer getPixelBuffer() { return readPixelBuffer; }
+    public Buffer getPixelBuffer() { return readPixelBuffer; }
     
     /**
      * rewind the raw pixel ByteBuffer
@@ -107,10 +127,9 @@ public class GLReadBufferUtil {
     }
 
     /**
-     * Read the drawable's pixels to TextureData and Texture, if requested at construction
+     * Read the drawable's pixels to TextureData and Texture, if requested at construction.
      * 
      * @param gl the current GL context object. It's read drawable is being used as the pixel source.
-     * @param drawable the drawable to read from
      * @param mustFlipVertically indicates whether to flip the data vertically or not.
      *                           The context's drawable {@link GLDrawable#isGLOriented()} state
      *                           is taken into account.
@@ -120,13 +139,49 @@ public class GLReadBufferUtil {
      * @see #GLReadBufferUtil(boolean, boolean)
      */
     public boolean readPixels(GL gl, boolean mustFlipVertically) {
+        return readPixels(gl, 0, 0, null, null, mustFlipVertically);
+    }
+    
+    /**
+     * Read the drawable's pixels to TextureData and Texture, if requested at construction.
+     * 
+     * @param gl the current GL context object. It's read drawable is being used as the pixel source.
+     * @param inX readPixel x offset
+     * @param inY readPixel y offset
+     * @param ioWidth readPixel width
+     * @param ioHeight readPixel height
+     * @param mustFlipVertically indicates whether to flip the data vertically or not.
+     *                           The context's drawable {@link GLDrawable#isGLOriented()} state
+     *                           is taken into account.
+     *                           Vertical flipping is propagated to TextureData
+     *                           and handled in a efficient manner there (TextureCoordinates and TextureIO writer).
+     * 
+     * @see #GLReadBufferUtil(boolean, boolean)
+     */
+    public boolean readPixels(GL gl, int inX, int inY, int ioWidth[], int ioHeight[], boolean mustFlipVertically) {
         final int glerr0 = gl.glGetError();
         if(GL.GL_NO_ERROR != glerr0) {
             System.err.println("Info: GLReadBufferUtil.readPixels: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
         }
+        final PixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
+        final int internalFormat;
+        if(gl.isGL2GL3() && 3 == componentCount) {
+            internalFormat = GL.GL_RGB;
+        } else {
+            internalFormat = (4 == componentCount) ? GL.GL_RGBA : GL.GL_RGB;
+        }
         final GLDrawable drawable = gl.getContext().getGLReadDrawable();
-        final int textureInternalFormat, textureDataFormat, textureDataType;
-        final int[] glImplColorReadVals = new int[] { 0, 0 };
+        final int width, height;
+        if( null == ioWidth || drawable.getWidth() < ioWidth[0] ) {
+            width = drawable.getWidth();
+        } else {
+            width = ioWidth[0];
+        }
+        if( null == ioHeight || drawable.getHeight() < ioHeight[0] ) {
+            height = drawable.getHeight();
+        } else {
+            height= ioHeight[0];
+        }
         
         final boolean flipVertically;
         if( drawable.isGLOriented() ) {
@@ -135,39 +190,21 @@ public class GLReadBufferUtil {
             flipVertically = !mustFlipVertically;
         }
         
-        if(gl.isGL2GL3() && 3 == components) {
-            textureInternalFormat=GL.GL_RGB;
-            textureDataFormat=GL.GL_RGB;
-            textureDataType = GL.GL_UNSIGNED_BYTE;            
-        } else if(gl.isGLES2Compatible() || gl.isExtensionAvailable(GLExtensions.OES_read_format)) {
-            gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
-            gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);            
-            textureInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
-            textureDataFormat = glImplColorReadVals[0];
-            textureDataType = glImplColorReadVals[1];
-        } else {
-            // RGBA read is safe for all GL profiles 
-            textureInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
-            textureDataFormat=GL.GL_RGBA;
-            textureDataType = GL.GL_UNSIGNED_BYTE;
-        }
-        
         final int tmp[] = new int[1];
-        final int readPixelSize = GLBuffers.sizeof(gl, tmp, textureDataFormat, textureDataType, 
-                                                   drawable.getWidth(), drawable.getHeight(), 1, true);
+        final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.format, pixelAttribs.type, width, height, 1, true);
         
         boolean newData = false;
-        if(readPixelSize>readPixelSizeLast) {
-            readPixelBuffer = Buffers.newDirectByteBuffer(readPixelSize);
+        if( readPixelSize > readPixelSizeLast || pixelBufferProvider.requiresNewBuffer(width, height) ) {
+            readPixelBuffer = pixelBufferProvider.allocate(width, height, readPixelSize);
+            Buffers.rangeCheckBytes(readPixelBuffer, readPixelSize);
             readPixelSizeLast = readPixelSize ;
             try {
                 readTextureData = new TextureData(
                            gl.getGLProfile(),
-                           textureInternalFormat,
-                           drawable.getWidth(), drawable.getHeight(),
+                           internalFormat,
+                           width, height,
                            0, 
-                           textureDataFormat,
-                           textureDataType,
+                           pixelAttribs,
                            false, false, 
                            flipVertically,
                            readPixelBuffer,
@@ -180,27 +217,25 @@ public class GLReadBufferUtil {
                 throw new RuntimeException("can not fetch offscreen texture", e);
             }
         } else {
-            readTextureData.setInternalFormat(textureInternalFormat);
-            readTextureData.setWidth(drawable.getWidth());
-            readTextureData.setHeight(drawable.getHeight());
-            readTextureData.setPixelFormat(textureDataFormat);
-            readTextureData.setPixelType(textureDataType);
+            readTextureData.setInternalFormat(internalFormat);
+            readTextureData.setWidth(width);
+            readTextureData.setHeight(height);
+            readTextureData.setPixelAttributes(pixelAttribs);
         }
         boolean res = null!=readPixelBuffer;
         if(res) {
             psm.setAlignment(gl, alignment, alignment);
             readPixelBuffer.clear();
             try {
-                gl.glReadPixels(0, 0, drawable.getWidth(), drawable.getHeight(), textureDataFormat, textureDataType, readPixelBuffer);
+                gl.glReadPixels(inX, inY, width, height, pixelAttribs.format, pixelAttribs.type, readPixelBuffer);
             } catch(GLException gle) { res = false; gle.printStackTrace(); }
-            readPixelBuffer.position(readPixelSize);
+            readPixelBuffer.position( readPixelSize / Buffers.sizeOfBufferElem(readPixelBuffer) );
             readPixelBuffer.flip();
             final int glerr1 = gl.glGetError();
             if(GL.GL_NO_ERROR != glerr1) {
                 System.err.println("GLReadBufferUtil.readPixels: readPixels error 0x"+Integer.toHexString(glerr1)+
-                                   " "+drawable.getWidth()+"x"+drawable.getHeight()+
-                                   ", fmt 0x"+Integer.toHexString(textureDataFormat)+", type 0x"+Integer.toHexString(textureDataType)+
-                                   ", impl-fmt 0x"+Integer.toHexString(glImplColorReadVals[0])+", impl-type 0x"+Integer.toHexString(glImplColorReadVals[1])+
+                                   " "+width+"x"+height+
+                                   ", "+pixelAttribs+
                                    ", "+readPixelBuffer+", sz "+readPixelSize);
                 res = false;                
             }
@@ -211,7 +246,7 @@ public class GLReadBufferUtil {
                     readTexture.updateSubImage(gl, readTextureData, 0, 
                                                0, 0, // src offset
                                                0, 0, // dst offset
-                                               drawable.getWidth(), drawable.getHeight());
+                                               width, height);
                 }
                 readPixelBuffer.rewind();
             }
@@ -226,7 +261,6 @@ public class GLReadBufferUtil {
             readTextureData = null;
         }
         if(null != readPixelBuffer) {
-            readPixelBuffer.clear();
             readPixelBuffer = null;
         }
         readPixelSizeLast = 0;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
new file mode 100644
index 000000000..f26fec0d5
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.util.awt;
+
+import java.awt.image.BufferedImage;
+import java.nio.Buffer;
+import java.nio.IntBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+
+import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.texture.awt.AWTTextureData.AWTPixelBufferProviderInt;
+
+/**
+ * {@link GLReadBufferUtil} specialization allowing to
+ * read out a frambuffer to an AWT BufferedImage
+ * utilizing {@link AWTPixelBufferProviderInt} for further AWT processing.
+ */
+public class AWTGLReadBufferUtil extends GLReadBufferUtil {
+    /**
+     * {@inheritDoc}
+     * 
+     * @param alpha
+     */
+    public AWTGLReadBufferUtil(boolean alpha) {
+        super(new AWTPixelBufferProviderInt(), alpha, false);
+    }
+
+    /**
+     * Returns the raw pixel Buffer, filled by {@link #readPixels(GLAutoDrawable, boolean)}.
+     * <p>
+     * Due to using {@link AWTPixelBufferProviderInt#allocate(int, int, int)},
+     * returns an {@link IntBuffer} instance.
+     * </p>
+     */
+    @Override
+    public Buffer getPixelBuffer() { return readPixelBuffer; }
+    
+    public BufferedImage getImage() { return ((AWTPixelBufferProviderInt)pixelBufferProvider).getImage(); }
+    
+    public BufferedImage readPixelsToBufferedImage(GL gl, boolean awtOrientation) {
+        if( readPixels(gl, awtOrientation) ) {
+            final BufferedImage image = getImage();
+            if( getTextureData().getMustFlipVertically()  ) {
+                ImageUtil.flipImageVertically(image);
+            }
+            return image;
+        }
+        return null;
+    }
+    public BufferedImage readPixelsToBufferedImage(GL gl, int inX, int inY, int inWidth, int inHeight, boolean awtOrientation) {
+        final int[] ioWidth = new int[] { inWidth };
+        final int[] ioHeight= new int[] { inHeight };
+        if( readPixels(gl, inX, inY, ioWidth, ioHeight, awtOrientation) ) {
+            final BufferedImage image = getImage();
+            if( getTextureData().getMustFlipVertically()  ) {
+                ImageUtil.flipImageVertically(image);
+            }
+            return image;
+        }
+        return null;
+    }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
index 0eab65380..2ffc27260 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
@@ -61,6 +61,8 @@ import com.jogamp.opengl.util.TGAWriter;
  * @deprecated Please consider using {@link com.jogamp.opengl.util.GLReadBufferUtil}, 
  *             which is AWT independent and does not require a CPU based vertical image flip 
  *             in case drawable {@link GLDrawable#isGLOriented() is in OpenGL orientation}.
+ *             Further more you may use {@link AWTGLReadBufferUtil} to read out 
+ *             the framebuffer into a BufferedImage for further AWT processing.
  */
 public class Screenshot {
   private Screenshot() {}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java
index 089520658..81be58aa5 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java
@@ -28,6 +28,7 @@
 
 package com.jogamp.opengl.test.junit.jogl.awt;
 
+import java.awt.Container;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
  
@@ -49,7 +50,9 @@ import javax.swing.JLabel;
 import org.junit.Assert;
 import org.junit.Test;
 
+import com.jogamp.opengl.test.junit.util.MiscUtils;
 import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
 
 /**
  * Tests for bug 461, a failure of GLDrawableFactory.createGLPbuffer() on Windows
@@ -58,8 +61,10 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
  * @author Wade Walker (from code sample provided by Owen Dimond)
  */
 public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GLEventListener {
+    static long durationPerTest = 500;
     JFrame jframe;
     GLOffscreenAutoDrawable offScreenBuffer;
+    AWTGLReadBufferUtil awtGLReadBufferUtil;
     
     private void render(GLAutoDrawable drawable) {
         GL2 gl = drawable.getGL().getGL2();
@@ -78,7 +83,8 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
     }
     
     /* @Override */
-    public void init(GLAutoDrawable drawable) {                        
+    public void init(GLAutoDrawable drawable) {
+        awtGLReadBufferUtil = new AWTGLReadBufferUtil(false);
     }
 
     /* @Override */
@@ -88,14 +94,18 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
     /* @Override */
     public void display(GLAutoDrawable drawable) {             
         render(offScreenBuffer);
-        BufferedImage outputImage = com.jogamp.opengl.util.awt.Screenshot.readToBufferedImage(200, 200, false);        
+        // BufferedImage outputImage = com.jogamp.opengl.util.awt.Screenshot.readToBufferedImage(200, 200, false);
+        BufferedImage outputImage = awtGLReadBufferUtil.readPixelsToBufferedImage(drawable.getGL(), 0, 0, 200, 200, true /* awtOrientation */);
         Assert.assertNotNull(outputImage);
         ImageIcon imageIcon = new ImageIcon(outputImage);
         final JLabel imageLabel = new JLabel(imageIcon);        
         try {
             javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
                 public void run() {
-                    jframe.getContentPane().add(imageLabel);
+                    Container cont = jframe.getContentPane();
+                    cont.removeAll();
+                    cont.add(imageLabel);
+                    cont.validate();
                 }});
         } catch (Exception e) {
             e.printStackTrace();
@@ -105,6 +115,7 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
     /* @Override */
     public void dispose(GLAutoDrawable drawable) {  
         try {
+            awtGLReadBufferUtil.dispose(drawable.getGL());
             javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
                 public void run() {
                     jframe.setVisible(false);
@@ -141,7 +152,8 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
         glCap.setSampleBuffers(true);
       
         // Without line below, there is an error on Windows.
-        glCap.setDoubleBuffered(false);
+        // glCap.setDoubleBuffered(false); // implicit double buffer -> MSAA + FBO
+        
         // Needed for drop shadows
         glCap.setStencilBits(1);
 
@@ -149,16 +161,25 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
         offScreenBuffer = fac.createOffscreenAutoDrawable(GLProfile.getDefaultDevice(), glCap, null, 200, 200, null);
         Assert.assertNotNull(offScreenBuffer);
         offScreenBuffer.addGLEventListener(this);        
-        offScreenBuffer.display();
         javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
             public void run() {
                 jframe.setSize( 300, 300);
                 jframe.setVisible(true);
             }});
+        offScreenBuffer.display(); // read from front buffer due to FBO+MSAA -> double-buffer
+        offScreenBuffer.display(); // now we have prev. image in front buffer to be read out
+        
+        Thread.sleep(durationPerTest);
+
         offScreenBuffer.destroy();
     }
 
     public static void main(String args[]) {
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-time")) {
+                durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+            }
+        }
         org.junit.runner.JUnitCore.main(TestBug461FBOSupersamplingSwingAWT.class.getName());
     }
 }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java
index 837d94cb3..3f593e908 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java
@@ -128,7 +128,7 @@ public class TestBug605FlippedImageNEWT extends UITestCase {
         glad.display();
         System.err.println("XXX "+glad.getChosenGLCapabilities());
         System.err.println("XXX "+glad.getContext().getGLVersion());
-        testFlipped(rbu.getPixelBuffer(), glad.getWidth(), glad.getHeight(), 3);        
+        testFlipped((ByteBuffer)rbu.getPixelBuffer(), glad.getWidth(), glad.getHeight(), 3);        
         
         glad.destroy();        
     }
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
index 8baba68ec..5b2876744 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java
@@ -29,17 +29,25 @@
 package com.jogamp.opengl.test.junit.jogl.util.texture;
 
 
+import com.jogamp.common.util.awt.AWTEDTExecutor;
 import com.jogamp.opengl.test.junit.jogl.demos.gl2.TextureDraw01GL2Listener;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
 import com.jogamp.opengl.test.junit.util.UITestCase;
 
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
 import javax.media.opengl.GLProfile;
 import javax.media.opengl.GLCapabilities;
 import javax.media.opengl.awt.GLCanvas;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
 import com.jogamp.opengl.util.texture.TextureData;
 import com.jogamp.opengl.util.texture.awt.AWTTextureIO;
-import com.jogamp.opengl.util.Animator;
 
 import java.awt.AlphaComposite;
+import java.awt.Canvas;
 import java.awt.Color;
 import java.awt.Frame;
 import java.awt.GradientPaint;
@@ -54,7 +62,14 @@ import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+/**
+ * Demonstrates TextureData w/ AWT usage in both directions,
+ * i.e. generating a texture based on an AWT BufferedImage data
+ * as well as reading out GL framebuffer and displaying it 
+ * as an BufferedImage. 
+ */
 public class TestTexture01AWT extends UITestCase {
+    static long durationPerTest = 500;
     static GLProfile glp;
     static GLCapabilities caps;
     BufferedImage textureImage;
@@ -107,37 +122,74 @@ public class TestTexture01AWT extends UITestCase {
 
     @Test
     public void test1() throws InterruptedException {
+        final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(false);
+        final Frame frame0 = new Frame("GL -> AWT");
+        final Canvas canvas = new Canvas();
+        frame0.add(canvas);
+        
         final GLCanvas glCanvas = new GLCanvas(caps);
-        final Frame frame = new Frame("Texture Test");
-        Assert.assertNotNull(frame);
-        frame.add(glCanvas);
+        final Frame frame1 = new Frame("AWT -> Texture");
+        Assert.assertNotNull(frame1);
+        frame1.add(glCanvas);
 
         // create texture    
         TextureData textureData = AWTTextureIO.newTextureData(caps.getGLProfile(), textureImage, false);
         glCanvas.addGLEventListener(new TextureDraw01GL2Listener(textureData));
+        glCanvas.addGLEventListener(new GLEventListener() {
+            
+            @Override
+            public void init(GLAutoDrawable drawable) { }
+            @Override
+            public void dispose(GLAutoDrawable drawable) { }
+            @Override
+            public void display(GLAutoDrawable drawable) {
+                BufferedImage outputImage = awtGLReadBufferUtil.readPixelsToBufferedImage(drawable.getGL(), true /* awtOrientation */);
+                ImageIcon imageIcon = new ImageIcon(outputImage);
+                final JLabel imageLabel = new JLabel(imageIcon);        
+                try {
+                    AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+                        public void run() {
+                            frame0.removeAll();
+                            frame0.add(imageLabel);
+                            frame0.validate();
+                        }});
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }                
+            }
+
+            @Override
+            public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+                frame0.setSize(frame1.getWidth(), frame1.getHeight());
+                frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY());
+                frame0.validate();
+            }            
+        });
 
-        Animator animator = new Animator(glCanvas);
         try {
             javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
                 public void run() {
-                    frame.setSize(512, 512);
-                    frame.setVisible(true);
+                    frame1.setSize(256, 256);
+                    frame1.setLocation(0, 0);
+                    frame1.setVisible(true);
+                    frame0.setSize(frame1.getWidth(), frame1.getHeight());
+                    frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY());
+                    frame0.setVisible(true);
                 }});
         } catch( Throwable throwable ) {
             throwable.printStackTrace();
             Assume.assumeNoException( throwable );
         }                
-        animator.start();
+        
+        Thread.sleep(durationPerTest);
 
-        Thread.sleep(500); // 500 ms
-
-        animator.stop();
         try {
             javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
                 public void run() {
-                    frame.setVisible(false);
-                    frame.remove(glCanvas);
-                    frame.dispose();
+                    frame0.setVisible(false);
+                    frame0.dispose();
+                    frame1.setVisible(false);
+                    frame1.dispose();
                 }});
         } catch( Throwable throwable ) {
             throwable.printStackTrace();
@@ -146,6 +198,11 @@ public class TestTexture01AWT extends UITestCase {
     }
 
     public static void main(String args[]) throws IOException {
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-time")) {
+                durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+            }
+        }
         String tstname = TestTexture01AWT.class.getName();
         org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
             tstname,
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java
new file mode 100644
index 000000000..bdc8934fc
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java
@@ -0,0 +1,165 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+ 
+package com.jogamp.opengl.test.junit.jogl.util.texture;
+
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.awt.GLCanvas;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+
+import com.jogamp.opengl.util.FPSAnimator;
+import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
+
+import java.awt.Frame;
+import java.awt.image.BufferedImage;
+
+import java.io.IOException;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Demonstrates TextureData w/ AWT usage,
+ * i.e. reading out an animated GL framebuffer and displaying it 
+ * as an BufferedImage. 
+ */
+public class TestTexture02AWT extends UITestCase {
+    static long durationPerTest = 500;
+    static GLProfile glp;
+    static GLCapabilities caps;
+
+    @BeforeClass
+    public static void initClass() {
+        if(!GLProfile.isAvailable(GLProfile.GL2ES2)) {
+            UITestCase.setTestSupported(false);
+            return;
+        }
+        glp = GLProfile.getGL2ES2();
+        Assert.assertNotNull(glp);
+        caps = new GLCapabilities(glp);
+        Assert.assertNotNull(caps);
+    }
+
+    @Test
+    public void test1() throws InterruptedException {
+        final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(false);
+        final Frame frame0 = new Frame("GL -> AWT");
+        final ImageIcon imageIcon = new ImageIcon();
+        final JLabel imageLabel = new JLabel(imageIcon);
+        frame0.add(imageLabel);
+        
+        final GLCanvas glCanvas = new GLCanvas(caps);
+        final Frame frame1 = new Frame("GearsES2");
+        Assert.assertNotNull(frame1);
+        frame1.add(glCanvas);
+
+        glCanvas.addGLEventListener(new GearsES2(1));
+        glCanvas.addGLEventListener(new GLEventListener() {            
+            @Override
+            public void init(GLAutoDrawable drawable) { }
+            @Override
+            public void dispose(GLAutoDrawable drawable) { }
+            @Override
+            public void display(GLAutoDrawable drawable) {
+                BufferedImage outputImage = awtGLReadBufferUtil.readPixelsToBufferedImage(drawable.getGL(), true /* awtOrientation */);
+                imageIcon.setImage(outputImage);
+                imageLabel.repaint();
+            }
+
+            @Override
+            public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+                frame0.setSize(frame1.getWidth(), frame1.getHeight());
+                frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY());
+                frame0.validate();
+            }            
+        });
+
+        try {
+            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+                public void run() {
+                    frame1.setSize(256, 256);
+                    frame1.setLocation(0, 0);
+                    frame1.setVisible(true);
+                    frame0.setSize(frame1.getWidth(), frame1.getHeight());
+                    frame0.setLocation(frame1.getX()+frame1.getWidth()+32, frame0.getY());
+                    frame0.setVisible(true);
+                }});
+        } catch( Throwable throwable ) {
+            throwable.printStackTrace();
+            Assume.assumeNoException( throwable );
+        }                
+        FPSAnimator animator = new FPSAnimator(glCanvas, 15); // 15fps
+        animator.start();
+        
+        Thread.sleep(durationPerTest);
+
+        animator.stop();
+        try {
+            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+                public void run() {
+                    frame0.setVisible(false);
+                    frame0.dispose();
+                    frame1.setVisible(false);
+                    frame1.dispose();
+                }});
+        } catch( Throwable throwable ) {
+            throwable.printStackTrace();
+            Assume.assumeNoException( throwable );
+        }                
+    }
+
+    public static void main(String args[]) throws IOException {
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-time")) {
+                durationPerTest = MiscUtils.atol(args[++i], durationPerTest);
+            }
+        }
+        String tstname = TestTexture02AWT.class.getName();
+        org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] {
+            tstname,
+            "filtertrace=true",
+            "haltOnError=false",
+            "haltOnFailure=false",
+            "showoutput=true",
+            "outputtoformatters=true",
+            "logfailedtests=true",
+            "logtestlistenerevents=true",
+            "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter",
+            "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } );
+    }
+}
-- 
cgit v1.2.3