summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java253
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java57
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java203
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java25
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java122
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java96
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java190
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/caps/TestBug605FlippedImageNEWT.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java151
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java3
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java5
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java3
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture01AWT.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTexture02AWT.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java9
16 files changed, 794 insertions, 331 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
new file mode 100644
index 000000000..b2e0af2b5
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
@@ -0,0 +1,253 @@
+/**
+ * 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;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLContext;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.texture.TextureData;
+
+/**
+ * OpenGL pixel data buffer, allowing user to provide buffers via their {@link GLPixelBufferProvider} implementation.
+ * <p>
+ * {@link GLPixelBufferProvider} produces a {@link GLPixelBuffer}.
+ * </p>
+ * <p>
+ * You may use {@link #defaultProvider}.
+ * </p>
+ */
+public class GLPixelBuffer {
+
+ /** Allows user to interface with another toolkit to define {@link GLPixelAttributes} and memory buffer to produce {@link TextureData}. */
+ public static interface GLPixelBufferProvider {
+ /** Called first to determine {@link GLPixelAttributes}. */
+ GLPixelAttributes getAttributes(GL gl, int componentCount);
+
+ /**
+ * Allocates a new {@link GLPixelBuffer} object.
+ * <p>
+ * Being called to gather the initial {@link GLPixelBuffer},
+ * or a new replacement {@link GLPixelBuffer} if {@link GLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+ * </p>
+ * <p>
+ * The minimum required {@link Buffer#remaining() remaining} byte size equals to <code>minByteSize</code>, if &gt; 0,
+ * otherwise utilize {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean)}
+ * to calculate it.
+ * </p>
+ *
+ * @param gl the corresponding current GL context object
+ * @param pixelAttributes the desired {@link GLPixelAttributes}
+ * @param width in pixels
+ * @param height in pixels
+ * @param depth in pixels
+ * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
+ * @param minByteSize if &gt; 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore.
+ */
+ GLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize);
+ }
+ /**
+ * Default {@link GLPixelBufferProvider} utilizing best match for {@link GLPixelAttributes}
+ * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}.
+ */
+ public static GLPixelBufferProvider defaultProvider = new GLPixelBufferProvider() {
+
+ @Override
+ public GLPixelAttributes getAttributes(GL gl, int componentCount) {
+ final GLContext ctx = gl.getContext();
+ final int dFormat, dType;
+
+ if(gl.isGL2GL3() && 3 == componentCount) {
+ dFormat = GL.GL_RGB;
+ dType = GL.GL_UNSIGNED_BYTE;
+ } else {
+ dFormat = ctx.getDefaultPixelDataFormat();
+ dType = ctx.getDefaultPixelDataType();
+ }
+ return new GLPixelAttributes(componentCount, dFormat, dType);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns an NIO {@link ByteBuffer}.
+ * </p>
+ */
+ @Override
+ public GLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize) {
+ if( minByteSize > 0 ) {
+ return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(minByteSize));
+ } else {
+ int[] tmp = { 0 };
+ final int byteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.bytesPerPixel, width, height, depth, pack);
+ return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(byteSize));
+ }
+ }
+ };
+
+ /** Pixel attributes. */
+ public static class GLPixelAttributes {
+ /** Undefined instance of {@link GLPixelAttributes}, having componentCount:=0, format:=0 and type:= 0. */
+ public static final GLPixelAttributes UNDEF = new GLPixelAttributes(0, 0, 0);
+
+ /** Pixel component count */
+ public final int componentCount;
+ /** The OpenGL pixel data format */
+ public final int format;
+ /** The OpenGL pixel data type */
+ public final int type;
+ /** The OpenGL pixel size in bytes */
+ public final int bytesPerPixel;
+
+ /**
+ * Deriving {@link #componentCount} via GL <code>dataFormat</code>, i.e. {@link GLBuffers#componentCount(int)} if &gt; 0.
+ * @param dataFormat GL data format
+ * @param dataType GL data type
+ */
+ public GLPixelAttributes(int dataFormat, int dataType) {
+ this(0 < dataFormat ? GLBuffers.componentCount(dataFormat) : 0, dataFormat, dataType);
+ }
+ /**
+ * Using user specified source {@link #componentCount}.
+ * @param componentCount source component count
+ * @param dataFormat GL data format
+ * @param dataType GL data type
+ */
+ public GLPixelAttributes(int componentCount, int dataFormat, int dataType) {
+ this.componentCount = componentCount;
+ this.format = dataFormat;
+ this.type = dataType;
+ this.bytesPerPixel = ( 0 < dataFormat && 0 < dataType ) ? GLBuffers.bytesPerPixel(dataFormat, dataType) : 0;
+ }
+ public String toString() {
+ return "PixelAttributes[comp "+componentCount+", fmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+", bytesPerPixel "+bytesPerPixel+"]";
+ }
+ }
+
+ /** The {@link GLPixelAttributes}. */
+ public final GLPixelAttributes pixelAttributes;
+ /** Width in pixels. */
+ public final int width;
+ /** Height in pixels. */
+ public final int height;
+ /** Depth in pixels. */
+ public final int depth;
+ /** Data packing direction. If <code>true</code> for read mode GPU -> CPU, <code>false</code> for write mode CPU -> GPU. */
+ public final boolean pack;
+ /** Byte size of the buffer. Actually the number of {@link Buffer#remaining()} bytes when passed in ctor. */
+ public final int byteSize;
+ /**
+ * Buffer holding the pixel data. If {@link #rewind()}, it holds <code>byteSize</code> {@link Buffer#remaining()} bytes.
+ * <p>
+ * By default the {@link Buffer} is a {@link ByteBuffer}, due to {@link DefProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int)}.
+ * However, other {@link GLPixelBufferProvider} may utilize different {@link Buffer} types.
+ * </p>
+ */
+ public final Buffer buffer;
+ /** Buffer element size in bytes. */
+ public final int bufferElemSize;
+
+ public StringBuffer toString(StringBuffer sb) {
+ if(null == sb) {
+ sb = new StringBuffer();
+ }
+ sb.append(pixelAttributes).append(", dim ").append(width).append("x").append(height).append("x").append(depth).append(", pack ").append(pack)
+ .append(", buffer[sz [bytes ").append(byteSize).append(", elemSize ").append(bufferElemSize).append(", ").append(buffer).append("]");
+ return sb;
+ }
+ public String toString() {
+ return "GLPixelBuffer["+toString(null).toString()+"]";
+ }
+
+ public GLPixelBuffer(GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, Buffer buffer) {
+ this.pixelAttributes = pixelAttributes;
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
+ this.pack = pack;
+ this.buffer = buffer;
+ this.byteSize = Buffers.remainingBytes(buffer);
+ this.bufferElemSize = Buffers.sizeOfBufferElem(buffer);
+ }
+
+ public boolean isValid() {
+ return 0 < byteSize;
+ }
+
+ public Buffer rewind() {
+ return buffer.rewind();
+ }
+
+ /** Returns the byte position of the {@link #buffer}. */
+ public int position() {
+ return buffer.position() * bufferElemSize;
+ }
+
+ /** Sets the byte position of the {@link #buffer}. */
+ public Buffer position(int bytePos) {
+ return buffer.position( bytePos / bufferElemSize );
+ }
+
+ public Buffer flip() {
+ return buffer.flip();
+ }
+
+ public Buffer clear() {
+ return buffer.clear();
+ }
+
+ /**
+ * Returns true, if implementation requires a new buffer based on the new size
+ * due to pixel alignment or byte size, otherwise false.
+ * <p>
+ * It is assumed that <code>pixelAttributes</code>, <code>depth</code> and <code>pack</code> stays the same!
+ * </p>
+ * <p>
+ * The minimum required byte size equals to <code>minByteSize</code>, if &gt; 0,
+ * otherwise utilize {@link GLBuffers#sizeof(GL, int[], int, int, int, int, int, boolean) GLBuffers.sizeof(..)}
+ * to calculate it.
+ * </p>
+ * @param gl the corresponding current GL context object
+ * @param newWidth new width in pixels
+ * @param newHeight new height in pixels
+ * @param minByteSize if &gt; 0, the pre-calculated minimum byte-size for the resulting buffer, otherwise ignore.
+ * @see GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int)
+ */
+ public boolean requiresNewBuffer(GL gl, int newWidth, int newHeight, int minByteSize) {
+ return this.byteSize < minByteSize;
+ }
+
+ /** Dispose resources. */
+ public void dispose() {
+ buffer.clear();
+ }
+}
+
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index dc87c7ac9..602dbb095 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -30,10 +30,9 @@ package com.jogamp.opengl.util;
import java.io.File;
import java.io.IOException;
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLException;
@@ -41,9 +40,9 @@ 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.GLPixelBuffer;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelBufferProvider;
import com.jogamp.opengl.util.texture.TextureIO;
/**
@@ -51,13 +50,12 @@ 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 PixelBufferProvider pixelBufferProvider;
+ protected final GLPixelBufferProvider pixelBufferProvider;
protected final int componentCount, alignment;
protected final Texture readTexture;
protected final GLPixelStorageModes psm;
- protected int readPixelSizeLast = 0;
- protected Buffer readPixelBuffer = null;
+ protected GLPixelBuffer readPixelBuffer = null;
protected TextureData readTextureData = null;
/**
@@ -65,10 +63,10 @@ public class GLReadBufferUtil {
* @param write2Texture true if readPixel's TextureData shall be written to a 2d Texture
*/
public GLReadBufferUtil(boolean alpha, boolean write2Texture) {
- this(new DefPixelBufferProvider(), alpha, write2Texture);
+ this(GLPixelBuffer.defaultProvider, alpha, write2Texture);
}
- public GLReadBufferUtil(PixelBufferProvider pixelBufferProvider, boolean alpha, boolean write2Texture) {
+ public GLReadBufferUtil(GLPixelBufferProvider pixelBufferProvider, boolean alpha, boolean write2Texture) {
this.pixelBufferProvider = pixelBufferProvider;
this.componentCount = alpha ? 4 : 3 ;
this.alignment = alpha ? 4 : 1 ;
@@ -76,11 +74,11 @@ public class GLReadBufferUtil {
this.psm = new GLPixelStorageModes();
}
- /** Returns the {@link PixelBufferProvider} used by this instance. */
- public PixelBufferProvider getPixelBufferProvider() { return pixelBufferProvider; }
+ /** Returns the {@link GLPixelBufferProvider} used by this instance. */
+ public GLPixelBufferProvider getPixelBufferProvider() { return pixelBufferProvider; }
public boolean isValid() {
- return null!=readTextureData && null!=readPixelBuffer ;
+ return null!=readTextureData && null!=readPixelBuffer && readPixelBuffer.isValid();
}
public boolean hasAlpha() { return 4 == componentCount ? true : false ; }
@@ -88,14 +86,9 @@ public class GLReadBufferUtil {
public GLPixelStorageModes getGLPixelStorageModes() { return psm; }
/**
- * 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>
+ * Returns the {@link GLPixelBuffer}, created and filled by {@link #readPixels(GLAutoDrawable, boolean)}.
*/
- public Buffer getPixelBuffer() { return readPixelBuffer; }
+ public GLPixelBuffer getPixelBuffer() { return readPixelBuffer; }
/**
* rewind the raw pixel ByteBuffer
@@ -163,7 +156,7 @@ public class GLReadBufferUtil {
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 GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
final int internalFormat;
if(gl.isGL2GL3() && 3 == componentCount) {
internalFormat = GL.GL_RGB;
@@ -191,13 +184,12 @@ public class GLReadBufferUtil {
}
final int tmp[] = new int[1];
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.format, pixelAttribs.type, width, height, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, width, height, 1, true);
boolean newData = false;
- if( readPixelSize > readPixelSizeLast || pixelBufferProvider.requiresNewBuffer(width, height) ) {
- readPixelBuffer = pixelBufferProvider.allocate(width, height, readPixelSize);
+ if( null == readPixelBuffer || readPixelBuffer.requiresNewBuffer(gl, width, height, readPixelSize) ) {
+ readPixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, width, height, 1, true, readPixelSize);
Buffers.rangeCheckBytes(readPixelBuffer, readPixelSize);
- readPixelSizeLast = readPixelSize ;
try {
readTextureData = new TextureData(
gl.getGLProfile(),
@@ -207,13 +199,12 @@ public class GLReadBufferUtil {
pixelAttribs,
false, false,
flipVertically,
- readPixelBuffer,
+ readPixelBuffer.buffer,
null /* Flusher */);
newData = true;
} catch (Exception e) {
readTextureData = null;
readPixelBuffer = null;
- readPixelSizeLast = 0;
throw new RuntimeException("can not fetch offscreen texture", e);
}
} else {
@@ -222,14 +213,17 @@ public class GLReadBufferUtil {
readTextureData.setHeight(height);
readTextureData.setPixelAttributes(pixelAttribs);
}
- boolean res = null!=readPixelBuffer;
+ boolean res = null!=readPixelBuffer && readPixelBuffer.isValid();
if(res) {
psm.setAlignment(gl, alignment, alignment);
+ if(gl.isGL2GL3()) {
+ gl.getGL2GL3().glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, readPixelBuffer.width);
+ }
readPixelBuffer.clear();
try {
- gl.glReadPixels(inX, inY, width, height, pixelAttribs.format, pixelAttribs.type, readPixelBuffer);
+ gl.glReadPixels(inX, inY, width, height, pixelAttribs.format, pixelAttribs.type, readPixelBuffer.buffer);
} catch(GLException gle) { res = false; gle.printStackTrace(); }
- readPixelBuffer.position( readPixelSize / Buffers.sizeOfBufferElem(readPixelBuffer) );
+ readPixelBuffer.position( readPixelSize );
readPixelBuffer.flip();
final int glerr1 = gl.glGetError();
if(GL.GL_NO_ERROR != glerr1) {
@@ -261,10 +255,9 @@ public class GLReadBufferUtil {
readTextureData = null;
}
if(null != readPixelBuffer) {
+ readPixelBuffer.dispose();
readPixelBuffer = null;
}
- readPixelSizeLast = 0;
- pixelBufferProvider.dispose();
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
new file mode 100644
index 000000000..2af48cefd
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
@@ -0,0 +1,203 @@
+/**
+ * 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.awt.image.DataBufferInt;
+import java.nio.Buffer;
+import java.nio.IntBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2GL3;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.GLPixelBuffer;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+
+/**
+ * AWT {@link GLPixelBuffer} backed by an {@link BufferedImage} of type
+ * {@link BufferedImage#TYPE_INT_ARGB} or {@link BufferedImage#TYPE_INT_RGB}.
+ * <p>
+ * Implementation uses an array backed {@link IntBuffer}.
+ * </p>
+ * <p>
+ * {@link AWTGLPixelBuffer} can be produced via {@link AWTGLPixelBufferProvider}'s
+ * {@link AWTGLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocate(..)}.
+ * </p>
+ * <p>
+ * See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)} for {@link #allowRowStride} details.
+ * </p>
+ */
+public class AWTGLPixelBuffer extends GLPixelBuffer {
+ public static final GLPixelAttributes awtPixelAttributesIntRGB = new GLPixelAttributes(GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
+
+ /** Allow {@link GL2GL3#GL_PACK_ROW_LENGTH}, or {@link GL2GL3#GL_UNPACK_ROW_LENGTH}. See {@link #requiresNewBuffer(GL, int, int, int)}. */
+ public final boolean allowRowStride;
+ /** The underlying {@link BufferedImage}. */
+ public final BufferedImage image;
+
+ /**
+ * @param pixelAttributes the desired {@link GLPixelAttributes}
+ * @param width in pixels
+ * @param height in pixels
+ * @param depth in pixels
+ * @param pack true for read mode GPU -> CPU, otherwise false for write mode CPU -> GPU
+ * @param image the AWT image
+ * @param buffer the backing array
+ * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link #requiresNewBuffer(GL, int, int, int)}.
+ */
+ public AWTGLPixelBuffer(GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, BufferedImage image,
+ Buffer buffer, boolean allowRowStride) {
+ super(pixelAttributes, width, height, depth, pack, buffer);
+ this.allowRowStride = allowRowStride;
+ this.image = image;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * If <code>{@link #allowRowStride} = false</code>,
+ * method returns <code>true</code> if the new size &ne; current size.
+ * </p>
+ * <p>
+ * If <code>{@link #allowRowStride} = true</code>, see {@link AWTGLPixelBufferProvider#AWTGLPixelBufferProvider(boolean)},
+ * method returns <code>true</code> only if the new size &gt; current size. Assuming user utilizes the row-stride
+ * when dealing w/ the data, i.e. {@link GL2GL3#GL_PACK_ROW_LENGTH}.
+ * </p>
+ */
+ @Override
+ public boolean requiresNewBuffer(GL gl, int newWidth, int newHeight, int minByteSize) {
+ if( allowRowStride && gl.isGL2GL3() ) {
+ return width < newWidth || height < newHeight;
+ } else {
+ return width != newWidth || height != newHeight;
+ }
+ }
+
+ @Override
+ public void dispose() {
+ image.flush();
+ super.dispose();
+ }
+
+ public StringBuffer toString(StringBuffer sb) {
+ sb = super.toString(sb);
+ sb.append(", allowRowStride ").append(allowRowStride).append(", image [").append(image.getWidth()).append("x").append(image.getHeight()).append(", ").append(image.toString()).append("]");
+ return sb;
+ }
+ public String toString() {
+ return "AWTGLPixelBuffer["+toString(null).toString()+"]";
+ }
+
+ /**
+ * Provider for {@link AWTGLPixelBuffer} instances.
+ */
+ public static class AWTGLPixelBufferProvider implements GLPixelBufferProvider {
+ /** Allow {@link GL2GL3#GL_PACK_ROW_LENGTH}, or {@link GL2GL3#GL_UNPACK_ROW_LENGTH}. */
+ public final boolean allowRowStride;
+
+ /**
+ * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+ */
+ public AWTGLPixelBufferProvider(boolean allowRowStride) {
+ this.allowRowStride = allowRowStride;
+ }
+ @Override
+ public GLPixelAttributes getAttributes(GL gl, int componentCount) {
+ return awtPixelAttributesIntRGB;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns an array backed {@link IntBuffer} of size <pre>width*height*{@link Buffers#SIZEOF_INT SIZEOF_INT}</code>.
+ * </p>
+ */
+ @Override
+ public AWTGLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize) {
+ final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+ final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+ final Buffer ibuffer = IntBuffer.wrap( readBackIntBuffer );
+ return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, allowRowStride);
+ }
+ }
+
+ /**
+ * Provider for singleton {@link AWTGLPixelBuffer} instances.
+ * <p>
+ * Provider instance holds the last {@link AWTGLPixelBuffer} instance
+ * {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+ * A new {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocation}
+ * will return same instance, if a new buffer is not {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int) required}.
+ * The latter is true if size are compatible, hence <code>allowRowStride</code> should be enabled, if possible.
+ * </p>
+ */
+ public static class SingleAWTGLPixelBufferProvider extends AWTGLPixelBufferProvider {
+ private AWTGLPixelBuffer single = null;
+
+ /**
+ * @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+ */
+ public SingleAWTGLPixelBufferProvider(boolean allowRowStride) {
+ super(allowRowStride);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns an array backed {@link IntBuffer} of size <pre>width*height*{@link Buffers#SIZEOF_INT SIZEOF_INT}</code>.
+ * </p>
+ */
+ @Override
+ public AWTGLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize) {
+ if( null == single || single.requiresNewBuffer(gl, width, height, minByteSize) ) {
+ single = allocateImpl(pixelAttributes, width, height, depth, pack, minByteSize);
+ }
+ return single;
+ }
+
+ private AWTGLPixelBuffer allocateImpl(GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize) {
+ final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+ final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+ final Buffer ibuffer = IntBuffer.wrap( readBackIntBuffer );
+ return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, allowRowStride);
+ }
+
+ /**
+ * Initializes the single {@link AWTGLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+ * @return the newly initialized single {@link AWTGLPixelBuffer}, or null if already allocated.
+ */
+ public AWTGLPixelBuffer initSingleton(int width, int height, int depth, boolean pack) {
+ if( null != single ) {
+ return null;
+ }
+ single = allocateImpl(AWTGLPixelBuffer.awtPixelAttributesIntRGB, width, height, depth, pack, 0);
+ return single;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
index f26fec0d5..0edd53ca1 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLReadBufferUtil.java
@@ -28,14 +28,11 @@
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 javax.media.opengl.GLProfile;
import com.jogamp.opengl.util.GLReadBufferUtil;
-import com.jogamp.opengl.util.texture.awt.AWTTextureData.AWTPixelBufferProviderInt;
/**
* {@link GLReadBufferUtil} specialization allowing to
@@ -48,25 +45,15 @@ public class AWTGLReadBufferUtil extends GLReadBufferUtil {
*
* @param alpha
*/
- public AWTGLReadBufferUtil(boolean alpha) {
- super(new AWTPixelBufferProviderInt(), alpha, false);
+ public AWTGLReadBufferUtil(GLProfile glp, boolean alpha) {
+ super(new AWTGLPixelBuffer.AWTGLPixelBufferProvider( glp.isGL2GL3() /* allowRowStride */ ), 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 AWTGLPixelBuffer getAWTGLPixelBuffer() { return (AWTGLPixelBuffer)this.getPixelBuffer(); }
public BufferedImage readPixelsToBufferedImage(GL gl, boolean awtOrientation) {
if( readPixels(gl, awtOrientation) ) {
- final BufferedImage image = getImage();
+ final BufferedImage image = getAWTGLPixelBuffer().image;
if( getTextureData().getMustFlipVertically() ) {
ImageUtil.flipImageVertically(image);
}
@@ -78,7 +65,7 @@ public class AWTGLReadBufferUtil extends GLReadBufferUtil {
final int[] ioWidth = new int[] { inWidth };
final int[] ioHeight= new int[] { inHeight };
if( readPixels(gl, inX, inY, ioWidth, ioHeight, awtOrientation) ) {
- final BufferedImage image = getImage();
+ final BufferedImage image = getAWTGLPixelBuffer().image;
if( getTextureData().getMustFlipVertically() ) {
ImageUtil.flipImageVertically(image);
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
index 2f0c86255..dec1b43cf 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java
@@ -38,14 +38,11 @@
package com.jogamp.opengl.util.texture;
import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import javax.media.opengl.GL;
-import javax.media.opengl.GLContext;
import javax.media.opengl.GLProfile;
-import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.GLBuffers;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
/**
* Represents the data for an OpenGL texture. This is separated from
@@ -62,97 +59,10 @@ public class TextureData {
/** ColorSpace of pixel data. */
public static enum ColorSpace { RGB, YCbCr, YCCK, CMYK };
- /** Pixel data attributes. */
- public static class PixelAttributes {
- /** Undefinded instance of {@link PixelAttributes}, having format:=0 and type:= 0. */
- public static final PixelAttributes UNDEF = new PixelAttributes(0, 0);
-
- /** The OpenGL pixel data format */
- public final int format;
- /** The OpenGL pixel data type */
- public final int type;
- public PixelAttributes(int dataFormat, int dataType) {
- this.format = dataFormat;
- this.type = dataType;
- }
- public String toString() {
- return "PixelAttributes[fFmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+"]";
- }
- }
- /** Allows user to interface with another toolkit to define {@link PixelAttributes} and memory buffer to produce {@link TextureData}. */
- public static interface PixelBufferProvider {
- /** Called first to determine {@link PixelAttributes}. */
- PixelAttributes getAttributes(GL gl, int componentCount);
-
- /**
- * Returns true, if implementation requires a new buffer based on the new size
- * and previous aquired {@link #getAttributes(GL, int) attributes} due to pixel alignment, otherwise false.
- * @see #allocate(int, int, int)
- */
- boolean requiresNewBuffer(int width, int height);
-
- /**
- * Called after {@link #getAttributes(GL, int)} to retrieve the NIO or array backed pixel {@link Buffer}.
- * <p>
- * Being called to gather the initial {@link Buffer}, if the existing {@link Buffer} size is not sufficient,
- * or if {@link #requiresNewBuffer(int, int)} returns false.
- * </p>
- * <p>
- * Number of components was passed via {@link #getAttributes(GL, int)}.
- * </p>
- * <p>
- * The returned buffer must have at least <code>minByteSize</code> {@link Buffer#remaining() remaining}.
- * </p>
- */
- Buffer allocate(int width, int height, int minByteSize);
-
- /** Dispose resources. */
- void dispose();
- }
- /**
- * Default {@link PixelBufferProvider} utilizing best match for {@link PixelAttributes}
- * and {@link #allocate(int, int, int) allocating} a {@link ByteBuffer}.
- */
- public static class DefPixelBufferProvider implements PixelBufferProvider {
- @Override
- public PixelAttributes getAttributes(GL gl, int componentCount) {
- final GLContext ctx = gl.getContext();
- final int dFormat, dType;
-
- if(gl.isGL2GL3() && 3 == componentCount) {
- dFormat = GL.GL_RGB;
- dType = GL.GL_UNSIGNED_BYTE;
- } else {
- dFormat = ctx.getDefaultPixelDataFormat();
- dType = ctx.getDefaultPixelDataType();
- }
- return new TextureData.PixelAttributes(dFormat, dType);
- }
- @Override
- public boolean requiresNewBuffer(int width, int height) {
- return false;
- }
- /**
- * {@inheritDoc}
- * <p>
- * Returns an NIO {@link ByteBuffer} of <code>minByteSize</code>.
- * </p>
- */
- @Override
- public final Buffer allocate(int width, int height, int minByteSize) {
- return Buffers.newDirectByteBuffer(minByteSize);
- }
-
- @Override
- public void dispose() {
- // nop
- }
- }
-
protected int width;
protected int height;
private int border;
- protected PixelAttributes pixelAttributes;
+ protected GLPixelAttributes pixelAttributes;
protected int internalFormat; // perhaps inferred from pixelFormat?
protected boolean mipmap; // indicates whether mipmaps should be generated
// (ignored if mipmaps are supplied from the file)
@@ -225,7 +135,7 @@ public class TextureData {
boolean mustFlipVertically,
Buffer buffer,
Flusher flusher) throws IllegalArgumentException {
- this(glp, internalFormat, width, height, border, new PixelAttributes(pixelFormat, pixelType),
+ this(glp, internalFormat, width, height, border, new GLPixelAttributes(pixelFormat, pixelType),
mipmap, dataIsCompressed, mustFlipVertically, buffer, flusher);
}
@@ -273,7 +183,7 @@ public class TextureData {
int width,
int height,
int border,
- PixelAttributes pixelAttributes,
+ GLPixelAttributes pixelAttributes,
boolean mipmap,
boolean dataIsCompressed,
boolean mustFlipVertically,
@@ -348,7 +258,7 @@ public class TextureData {
boolean mustFlipVertically,
Buffer[] mipmapData,
Flusher flusher) throws IllegalArgumentException {
- this(glp, internalFormat, width, height, border, new PixelAttributes(pixelFormat, pixelType),
+ this(glp, internalFormat, width, height, border, new GLPixelAttributes(pixelFormat, pixelType),
dataIsCompressed, mustFlipVertically, mipmapData, flusher);
}
@@ -395,7 +305,7 @@ public class TextureData {
int width,
int height,
int border,
- PixelAttributes pixelAttributes,
+ GLPixelAttributes pixelAttributes,
boolean dataIsCompressed,
boolean mustFlipVertically,
Buffer[] mipmapData,
@@ -429,7 +339,7 @@ public class TextureData {
public void setColorSpace(ColorSpace cs) { pixelCS = cs; }
/** Used only by subclasses */
- protected TextureData(GLProfile glp) { this.glProfile = glp; this.pixelAttributes = PixelAttributes.UNDEF; }
+ protected TextureData(GLProfile glp) { this.glProfile = glp; this.pixelAttributes = GLPixelAttributes.UNDEF; }
/** Returns the width in pixels of the texture data. */
public int getWidth() { return width; }
@@ -439,8 +349,8 @@ public class TextureData {
public int getBorder() {
return border;
}
- /** Returns the intended OpenGL {@link PixelAttributes} of the texture data, i.e. format and type. */
- public PixelAttributes getPixelAttributes() {
+ /** Returns the intended OpenGL {@link GLPixelAttributes} of the texture data, i.e. format and type. */
+ public GLPixelAttributes getPixelAttributes() {
return pixelAttributes;
}
/** Returns the intended OpenGL pixel format of the texture data. */
@@ -495,27 +405,27 @@ public class TextureData {
/** Sets the border in pixels of the texture data. */
public void setBorder(int border) { this.border = border; }
/** Sets the intended OpenGL pixel format of the texture data. */
- public void setPixelAttributes(PixelAttributes pixelAttributes) { this.pixelAttributes = pixelAttributes; }
+ public void setPixelAttributes(GLPixelAttributes pixelAttributes) { this.pixelAttributes = pixelAttributes; }
/**
- * Sets the intended OpenGL pixel format component of {@link PixelAttributes} of the texture data.
+ * Sets the intended OpenGL pixel format component of {@link GLPixelAttributes} of the texture data.
* <p>
- * Use {@link #setPixelAttributes(PixelAttributes)}, if setting format and type.
+ * Use {@link #setPixelAttributes(GLPixelAttributes)}, if setting format and type.
* </p>
*/
public void setPixelFormat(int pixelFormat) {
if( pixelAttributes.format != pixelFormat ) {
- pixelAttributes = new PixelAttributes(pixelFormat, pixelAttributes.type);
+ pixelAttributes = new GLPixelAttributes(pixelFormat, pixelAttributes.type);
}
}
/**
- * Sets the intended OpenGL pixel type component of {@link PixelAttributes} of the texture data.
+ * Sets the intended OpenGL pixel type component of {@link GLPixelAttributes} of the texture data.
* <p>
- * Use {@link #setPixelAttributes(PixelAttributes)}, if setting format and type.
+ * Use {@link #setPixelAttributes(GLPixelAttributes)}, if setting format and type.
* </p>
*/
public void setPixelType(int pixelType) {
if( pixelAttributes.type != pixelType) {
- pixelAttributes = new PixelAttributes(pixelAttributes.format, pixelType);
+ pixelAttributes = new GLPixelAttributes(pixelAttributes.format, pixelType);
}
}
/** Sets the intended OpenGL internal format of the texture data. */
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
index 7a0f00edf..d7e825c1d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java
@@ -66,62 +66,10 @@ import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
-import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
import com.jogamp.opengl.util.texture.TextureData;
-import com.jogamp.opengl.util.texture.TextureData.PixelBufferProvider;
public class AWTTextureData extends TextureData {
- public static final PixelAttributes awtPixelAttributesIntRGB = new PixelAttributes(GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
-
- /**
- * AWT {@link PixelBufferProvider} backed by a {@link BufferedImage} of type
- * {@link BufferedImage#TYPE_INT_ARGB} or {@link BufferedImage#TYPE_INT_RGB}
- * and {@link #allocate(int, int, int) allocating} am array backed {@link IntBuffer}.
- */
- public static final class AWTPixelBufferProviderInt implements PixelBufferProvider {
- private BufferedImage image = null;
- private int componentCount = 0;
-
- @Override
- public PixelAttributes getAttributes(GL gl, int componentCount) {
- this.componentCount = componentCount;
- return awtPixelAttributesIntRGB;
- }
- @Override
- public boolean requiresNewBuffer(int width, int height) {
- return null == image || image.getWidth() != width || image.getHeight() != height;
- }
- /**
- * {@inheritDoc}
- * <p>
- * Returns an array backed {@link IntBuffer} of size <pre>width*height*{@link Buffers#SIZEOF_INT SIZEOF_INT}</code>.
- * </p>
- */
- @Override
- public Buffer allocate(int width, int height, int minByteSize) {
- image = new BufferedImage(width, height, 4 == componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
- final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
- return IntBuffer.wrap( readBackIntBuffer );
- }
-
- @Override
- public void dispose() {
- if(null != image) {
- image.flush();
- image = null;
- }
- }
-
- /** Returns the number source components being used as indicated at {@link #allocate(int, int, int)}. */
- public int getComponentCount() { return componentCount; }
-
- /** Returns the underlying {@link BufferedImage} as allocated via {@link #allocate(int, int, int)}. */
- public BufferedImage getImage() { return image; }
-
- /** Returns true if an underlying {@link BufferedImage} has been allocated via {@link #allocate(int, int, int)}. */
- public boolean hasImage() { return null != image; }
- }
-
// Mechanism for lazily converting input BufferedImages with custom
// ColorModels to standard ones for uploading to OpenGL, as well as
// backing off from the optimizations of hoping that either
@@ -198,7 +146,7 @@ public class AWTTextureData extends TextureData {
}
@Override
- public PixelAttributes getPixelAttributes() {
+ public GLPixelAttributes getPixelAttributes() {
validatePixelAttributes();
return super.getPixelAttributes();
}
@@ -229,7 +177,7 @@ public class AWTTextureData extends TextureData {
}
private void createFromImage(GLProfile glp, BufferedImage image) {
- pixelAttributes = PixelAttributes.UNDEF; // Determine from image
+ pixelAttributes = GLPixelAttributes.UNDEF; // Determine from image
mustFlipVertically = true;
width = image.getWidth();
@@ -259,21 +207,21 @@ public class AWTTextureData extends TextureData {
if (glp.isGL2GL3()) {
switch (image.getType()) {
case BufferedImage.TYPE_INT_RGB:
- pixelAttributes = new PixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
+ pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
rowLength = scanlineStride;
alignment = 4;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_INT_ARGB_PRE:
- pixelAttributes = new PixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
+ pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
rowLength = scanlineStride;
alignment = 4;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_INT_BGR:
- pixelAttributes = new PixelAttributes(GL.GL_RGBA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV);
rowLength = scanlineStride;
alignment = 4;
expectingGL12 = true;
@@ -284,7 +232,7 @@ public class AWTTextureData extends TextureData {
// we can pass the image data directly to OpenGL only if
// we have an integral number of pixels in each scanline
if ((scanlineStride % 3) == 0) {
- pixelAttributes = new PixelAttributes(GL2GL3.GL_BGR, GL.GL_UNSIGNED_BYTE);
+ pixelAttributes = new GLPixelAttributes(GL2GL3.GL_BGR, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 3;
alignment = 1;
} else {
@@ -304,7 +252,7 @@ public class AWTTextureData extends TextureData {
// the necessary byte swapping (FIXME: needs more
// investigation)
if ((scanlineStride % 4) == 0 && glp.isGL2() && false) {
- pixelAttributes = new PixelAttributes(GL2.GL_ABGR_EXT, GL.GL_UNSIGNED_BYTE);
+ pixelAttributes = new GLPixelAttributes(GL2.GL_ABGR_EXT, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 4;
alignment = 4;
@@ -320,26 +268,26 @@ public class AWTTextureData extends TextureData {
}
}
case BufferedImage.TYPE_USHORT_565_RGB:
- pixelAttributes = new PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
rowLength = scanlineStride;
alignment = 2;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_USHORT_555_RGB:
- pixelAttributes = new PixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV);
+ pixelAttributes = new GLPixelAttributes(GL.GL_BGRA, GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV);
rowLength = scanlineStride;
alignment = 2;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_BYTE_GRAY:
- pixelAttributes = new PixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
+ pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride;
alignment = 1;
break;
case BufferedImage.TYPE_USHORT_GRAY:
- pixelAttributes = new PixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_SHORT);
+ pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_SHORT);
rowLength = scanlineStride;
alignment = 2;
break;
@@ -354,11 +302,11 @@ public class AWTTextureData extends TextureData {
default:
java.awt.image.ColorModel cm = image.getColorModel();
if (cm.equals(rgbColorModel)) {
- pixelAttributes = new PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 3;
alignment = 1;
} else if (cm.equals(rgbaColorModel)) {
- pixelAttributes = new PixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 4; // FIXME: correct?
alignment = 4;
} else {
@@ -370,7 +318,7 @@ public class AWTTextureData extends TextureData {
} else {
switch (image.getType()) {
case BufferedImage.TYPE_INT_RGB:
- pixelAttributes = new PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride;
alignment = 3;
expectingGL12 = true;
@@ -385,21 +333,21 @@ public class AWTTextureData extends TextureData {
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
throw new GLException("INT_BGR n.a.");
case BufferedImage.TYPE_USHORT_565_RGB:
- pixelAttributes = new PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_SHORT_5_6_5);
rowLength = scanlineStride;
alignment = 2;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_USHORT_555_RGB:
- pixelAttributes = new PixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1);
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_SHORT_5_5_5_1);
rowLength = scanlineStride;
alignment = 2;
expectingGL12 = true;
setupLazyCustomConversion(image);
break;
case BufferedImage.TYPE_BYTE_GRAY:
- pixelAttributes = new PixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
+ pixelAttributes = new GLPixelAttributes(GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride;
alignment = 1;
break;
@@ -416,11 +364,11 @@ public class AWTTextureData extends TextureData {
default:
java.awt.image.ColorModel cm = image.getColorModel();
if (cm.equals(rgbColorModel)) {
- pixelAttributes = new PixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 3;
alignment = 1;
} else if (cm.equals(rgbaColorModel)) {
- pixelAttributes = new PixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
+ pixelAttributes = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
rowLength = scanlineStride / 4; // FIXME: correct?
alignment = 4;
} else {
@@ -465,7 +413,7 @@ public class AWTTextureData extends TextureData {
} else {
throw new RuntimeException("Unexpected DataBuffer type?");
}
- pixelAttributes = new PixelAttributes(pixelFormat, pixelType);
+ pixelAttributes = new GLPixelAttributes(pixelFormat, pixelType);
}
private void createFromCustom(BufferedImage image) {
@@ -524,7 +472,7 @@ public class AWTTextureData extends TextureData {
// and knowing we're in the process of doing the fallback code
// path, re-infer a vanilla pixel format and type compatible with
// OpenGL 1.1
- pixelAttributes = PixelAttributes.UNDEF;
+ pixelAttributes = GLPixelAttributes.UNDEF;
setupLazyCustomConversion(imageForLazyCustomConversion);
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 65bcab100..3f3e88977 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -86,10 +86,11 @@ import jogamp.opengl.awt.Java2D;
import jogamp.opengl.util.glsl.GLSLTextureRaster;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.opengl.FBObject;
-import com.jogamp.opengl.util.GLBuffers;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
import com.jogamp.opengl.util.GLPixelStorageModes;
-import com.jogamp.opengl.util.texture.TextureData.PixelAttributes;
-import com.jogamp.opengl.util.texture.awt.AWTTextureData.AWTPixelBufferProviderInt;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider;
/** A lightweight Swing component which provides OpenGL rendering
support. Provided for compatibility with Swing user interfaces
@@ -133,12 +134,58 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private static final boolean DEBUG_VIEWPORT = Debug.isPropertyDefined("jogl.debug.GLJPanel.Viewport", true);
private static final boolean USE_GLSL_TEXTURE_RASTERIZER = !Debug.isPropertyDefined("jogl.gljpanel.noglsl", true);
+ /** Indicates whether the Java 2D OpenGL pipeline is requested by user. */
+ private static final boolean java2dOGLEnabledByProp;
+
+ /** Indicates whether the Java 2D OpenGL pipeline is enabled, resource-compatible and requested by user. */
+ private static final boolean useJava2DGLPipeline;
+
+ /** Indicates whether the Java 2D OpenGL pipeline's usage is error free. */
+ private static boolean java2DGLPipelineOK;
+
+ static {
+ boolean enabled = false;
+ final String sVal = System.getProperty("sun.java2d.opengl");
+ if( null != sVal ) {
+ enabled = Boolean.valueOf(sVal);
+ }
+ java2dOGLEnabledByProp = enabled && !Debug.isPropertyDefined("jogl.gljpanel.noogl", true);
+
+ enabled = false;
+ if( java2dOGLEnabledByProp ) {
+ // Force eager initialization of part of the Java2D class since
+ // otherwise it's likely it will try to be initialized while on
+ // the Queue Flusher Thread, which is not allowed
+ if (Java2D.isOGLPipelineResourceCompatible() && Java2D.isFBOEnabled()) {
+ if( null != Java2D.getShareContext(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()) ) {
+ enabled = true;
+ }
+ }
+ }
+ useJava2DGLPipeline = enabled;
+ java2DGLPipelineOK = enabled;
+ if( DEBUG ) {
+ System.err.println("GLJPanel: java2dOGLEnabledByProp "+java2dOGLEnabledByProp);
+ System.err.println("GLJPanel: useJava2DGLPipeline "+useJava2DGLPipeline);
+ System.err.println("GLJPanel: java2DGLPipelineOK "+java2DGLPipelineOK);
+ }
+ }
+
+ private static SingleAWTGLPixelBufferProvider singleAWTGLPixelBufferProvider = null;
+ private static synchronized SingleAWTGLPixelBufferProvider getSingleAWTGLPixelBufferProvider() {
+ if( null == singleAWTGLPixelBufferProvider ) {
+ singleAWTGLPixelBufferProvider = new SingleAWTGLPixelBufferProvider( true /* allowRowStride */ );
+ }
+ return singleAWTGLPixelBufferProvider;
+ }
+
private GLDrawableHelper helper = new GLDrawableHelper();
private volatile boolean isInitialized;
//
// Data used for either pbuffers or pixmap-based offscreen surfaces
//
+ private AWTGLPixelBufferProvider customPixelBufferProvider = null;
/** Single buffered offscreen caps */
private GLCapabilitiesImmutable offscreenCaps;
private GLProfile glProfile;
@@ -170,10 +217,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// Used by all backends either directly or indirectly to hook up callbacks
private Updater updater = new Updater();
- // Indicates whether the Java 2D OpenGL pipeline is enabled and resource-compatible
- private boolean oglPipelineUsable =
- Java2D.isOGLPipelineResourceCompatible() &&
- !Debug.isPropertyDefined("jogl.gljpanel.noogl", true);
+ private boolean oglPipelineUsable() {
+ return null == customPixelBufferProvider && useJava2DGLPipeline && java2DGLPipelineOK;
+ }
private AWTWindowClosingProtocol awtWindowClosingProtocol =
new AWTWindowClosingProtocol(this, new Runnable() {
@@ -183,17 +229,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
}, null);
- static {
- // Force eager initialization of part of the Java2D class since
- // otherwise it's likely it will try to be initialized while on
- // the Queue Flusher Thread, which is not allowed
- if (Java2D.isOGLPipelineResourceCompatible() && Java2D.isFBOEnabled()) {
- Java2D.getShareContext(GraphicsEnvironment.
- getLocalGraphicsEnvironment().
- getDefaultScreenDevice());
- }
- }
-
/** Creates a new GLJPanel component with a default set of OpenGL
capabilities and using the default OpenGL capabilities selection
mechanism.
@@ -252,6 +287,23 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
this.setFocusable(true); // allow keyboard input!
}
+ public AWTGLPixelBufferProvider getCustomPixelBufferProvider() { return customPixelBufferProvider; }
+
+ /**
+ * @param custom custom {@link AWTGLPixelBufferProvider}
+ * @throws IllegalArgumentException if <code>custom</code> is <code>null</code>
+ * @throws IllegalStateException if backend is already realized, i.e. this instanced already painted once.
+ */
+ public void setPixelBufferProvider(AWTGLPixelBufferProvider custom) throws IllegalArgumentException, IllegalStateException {
+ if( null == custom ) {
+ throw new IllegalArgumentException("Null PixelBufferProvider");
+ }
+ if( null != backend ) {
+ throw new IllegalStateException("Backend already realized.");
+ }
+ customPixelBufferProvider = custom;
+ }
+
@Override
public final Object getUpstreamWidget() {
return this;
@@ -629,7 +681,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
to perform OpenGL rendering using the GLJPanel into the same
OpenGL drawable as the Swing implementation uses. */
public boolean shouldPreserveColorBufferIfTranslucent() {
- return oglPipelineUsable;
+ return oglPipelineUsable();
}
@Override
@@ -701,10 +753,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
if ( null == backend ) {
- if (oglPipelineUsable) {
+ if ( oglPipelineUsable() ) {
backend = new J2DOGLBackend();
} else {
- backend = new OffscreenBackend();
+ backend = new OffscreenBackend(glProfile, customPixelBufferProvider);
}
isInitialized = false;
}
@@ -922,14 +974,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// backends, both of which rely on reading back the OpenGL frame
// buffer and drawing it with a BufferedImage
class OffscreenBackend implements Backend {
- protected AWTPixelBufferProviderInt pixelBufferProvider = new AWTPixelBufferProviderInt();
- private PixelAttributes pixelAttribs;
+ private final AWTGLPixelBufferProvider pixelBufferProvider;
+ private AWTGLPixelBuffer pixelBuffer;
+ private boolean pixelBufferCheckSize;
// One of these is used to store the read back pixels before storing
// in the BufferedImage
- protected IntBuffer readBackInts;
- protected int readBackWidthInPixels;
- protected int readBackHeightInPixels;
+ protected IntBuffer readBackInts;
// Implementation using software rendering
private GLDrawableImpl offscreenDrawable;
@@ -943,6 +994,15 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// For saving/restoring of OpenGL state during ReadPixels
private final GLPixelStorageModes psm = new GLPixelStorageModes();
+ OffscreenBackend(GLProfile glp, AWTGLPixelBufferProvider custom) {
+ if(null == custom) {
+ pixelBufferProvider = glp.isGL2GL3() ? getSingleAWTGLPixelBufferProvider() :
+ new AWTGLPixelBufferProvider( true /* allowRowStride */ );
+ } else {
+ pixelBufferProvider = custom;
+ }
+ }
+
@Override
public boolean isUsingOwnLifecycle() { return false; }
@@ -1049,7 +1109,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public void setOpaque(boolean opaque) {
if (opaque != isOpaque()) {
- pixelBufferProvider.dispose();
+ pixelBuffer.dispose();
+ pixelBuffer = null;
}
}
@@ -1076,30 +1137,38 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
alignment = 4;
}
+ final GLPixelAttributes pixelAttribs;
+
+ if( pixelBufferCheckSize ) {
+ pixelBufferCheckSize = false;
+ if( null != pixelBuffer && pixelBuffer.requiresNewBuffer(gl, panelWidth, panelHeight, 0) ) {
+ pixelBuffer.dispose();
+ pixelBuffer = null;
+ }
+ }
+
// Must now copy pixels from offscreen context into surface
- if ( !pixelBufferProvider.hasImage() ) {
+ if ( null == pixelBuffer ) {
if (0 >= panelWidth || 0 >= panelHeight ) {
return;
}
pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
-
- final int[] tmp = { 0 };
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.format, pixelAttribs.type, panelWidth, panelHeight, 1, true);
- final IntBuffer intBuffer = (IntBuffer) pixelBufferProvider.allocate(panelWidth, panelHeight, readPixelSize);
- if(!flipVertical || null != glslTextureRaster) {
- readBackInts = intBuffer;
+ pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, panelWidth, panelHeight, 1, true, 0);
+ if( !flipVertical || null != glslTextureRaster ) {
+ readBackInts = (IntBuffer) pixelBuffer.buffer;
} else {
- readBackInts = IntBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels);
+ readBackInts = IntBuffer.allocate(pixelBuffer.width * pixelBuffer.height);
}
if(DEBUG) {
- final BufferedImage offscreenImage = pixelBufferProvider.getImage();
- System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: pixelAttribs "+pixelAttribs);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: pixelBufferProvider 0x"+Integer.toHexString(pixelBufferProvider.hashCode())+", "+pixelBufferProvider.getClass().getSimpleName());
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: pixelBuffer 0x"+Integer.toHexString(pixelBuffer.hashCode())+", "+pixelBuffer+", alignment "+alignment);
System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: flippedVertical "+flipVertical+", glslTextureRaster "+(null!=glslTextureRaster));
- System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: panelSize "+panelWidth+"x"+panelHeight +", readBackSizeInPixels "+readBackWidthInPixels+"x"+readBackHeightInPixels);
- System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: offscreenImage "+offscreenImage.getWidth()+"x"+offscreenImage.getHeight());
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: panelSize "+panelWidth+"x"+panelHeight);
}
- }
+ } else {
+ pixelAttribs = pixelBuffer.pixelAttributes;
+ }
if( DEBUG_VIEWPORT ) {
int[] vp = new int[] { 0, 0, 0, 0 };
@@ -1111,7 +1180,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
psm.setAlignment(gl, alignment, alignment);
if(gl.isGL2GL3()) {
final GL2GL3 gl2gl3 = gl.getGL2GL3();
- gl2gl3.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, readBackWidthInPixels);
+ gl2gl3.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, pixelBuffer.width);
gl2gl3.glReadBuffer(gl2gl3.getDefaultReadBuffer());
}
@@ -1127,27 +1196,25 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
gl.glBindTexture(GL.GL_TEXTURE_2D, fboTex.getName());
// gl.glClear(GL.GL_DEPTH_BUFFER_BIT); // fboFlipped runs w/o DEPTH!
glslTextureRaster.display(gl.getGL2ES2());
- gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, pixelAttribs.format, pixelAttribs.type, readBackInts);
+ gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
fboFlipped.unbind(gl);
} else {
- gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, pixelAttribs.format, pixelAttribs.type, readBackInts);
+ gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
if ( flipVertical ) {
// Copy temporary data into raster of BufferedImage for faster
// blitting Note that we could avoid this copy in the cases
- // where !offscreenContext.offscreenImageNeedsVerticalFlip(),
- // but that's the software rendering path which is very slow
- // anyway
- final BufferedImage offscreenImage = pixelBufferProvider.getImage();
- final Object src = readBackInts.array();
- final Object dest = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData();
- final int srcIncr = readBackWidthInPixels;
- final int destIncr = offscreenImage.getWidth();
+ // where !offscreenDrawable.isGLOriented(),
+ // but that's the software rendering path which is very slow anyway.
+ final BufferedImage image = pixelBuffer.image;
+ final int[] src = readBackInts.array();
+ final int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+ final int incr = pixelBuffer.width;
int srcPos = 0;
- int destPos = (offscreenImage.getHeight() - 1) * destIncr;
- for (; destPos >= 0; srcPos += srcIncr, destPos -= destIncr) {
- System.arraycopy(src, srcPos, dest, destPos, destIncr);
+ int destPos = (panelHeight - 1) * pixelBuffer.width;
+ for (; destPos >= 0; srcPos += incr, destPos -= incr) {
+ System.arraycopy(src, srcPos, dest, destPos, incr);
}
}
}
@@ -1164,13 +1231,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
public void doPaintComponent(Graphics g) {
helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction);
- final BufferedImage offscreenImage = pixelBufferProvider.getImage();
- if ( null != offscreenImage ) {
+ if ( null != pixelBuffer ) {
+ final BufferedImage image = pixelBuffer.image;
// Draw resulting image in one shot
- g.drawImage(offscreenImage, 0, 0,
- offscreenImage.getWidth(),
- offscreenImage.getHeight(),
- null /* Null ImageObserver since image data is ready. */);
+ g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null); // Null ImageObserver since image data is ready.
}
}
@@ -1201,8 +1265,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
panelWidth = _drawable.getWidth();
panelHeight = _drawable.getHeight();
- readBackWidthInPixels = panelWidth;
- readBackHeightInPixels = panelHeight;
if( null != glslTextureRaster ) {
if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
@@ -1216,7 +1278,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
}
- pixelBufferProvider.dispose();
+ pixelBufferCheckSize = true;
return _drawable.isRealized();
}
@@ -1618,7 +1680,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
isInitialized = false;
backend = null;
- oglPipelineUsable = false;
+ java2DGLPipelineOK = false;
handleReshape = true;
j2dContext.destroy();
j2dContext = null;
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 81be58aa5..22c1f62dd 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
@@ -84,7 +84,7 @@ public class TestBug461FBOSupersamplingSwingAWT extends UITestCase implements GL
/* @Override */
public void init(GLAutoDrawable drawable) {
- awtGLReadBufferUtil = new AWTGLReadBufferUtil(false);
+ awtGLReadBufferUtil = new AWTGLReadBufferUtil(drawable.getGLProfile(), false);
}
/* @Override */
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 3f593e908..dc1d528f8 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((ByteBuffer)rbu.getPixelBuffer(), glad.getWidth(), glad.getHeight(), 3);
+ testFlipped((ByteBuffer)rbu.getPixelBuffer().buffer, glad.getWidth(), glad.getHeight(), 3);
glad.destroy();
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java
index e4c0f47a4..0b0030d99 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java
@@ -30,7 +30,10 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2.awt;
import java.awt.AWTException;
import java.awt.BorderLayout;
-import java.awt.Dimension;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
import java.lang.reflect.InvocationTargetException;
import java.nio.FloatBuffer;
@@ -39,8 +42,10 @@ import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLJPanel;
+import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
+import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import org.junit.AfterClass;
@@ -54,11 +59,15 @@ import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.FPSAnimator;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider;
public class TestGearsES2GLJPanelsAWT extends UITestCase {
static int demoCount = 4;
- static boolean opaque = false; // always faster and flicker-less w/o opaque, i.e. w/ alpha channel due to JComponent _paintImmediately(..)
- static float alpha = 0.3f;
+ static boolean jOpaque = false; // flicker-less w/o opaque, opaque leads to overdraw w/ mixed clipRects -> flicker - due to JComponent _paintImmediately(..) (?)
+ static boolean glOpaque = true; // can be either ..
+ static float glAlpha = 0.3f;
+ static boolean jZOrder = false;
static GLProfile glp;
static boolean shallUsePBuffer = false;
static boolean shallUseBitmap = false;
@@ -66,7 +75,15 @@ public class TestGearsES2GLJPanelsAWT extends UITestCase {
static int swapInterval = 0;
static boolean useAnimator = true;
static boolean manualTest = false;
+ static boolean useSingleBuffer = true; // default
+ /**
+ * Even though GLJPanel uses a SingleAWTGLPixelBufferProvider per default,
+ * we like to initialize it's size to a common maximum to ensure
+ * only one {@link AWTGLPixelBuffer} gets allocated.
+ */
+ static SingleAWTGLPixelBufferProvider singleAWTGLPixelBufferProvider;
+
@BeforeClass
public static void initClass() {
if(GLProfile.isAvailable(GLProfile.GL2)) {
@@ -75,21 +92,33 @@ public class TestGearsES2GLJPanelsAWT extends UITestCase {
} else {
setTestSupported(false);
}
+
+ if( useSingleBuffer ) {
+ singleAWTGLPixelBufferProvider = new SingleAWTGLPixelBufferProvider( glp.isGL2GL3() /* allowRowStride */);
+ singleAWTGLPixelBufferProvider.initSingleton(600, 600, 1, true);
+ } else {
+ singleAWTGLPixelBufferProvider = null;
+ }
}
@AfterClass
public static void releaseClass() {
}
- private void addPanel(GLCapabilitiesImmutable caps, GLAnimatorControl anim, final JFrame frame, boolean opaque, int x, int y, int w, int h, FloatBuffer color, float[] clearColor)
+ final static boolean useInterPanel = true;
+
+ /** Adds new JPanel to frame's content pane at index 0 */
+ private JComponent addPanel(GLCapabilitiesImmutable caps, GLAnimatorControl anim, final JFrame frame, boolean opaque, int x, int y, int w, int h, FloatBuffer color, float[] clearColor)
throws InterruptedException, InvocationTargetException
{
final GLJPanel canvas = new GLJPanel(caps);
+ if( useSingleBuffer ) {
+ canvas.setPixelBufferProvider( singleAWTGLPixelBufferProvider );
+ }
canvas.setOpaque(opaque);
- final Dimension glc_sz = new Dimension(w, h);
- canvas.setMinimumSize(glc_sz);
- canvas.setPreferredSize(glc_sz);
- canvas.setSize(glc_sz);
+ if ( !useInterPanel ) {
+ canvas.setBounds(x, y, w, h);
+ }
GearsES2 demo = new GearsES2(swapInterval);
demo.setIgnoreFocus(true);
demo.setGearsColors(color, color, color);
@@ -99,31 +128,62 @@ public class TestGearsES2GLJPanelsAWT extends UITestCase {
anim.add(canvas);
}
- final JPanel panel = new JPanel(new BorderLayout());
- panel.setBounds(x, y, w, h);
- panel.setOpaque(opaque);
+ final JPanel panel;
+ final JTextField text;
+ if ( useInterPanel ) {
+ panel = new JPanel(new BorderLayout());
+ panel.setBounds(x, y, w, h);
+ panel.setOpaque(opaque);
+ text = new JTextField(x+"/"+y+" "+w+"x"+h);
+ text.setOpaque(true);
+ } else {
+ panel = null;
+ text = null;
+ }
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- panel.add(canvas, BorderLayout.CENTER);
- frame.getContentPane().add(panel);
+ if ( useInterPanel ) {
+ panel.add(text, BorderLayout.NORTH);
+ panel.add(canvas, BorderLayout.CENTER);
+ frame.getContentPane().add(panel, 0);
+ } else {
+ frame.getContentPane().add(canvas, 0);
+ }
} } ) ;
+ return useInterPanel ? panel : canvas;
}
public static final FloatBuffer red = Buffers.newDirectFloatBuffer( new float[] { 1.0f, 0.0f, 0.0f, 1.0f } );
public static final FloatBuffer green = Buffers.newDirectFloatBuffer( new float[] { 0.0f, 1.0f, 0.0f, 1.0f } );
public static final FloatBuffer blue = Buffers.newDirectFloatBuffer( new float[] { 0.0f, 0.0f, 1.0f, 1.0f } );
public static final FloatBuffer yellow = Buffers.newDirectFloatBuffer( new float[] { 1.0f, 1.0f, 0.0f, 1.0f } );
+ public static final FloatBuffer grey = Buffers.newDirectFloatBuffer( new float[] { 0.5f, 0.5f, 0.5f, 1.0f } );
public static final float grayf = 0.3f;
- public static final float[] redish = new float[] { grayf, 0.0f, 0.0f, alpha };
- public static final float[] greenish = new float[] { 0.0f, grayf, 0.0f, alpha };
- public static final float[] blueish = new float[] { 0.0f, 0.0f, grayf, alpha };
- public static final float[] yellowish = new float[] { grayf, grayf, 0.0f, alpha };
+ public static final float[] redish = new float[] { grayf, 0.0f, 0.0f, glAlpha };
+ public static final float[] greenish = new float[] { 0.0f, grayf, 0.0f, glAlpha };
+ public static final float[] blueish = new float[] { 0.0f, 0.0f, grayf, glAlpha };
+ public static final float[] yellowish = new float[] { grayf, grayf, 0.0f, glAlpha };
+ public static final float[] greyish = new float[] { grayf, grayf, grayf, glAlpha };
+
+ protected void relayout(Container cont, float oW, float oH) {
+ final int count = cont.getComponentCount();
+ final int nW = cont.getWidth();
+ final int nH = cont.getHeight();
+ for(int i = 0 ; i < count; i++ ) {
+ final Component comp = cont.getComponent(i);
+ float fx = comp.getX() / oW;
+ float fy = comp.getY() / oH;
+ float fw = comp.getWidth() / oW;
+ float fh = comp.getHeight() / oH;
+ comp.setBounds( (int)(fx * nW), (int)(fy * nH), (int)(fw * nW), (int)(fh * nH) );
+ }
+ }
protected void runTestGL(GLCapabilities caps)
throws AWTException, InterruptedException, InvocationTargetException
{
- if( !opaque ) {
+ if( !glOpaque ) {
caps.setAlphaBits(caps.getRedBits());
}
@@ -137,22 +197,46 @@ public class TestGearsES2GLJPanelsAWT extends UITestCase {
frame.getContentPane().setLayout(null);
} } );
+ final float[] oldSize = new float[] { 600f, 600f };
+
+ frame.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ final int count = frame.getComponentCount();
+ for(int i = 0 ; i < count; i++ ) {
+ relayout(frame.getContentPane(), oldSize[0], oldSize[1]);
+ }
+ frame.getContentPane().invalidate();
+ frame.getContentPane().validate();
+ // frame.pack();
+ oldSize[0] = frame.getContentPane().getWidth();
+ oldSize[1] = frame.getContentPane().getHeight();
+ }
+ } ) ;
+
if( demoCount > 0 ) {
- addPanel(caps, animator, frame, opaque, 50, 50, 300, 300, red, redish); // A
+ addPanel(caps, animator, frame, jOpaque, 50, 50, 300, 300, red, redish); // A
}
if( demoCount > 1 ) {
- addPanel(caps, animator, frame, opaque, 200, 0, 150, 150, green, greenish); // B
+ addPanel(caps, animator, frame, jOpaque, 0, 250, 300, 300, blue, blueish); // C
}
if( demoCount > 2 ) {
- addPanel(caps, animator, frame, opaque, 0, 250, 300, 300, blue, blueish); // C
+ addPanel(caps, animator, frame, jOpaque, 300, 0, 150, 150, green, greenish); // B
}
if( demoCount > 3 ) {
- addPanel(caps, animator, frame, opaque, 300, 300, 100, 100, yellow, yellowish); // D
+ addPanel(caps, animator, frame, jOpaque, 300, 300, 100, 100, yellow, yellowish); // D
+ }
+ if( jZOrder ) {
+ final Container cont = frame.getContentPane();
+ final int count = cont.getComponentCount();
+ for(int i = 0 ; i < count; i++ ) {
+ cont.setComponentZOrder(cont.getComponent(i), count - 1 - i);
+ }
}
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- frame.setSize(600, 600);
+ frame.setSize((int)oldSize[0], (int)oldSize[1]);
frame.getContentPane().validate();
// frame.pack();
frame.setVisible(true);
@@ -284,11 +368,20 @@ public class TestGearsES2GLJPanelsAWT extends UITestCase {
swapInterval = MiscUtils.atoi(args[i], swapInterval);
} else if(args[i].equals("-msaa")) {
useMSAA = true;
- } else if(args[i].equals("-opaque")) {
- opaque = true;
+ } else if(args[i].equals("-jOpaque")) {
+ i++;
+ jOpaque = MiscUtils.atob(args[i], jOpaque);
+ } else if(args[i].equals("-glOpaque")) {
+ i++;
+ glOpaque = MiscUtils.atob(args[i], glOpaque);
} else if(args[i].equals("-alpha")) {
i++;
- alpha = MiscUtils.atof(args[i], alpha);
+ glAlpha = MiscUtils.atof(args[i], glAlpha);
+ } else if(args[i].equals("-singleBuffer")) {
+ i++;
+ useSingleBuffer = MiscUtils.atob(args[i], useSingleBuffer);
+ } else if(args[i].equals("-jZOrder")) {
+ jZOrder = true;
} else if(args[i].equals("-noanim")) {
useAnimator = false;
} else if(args[i].equals("-pbuffer")) {
@@ -303,14 +396,16 @@ public class TestGearsES2GLJPanelsAWT extends UITestCase {
}
}
System.err.println("swapInterval "+swapInterval);
- System.err.println("opaque "+opaque);
- System.err.println("alpha "+alpha);
+ System.err.println("opaque gl "+glOpaque+", java/gljpanel "+jOpaque);
+ System.err.println("alpha "+glAlpha);
+ System.err.println("jZOrder "+jZOrder);
System.err.println("demos "+demoCount);
System.err.println("useMSAA "+useMSAA);
System.err.println("useAnimator "+useAnimator);
System.err.println("shallUsePBuffer "+shallUsePBuffer);
System.err.println("shallUseBitmap "+shallUseBitmap);
System.err.println("manualTest "+manualTest);
+ System.err.println("useSingleBuffer "+useSingleBuffer);
org.junit.runner.JUnitCore.main(TestGearsES2GLJPanelsAWT.class.getName());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java
index 71a63a701..bf8323e88 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java
@@ -21,6 +21,7 @@ import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
import com.jogamp.opengl.util.GLReadBufferUtil;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureIO;
@@ -49,7 +50,7 @@ public class TestJPEGImage01NEWT extends UITestCase {
image.getWidth(),
image.getHeight(),
0,
- new TextureData.PixelAttributes(image.getGLFormat(), image.getGLType()),
+ new GLPixelAttributes(image.getGLFormat(), image.getGLType()),
false /* mipmap */,
false /* compressed */,
false /* must flip-vert */,
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java
index 681667362..1e27f5dae 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTBenchmarkNewtAWT.java
@@ -36,6 +36,7 @@ import javax.imageio.ImageIO;
import javax.media.opengl.GL;
import javax.media.opengl.GLProfile;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.awt.AWTTextureData;
import com.jogamp.opengl.util.texture.spi.JPEGImage;
@@ -68,7 +69,7 @@ public class TestJPEGJoglAWTBenchmarkNewtAWT extends UITestCase {
image.getWidth(),
image.getHeight(),
0,
- new TextureData.PixelAttributes(image.getGLFormat(), image.getGLType()),
+ new GLPixelAttributes(image.getGLFormat(), image.getGLType()),
false /* mipmap */,
false /* compressed */,
false /* must flip-vert */,
@@ -96,7 +97,7 @@ public class TestJPEGJoglAWTBenchmarkNewtAWT extends UITestCase {
image.getWidth(),
image.getHeight(),
0,
- new TextureData.PixelAttributes(image.getGLFormat(), image.getGLType()),
+ new GLPixelAttributes(image.getGLFormat(), image.getGLType()),
false /* mipmap */,
false /* compressed */,
false /* must flip-vert */,
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java
index 5d2969815..0df275652 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java
@@ -49,6 +49,7 @@ import com.jogamp.opengl.util.texture.TextureIO;
import com.jogamp.opengl.util.texture.awt.AWTTextureData;
import com.jogamp.opengl.util.texture.spi.JPEGImage;
import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
import com.jogamp.opengl.util.GLReadBufferUtil;
import java.awt.image.BufferedImage;
@@ -112,7 +113,7 @@ public class TestJPEGJoglAWTCompareNewtAWT extends UITestCase {
image.getWidth(),
image.getHeight(),
0,
- new TextureData.PixelAttributes(image.getGLFormat(), image.getGLType()),
+ new GLPixelAttributes(image.getGLFormat(), image.getGLType()),
false /* mipmap */,
false /* compressed */,
false /* must flip-vert */,
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 5b2876744..c33384611 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
@@ -122,7 +122,7 @@ public class TestTexture01AWT extends UITestCase {
@Test
public void test1() throws InterruptedException {
- final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(false);
+ final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false);
final Frame frame0 = new Frame("GL -> AWT");
final Canvas canvas = new Canvas();
frame0.add(canvas);
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
index bdc8934fc..5948f5971 100644
--- 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
@@ -77,7 +77,7 @@ public class TestTexture02AWT extends UITestCase {
@Test
public void test1() throws InterruptedException {
- final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(false);
+ final AWTGLReadBufferUtil awtGLReadBufferUtil = new AWTGLReadBufferUtil(caps.getGLProfile(), false);
final Frame frame0 = new Frame("GL -> AWT");
final ImageIcon imageIcon = new ImageIcon();
final JLabel imageLabel = new JLabel(imageIcon);
diff --git a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java
index d17914939..d6e9743e0 100644
--- a/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java
+++ b/src/test/com/jogamp/opengl/test/junit/util/MiscUtils.java
@@ -33,6 +33,15 @@ import java.lang.reflect.*;
import java.nio.FloatBuffer;
public class MiscUtils {
+ public static boolean atob(String str, boolean def) {
+ try {
+ return Boolean.parseBoolean(str);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ return def;
+ }
+
public static int atoi(String str, int def) {
try {
return Integer.parseInt(str);