diff options
author | Sven Gothel <[email protected]> | 2013-04-27 08:47:24 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-04-27 08:47:24 +0200 |
commit | 4d35eaa766071fd8dedab8b6e2ee53710831c567 (patch) | |
tree | cbf22cde01ea2ead789684f3098be44fb1b08c79 | |
parent | 587ec1437ed762ed8cdfcbf27f940ab83813f4a5 (diff) |
GLReadBufferUtil: Utilizing PixelBufferProvider; Adding AWTGLReadBufferUtil adding BufferedImage support; Demonstrating w/ unit tests.
7 files changed, 444 insertions, 76 deletions
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" } ); + } +} |