aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-06-09 00:42:41 +0200
committerSven Gothel <[email protected]>2011-06-09 00:42:41 +0200
commit423f5bf7f518433edcbf64accaf2cf5252cb4a63 (patch)
tree15b4278c893adc5f423a22b85b2b97c6b6cda010 /src
parentf6bd208d8ef15769e13cb959e614349fd1e7cae1 (diff)
GLBuffers fix ; GL imageSizeInBytes fix / unit tests.
- Moved implementation of prev GL imageSizeInBytes(..) -> GLBuffers.sizeof() for all GL profiles - GLBuffers.*: Added missing formats and types (GL2.1, GL3.3 and GL4.1) - GLBuffers.sizeof(): Fail fast if format/type is unhandled, or alignment invalid - Added unit test for GLBuffers.sizeof()
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java412
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java319
2 files changed, 710 insertions, 21 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
index efe3a7675..f2e742cda 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java
@@ -42,60 +42,145 @@ import com.jogamp.common.nio.Buffers;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLException;
import java.nio.*;
/**
* Utility routines for dealing with direct buffers.
* @author Kenneth Russel
+ * @author Sven Gothel
* @author Michael Bien
*/
public class GLBuffers extends Buffers {
+ /**
+ * @param glType shall be one of
+ * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
+ * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
+ * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
+ * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
+ * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
+ * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV (25)
+ * @return -1 if glType is unhandled, otherwise the actual value > 0
+ */
public static final int sizeOfGLType(int glType) {
- switch (glType) {
- case GL.GL_UNSIGNED_BYTE:
- return SIZEOF_BYTE;
+ switch (glType) { // 25
case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_BYTE:
+ case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
+ case GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV:
return SIZEOF_BYTE;
- case GL.GL_UNSIGNED_SHORT:
- return SIZEOF_SHORT;
+
case GL.GL_SHORT:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_UNSIGNED_SHORT_5_6_5:
+ case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
+ case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
return SIZEOF_SHORT;
- case GL.GL_FLOAT:
- return SIZEOF_FLOAT;
+
case GL.GL_FIXED:
- return SIZEOF_INT;
case GL2ES2.GL_INT:
+ case GL.GL_UNSIGNED_INT:
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:
+ case GL2GL3.GL_UNSIGNED_INT_10_10_10_2:
+ case GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL2GL3.GL_UNSIGNED_INT_24_8:
+ case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV:
return SIZEOF_INT;
- case GL2ES2.GL_UNSIGNED_INT:
- return SIZEOF_INT;
+
+ case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ return SIZEOF_LONG;
+
+ case GL.GL_FLOAT:
+ return SIZEOF_FLOAT;
+
case GL2.GL_DOUBLE:
return SIZEOF_DOUBLE;
}
return -1;
}
-
+
+ /**
+ * @param glType shall be one of
+ * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
+ * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
+ * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
+ * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
+ * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
+ * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV (25)
+ * @return null if glType is unhandled, otherwise the new Buffer object
+ */
public static final Buffer newDirectGLBuffer(int glType, int numElements) {
switch (glType) {
- case GL.GL_UNSIGNED_BYTE:
case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_BYTE:
+ case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
+ case GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV:
return newDirectByteBuffer(numElements);
- case GL.GL_UNSIGNED_SHORT:
+
case GL.GL_SHORT:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_UNSIGNED_SHORT_5_6_5:
+ case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
+ case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
return newDirectShortBuffer(numElements);
- case GL.GL_FLOAT:
- return newDirectFloatBuffer(numElements);
+
case GL.GL_FIXED:
case GL2ES2.GL_INT:
- case GL2ES2.GL_UNSIGNED_INT:
+ case GL.GL_UNSIGNED_INT:
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:
+ case GL2GL3.GL_UNSIGNED_INT_10_10_10_2:
+ case GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL2GL3.GL_UNSIGNED_INT_24_8:
+ case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV:
return newDirectIntBuffer(numElements);
+
+ case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ return newDirectLongBuffer(numElements);
+
+ case GL.GL_FLOAT:
+ return newDirectFloatBuffer(numElements);
+
case GL2.GL_DOUBLE:
return newDirectDoubleBuffer(numElements);
}
return null;
}
+ /**
+ * @param glType shall be one of
+ * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
+ * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
+ * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
+ * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
+ * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
+ * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV (25)
+ * @return null if glType is unhandled or parent is null or bufLen is 0, otherwise the new Buffer object
+ */
public static final Buffer sliceGLBuffer(ByteBuffer parent, int bytePos, int byteLen, int glType) {
if (parent == null || byteLen == 0) {
return null;
@@ -104,24 +189,309 @@ public class GLBuffers extends Buffers {
parent.limit(bytePos + byteLen);
switch (glType) {
- case GL.GL_UNSIGNED_BYTE:
case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_BYTE:
+ case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
+ case GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV:
return parent.slice();
- case GL.GL_UNSIGNED_SHORT:
+
case GL.GL_SHORT:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_UNSIGNED_SHORT_5_6_5:
+ case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
+ case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
return parent.asShortBuffer();
- case GL.GL_FLOAT:
- return parent.asFloatBuffer();
+
case GL.GL_FIXED:
- case GL2ES2.GL_INT:
+ case GL2GL3.GL_INT:
case GL2ES2.GL_UNSIGNED_INT:
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:
+ case GL2GL3.GL_UNSIGNED_INT_10_10_10_2:
+ case GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL2GL3.GL_UNSIGNED_INT_24_8:
+ case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV:
return parent.asIntBuffer();
+
+ case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ return parent.asLongBuffer();
+
+ case GL.GL_FLOAT:
+ return parent.asFloatBuffer();
+
case GL2.GL_DOUBLE:
return parent.asDoubleBuffer();
}
return null;
}
+ private static final int glGetInteger(GL gl, int pname, int[] tmp) {
+ gl.glGetIntegerv(pname, tmp, 0);
+ return tmp[0];
+ }
+
+ /**
+ * Returns the number of bytes required to read/write a memory buffer via OpenGL
+ * using the current GL pixel storage state and the given parameters.
+ *
+ * <p>This method is security critical, hence it throws an exception (fail-fast)
+ * in case of an invalid alignment. In case we forgot to handle
+ * proper values, please contact the maintainer.</p>
+ *
+ * @param gl the current GL object
+ *
+ * @param tmp a pass through integer array of size >= 1 used to store temp data (performance)
+ *
+ * @param bytesPerElement bytes per element
+ * @param width in pixels
+ * @param height in pixels
+ * @param depth in pixels
+ * @param pack true for read mode GPU -> CPU (pack), otherwise false for write mode CPU -> GPU (unpack)
+ * @return required minimum size of the buffer in bytes
+ * @throws GLException if alignment is invalid. Please contact the maintainer if this is our bug.
+ */
+ public static final int sizeof(GL gl, int tmp[],
+ int bytesPerElement, int width, int height, int depth,
+ boolean pack) {
+ int rowLength = 0;
+ int skipRows = 0;
+ int skipPixels = 0;
+ int alignment = 1;
+ int imageHeight = 0;
+ int skipImages = 0;
+
+ if (pack) {
+ alignment = glGetInteger(gl, GL.GL_PACK_ALIGNMENT, tmp);
+ if(gl.isGL2GL3()) {
+ rowLength = glGetInteger(gl, GL2GL3.GL_PACK_ROW_LENGTH, tmp);
+ skipRows = glGetInteger(gl, GL2GL3.GL_PACK_SKIP_ROWS, tmp);
+ skipPixels = glGetInteger(gl, GL2GL3.GL_PACK_SKIP_PIXELS, tmp);
+ if (depth > 1) {
+ imageHeight = glGetInteger(gl, GL2GL3.GL_PACK_IMAGE_HEIGHT, tmp);
+ skipImages = glGetInteger(gl, GL2GL3.GL_PACK_SKIP_IMAGES, tmp);
+ }
+ }
+ } else {
+ alignment = glGetInteger(gl, GL.GL_UNPACK_ALIGNMENT, tmp);
+ if(gl.isGL2GL3 ()) {
+ rowLength = glGetInteger(gl, GL2GL3.GL_UNPACK_ROW_LENGTH, tmp);
+ skipRows = glGetInteger(gl, GL2GL3.GL_UNPACK_SKIP_ROWS, tmp);
+ skipPixels = glGetInteger(gl, GL2GL3.GL_UNPACK_SKIP_PIXELS, tmp);
+ if (depth > 1) {
+ imageHeight = glGetInteger(gl, GL2GL3.GL_UNPACK_IMAGE_HEIGHT, tmp);
+ skipImages = glGetInteger(gl, GL2GL3.GL_UNPACK_SKIP_IMAGES, tmp);
+ }
+ }
+ }
+
+ // Try to deal somewhat correctly with potentially invalid values
+ width = Math.max(0, width );
+ height = Math.max(1, height); // min 1D
+ depth = Math.max(1, depth ); // min 1 * imageSize
+ skipRows = Math.max(0, skipRows);
+ skipPixels = Math.max(0, skipPixels);
+ alignment = Math.max(1, alignment);
+ skipImages = Math.max(0, skipImages);
+
+ imageHeight = ( imageHeight > 0 ) ? imageHeight : height;
+ rowLength = ( rowLength > 0 ) ? rowLength : width;
+
+ int rowLengthInBytes = rowLength * bytesPerElement;
+ int skipBytes = skipPixels * bytesPerElement;
+
+ switch(alignment) {
+ case 1:
+ break;
+ case 2:
+ case 4:
+ case 8: {
+ // x % 2n == x & (2n - 1)
+ int remainder = rowLengthInBytes & ( alignment - 1 );
+ if (remainder > 0) {
+ rowLengthInBytes += alignment - remainder;
+ }
+ remainder = skipBytes & ( alignment - 1 );
+ if (remainder > 0) {
+ skipBytes += alignment - remainder;
+ }
+ }
+ break;
+ default:
+ throw new GLException("Invalid alignment "+alignment+", must be 2**n (1,2,4,8). Pls notify the maintainer in case this is our bug.");
+ }
+
+ /**
+ * skipImages, depth, skipPixels and skipRows are static offsets.
+ *
+ * skipImages and depth are in multiples of image size.
+ *
+ * skipBytes and rowLengthInBytes are aligned
+ *
+ * rowLengthInBytes is the aligned byte offset
+ * from line n to line n+1 at the same x-axis position.
+ */
+ return
+ skipBytes + // aligned skipPixels * bpp
+ ( skipImages + depth - 1 ) * imageHeight * rowLengthInBytes + // aligned whole images
+ ( skipRows + height - 1 ) * rowLengthInBytes + // aligned lines
+ width * bytesPerElement; // last line
+ }
+
+ /**
+ * Returns the number of bytes required to read/write a memory buffer via OpenGL
+ * using the current GL pixel storage state and the given parameters.
+ *
+ * <p>This method is security critical, hence it throws an exception (fail-fast)
+ * in case either the format, type or alignment is unhandled. In case we forgot to handle
+ * proper values, please contact the maintainer.</p>
+ *
+ * @param gl the current GL object
+ *
+ * @param tmp a pass through integer array of size >= 1 used to store temp data (performance)
+ *
+ * @param format must be one of
+ * GL_COLOR_INDEX, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL,
+ * GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_LUMINANCE,
+ * GL_RG, GL_LUMINANCE_ALPHA,
+ * GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_ABGR_EXT,
+ * GL_RED_INTEGER, GL_GREEN_INTEGER, GL_BLUE_INTEGER,
+ * GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER,
+ * GL_RGBA_INTEGER, GL_BGRA_INTEGER (24)
+ *
+ * @param type must be one of
+ * GL_BITMAP,
+ * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT,
+ * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV,
+ * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV,
+ * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV,
+ * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV,
+ * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV
+ * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV,
+ * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV (26)
+ *
+ * @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
+ * @return required minimum size of the buffer in bytes
+ * @throws GLException if format, type or alignment is not handled. Please contact the maintainer if this is our bug.
+ */
+ public static final int sizeof(GL gl, int tmp[],
+ int format, int type, int width, int height, int depth,
+ boolean pack) throws GLException {
+ int elements = 0;
+ int esize = 0;
+
+ if (width < 0) return 0;
+ if (height < 0) return 0;
+ if (depth < 0) return 0;
+
+ switch (format) /* 24 */ {
+ case GL2.GL_COLOR_INDEX:
+ case GL2GL3.GL_STENCIL_INDEX:
+ case GL2GL3.GL_DEPTH_COMPONENT:
+ case GL2GL3.GL_DEPTH_STENCIL:
+ case GL2GL3.GL_RED:
+ case GL2GL3.GL_RED_INTEGER:
+ case GL2GL3.GL_GREEN:
+ case GL2GL3.GL_GREEN_INTEGER:
+ case GL2GL3.GL_BLUE:
+ case GL2GL3.GL_BLUE_INTEGER:
+ case GL.GL_ALPHA:
+ case GL.GL_LUMINANCE:
+ elements = 1;
+ break;
+ case GL.GL_LUMINANCE_ALPHA:
+ case GL2GL3.GL_RG:
+ case GL2GL3.GL_RG_INTEGER:
+ elements = 2;
+ break;
+ case GL.GL_RGB:
+ case GL2GL3.GL_RGB_INTEGER:
+ case GL2GL3.GL_BGR:
+ case GL2GL3.GL_BGR_INTEGER:
+ elements = 3;
+ break;
+ case GL.GL_RGBA:
+ case GL2GL3.GL_RGBA_INTEGER:
+ case GL2GL3.GL_BGRA:
+ case GL2GL3.GL_BGRA_INTEGER:
+ case GL2.GL_ABGR_EXT:
+ elements = 4;
+ break;
+ /* FIXME ??
+ case GL.GL_HILO_NV:
+ elements = 2;
+ break; */
+ default:
+ throw new GLException("format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug.");
+ }
+
+ switch (type) /* 26 */ {
+ case GL2.GL_BITMAP:
+ if (GL2.GL_COLOR_INDEX == format || GL2GL3.GL_STENCIL_INDEX == format) {
+ return (depth * (height * ((width+7)/8)));
+ }
+ case GL.GL_BYTE:
+ case GL.GL_UNSIGNED_BYTE:
+ esize = 1;
+ break;
+ case GL.GL_SHORT:
+ case GL.GL_UNSIGNED_SHORT:
+ case GL.GL_HALF_FLOAT:
+ esize = 2;
+ break;
+ case GL2ES2.GL_INT:
+ case GL.GL_UNSIGNED_INT:
+ case GL.GL_FLOAT:
+ esize = 4;
+ break;
+ case GL2GL3.GL_DOUBLE:
+ esize = 8;
+ break;
+
+ case GL2GL3.GL_UNSIGNED_BYTE_3_3_2:
+ case GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV:
+ esize = 1;
+ elements = 1;
+ break;
+ case GL.GL_UNSIGNED_SHORT_5_6_5:
+ case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
+ case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ case GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ esize = 2;
+ elements = 1;
+ break;
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:
+ case GL2GL3.GL_UNSIGNED_INT_10_10_10_2:
+ case GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL2GL3.GL_UNSIGNED_INT_24_8:
+ case GL2GL3.GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL2GL3.GL_UNSIGNED_INT_5_9_9_9_REV:
+ esize = 4;
+ elements = 1;
+ break;
+ case GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ esize = 8;
+ elements = 1;
+ break;
+
+ default:
+ throw new GLException("type 0x"+Integer.toHexString(type)+"/"+"format 0x"+Integer.toHexString(format)+" not supported [yet], pls notify the maintainer in case this is our bug.");
+ }
+
+ return sizeof(gl, tmp, elements * esize, width, height, depth, pack);
+ }
+
//----------------------------------------------------------------------
// Conversion routines
//
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java
new file mode 100644
index 000000000..a328a2bac
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGPUMemSec01NEWT.java
@@ -0,0 +1,319 @@
+/**
+ * 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.acore;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.GLPixelStorageModes;
+import com.jogamp.opengl.test.junit.util.NEWTGLContext;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestGPUMemSec01NEWT extends UITestCase {
+ static String hexString(int i) {
+ return "0x"+Integer.toHexString(i);
+ }
+ static String exceptionMsg(String pre, int format, int type, int components, int width, int height, int rl1, int rl4, int rl8) {
+ return pre +
+ ": fmt "+hexString(format)+", type "+hexString(type)+", comps "+components+
+ ", "+width+"x"+height+
+ ", rowlenA1 "+rl1+", rowlenA4 "+rl4+", rowlenA8 "+rl8;
+ }
+
+ static NEWTGLContext.WindowContext createCurrentGLOffscreenWindow(int width, int height) throws GLException, InterruptedException {
+ final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOffscreenWindow(GLProfile.getGL2ES2(), width, height, true);
+ final GL _gl = winctx.context.getGL();
+ Assert.assertTrue(_gl.isGL2GL3());
+ final GL2GL3 gl = _gl.getGL2GL3();
+
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ // misc GL setup
+ gl.glClearColor(1, 1, 1, 1);
+ gl.glEnable(GL2ES2.GL_DEPTH_TEST);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ gl.glViewport(0, 0, width, height);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+
+ return winctx;
+ }
+
+ static int readPixelsCheck(GL gl, int format, int type, int components, int width, int height) throws InterruptedException {
+ int expectedExceptions = 0;
+
+ final int rowlenA1 = width * components;
+
+ final int rowlenA4 = ( ( width * components + 3 ) / 4 ) * 4 ;
+ Assert.assertTrue(rowlenA4 % 4 == 0);
+
+ final int rowlenA8 = ( ( width * components + 7 ) / 8 ) * 8 ;
+ Assert.assertTrue(rowlenA8 % 8 == 0);
+
+ GLPixelStorageModes psm = new GLPixelStorageModes();
+ psm.setPackAlignment(gl, 1);
+
+ Exception ee = null;
+
+ // ok size !
+ try {
+ ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1);
+ gl.glReadPixels(0, 0, width, height, format, type, bb);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ } catch(IndexOutOfBoundsException e) {
+ ee = e;
+ }
+ Assert.assertNull(
+ exceptionMsg("Unexpected IndexOutOfBoundsException (size ok, alignment 1)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ ee = null;
+
+
+ // too small -10 !
+ try {
+ ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1-10);
+ gl.glReadPixels(0, 0, width, height, format, type, bb);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ } catch(IndexOutOfBoundsException e) {
+ ee = e;
+ System.err.println(
+ exceptionMsg("OK Expected IndexOutOfBoundsException (size-10 bytes)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8)+
+ ": "+ee.getMessage());
+ expectedExceptions++;
+ }
+ Assert.assertNotNull(
+ exceptionMsg("Expected IndexOutOfBoundsException (size-10 bytes)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ ee = null;
+
+ // too small size/4 !
+ try {
+ ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1/4);
+ gl.glReadPixels(0, 0, width, height, format, type, bb);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ } catch(IndexOutOfBoundsException e) {
+ ee = e;
+ System.err.println(
+ exceptionMsg("OK Expected IndexOutOfBoundsException (size/4 bytes)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8)+
+ ": "+ee.getMessage());
+ expectedExceptions++;
+ }
+ Assert.assertNotNull(
+ exceptionMsg("Expected IndexOutOfBoundsException (size/4 bytes)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ ee = null;
+
+ //
+ // Alignment test
+ //
+ psm.setPackAlignment(gl, 4);
+
+ // ok size !
+ try {
+ ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA4);
+ gl.glReadPixels(0, 0, width, height, format, type, bb);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ } catch(IndexOutOfBoundsException e) {
+ ee = e;
+ }
+ Assert.assertNull(
+ exceptionMsg("Unexpected IndexOutOfBoundsException (size ok, alignment 4)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ ee = null;
+
+ // too small if rowlenA1%4 > 0
+ try {
+ ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1);
+ gl.glReadPixels(0, 0, width, height, format, type, bb);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ } catch(IndexOutOfBoundsException e) {
+ ee = e;
+ if(rowlenA1%4>0) {
+ System.err.println(
+ exceptionMsg("OK Expected IndexOutOfBoundsException (alignment 4)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8)+
+ ": "+ee.getMessage());
+ expectedExceptions++;
+ }
+ }
+ if(rowlenA1%4>0) {
+ Assert.assertNotNull(
+ exceptionMsg("Expected IndexOutOfBoundsException (alignment 4)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ } else {
+ Assert.assertNull(
+ exceptionMsg("Unexpected IndexOutOfBoundsException (alignment 4)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ }
+ ee = null;
+
+ psm.setPackAlignment(gl, 8);
+
+ // ok size !
+ try {
+ ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA8);
+ gl.glReadPixels(0, 0, width, height, format, type, bb);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ } catch(IndexOutOfBoundsException e) {
+ ee = e;
+ }
+ Assert.assertNull(
+ exceptionMsg("Unexpected IndexOutOfBoundsException (size ok, alignment 8)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ ee = null;
+
+ // too small if rowlenA1%8 > 0
+ try {
+ ByteBuffer bb = Buffers.newDirectByteBuffer(height*rowlenA1);
+ gl.glReadPixels(0, 0, width, height, format, type, bb);
+ Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
+ } catch(IndexOutOfBoundsException e) {
+ ee = e;
+ if(rowlenA1%8>0) {
+ System.err.println(
+ exceptionMsg("OK Expected IndexOutOfBoundsException (alignment 8)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8)+
+ ": "+ee.getMessage());
+ expectedExceptions++;
+ }
+ }
+ if(rowlenA1%8>0) {
+ Assert.assertNotNull(
+ exceptionMsg("Expected IndexOutOfBoundsException (alignment 8)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ } else {
+ Assert.assertNull(
+ exceptionMsg("Unexpected IndexOutOfBoundsException (alignment 8)",
+ format, type, components, width, height, rowlenA1, rowlenA4, rowlenA8), ee);
+ }
+ ee = null;
+
+ psm.restore(gl);
+
+ return expectedExceptions;
+ }
+
+ @Test
+ public void testReadPixels_640x480xREDxUB() throws InterruptedException {
+ final int width = 640;
+ final int height= 480;
+
+ // preset ..
+ final NEWTGLContext.WindowContext winctx = createCurrentGLOffscreenWindow(width, height);
+ final GLDrawable drawable = winctx.context.getGLDrawable();
+ final GL2GL3 gl = winctx.context.getGL().getGL2GL3();
+
+ // 2 x too small - 0 x alignment
+ Assert.assertEquals(2, readPixelsCheck(gl, GL2GL3.GL_RED, GL.GL_UNSIGNED_BYTE, 1, width, height));
+
+ drawable.swapBuffers();
+ Thread.sleep(50);
+
+ NEWTGLContext.destroyWindow(winctx);
+ }
+
+ @Test
+ public void testReadPixels_640x480xRGBxUB() throws InterruptedException {
+ final int width = 640;
+ final int height= 480;
+
+ // preset ..
+ final NEWTGLContext.WindowContext winctx = createCurrentGLOffscreenWindow(width, height);
+ final GLDrawable drawable = winctx.context.getGLDrawable();
+ final GL2GL3 gl = winctx.context.getGL().getGL2GL3();
+
+ // 2 x too small - 0 x alignment
+ Assert.assertEquals(2, readPixelsCheck(gl, GL2GL3.GL_RGB, GL.GL_UNSIGNED_BYTE, 3, width, height));
+
+ drawable.swapBuffers();
+ Thread.sleep(50);
+
+ NEWTGLContext.destroyWindow(winctx);
+ }
+
+ @Test
+ public void testReadPixels_102x100xREDxUB() throws InterruptedException {
+ int wwidth = 640;
+ int wheight= 480;
+ int rwidth = 102;
+ int rheight= 100;
+
+ // preset ..
+ final NEWTGLContext.WindowContext winctx = createCurrentGLOffscreenWindow(wwidth, wheight);
+ final GLDrawable drawable = winctx.context.getGLDrawable();
+ final GL2GL3 gl = winctx.context.getGL().getGL2GL3();
+
+ // 2 x too small - 2 x alignment
+ Assert.assertEquals(4, readPixelsCheck(gl, GL2GL3.GL_RED, GL.GL_UNSIGNED_BYTE, 1, rwidth, rheight));
+
+ drawable.swapBuffers();
+ Thread.sleep(50);
+
+ NEWTGLContext.destroyWindow(winctx);
+ }
+
+ @Test
+ public void testReadPixels_102x100xRGBxUB() throws InterruptedException {
+ final int wwidth = 640;
+ final int wheight= 480;
+ final int rwidth = 102;
+ final int rheight= 100;
+
+ // preset ..
+ final NEWTGLContext.WindowContext winctx = createCurrentGLOffscreenWindow(wwidth, wheight);
+ final GLDrawable drawable = winctx.context.getGLDrawable();
+ final GL2GL3 gl = winctx.context.getGL().getGL2GL3();
+
+ // 2 x too small - 2 x alignment
+ Assert.assertEquals(4, readPixelsCheck(gl, GL2GL3.GL_RGB, GL.GL_UNSIGNED_BYTE, 3, rwidth, rheight));
+
+ drawable.swapBuffers();
+ Thread.sleep(50);
+
+ NEWTGLContext.destroyWindow(winctx);
+ }
+
+ public static void main(String args[]) throws IOException {
+ String tstname = TestGPUMemSec01NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+}
+