aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xmake/scripts/tests-x32-dbg.bat7
-rwxr-xr-xmake/scripts/tests-x64-dbg.bat5
-rw-r--r--make/scripts/tests.sh20
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java489
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java26
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java12
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java6
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java6
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java195
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java8
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java48
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java6
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java93
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java628
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java519
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java8
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java29
-rw-r--r--src/newt/classes/jogamp/newt/DisplayImpl.java2
-rw-r--r--src/newt/classes/jogamp/newt/PointerIconImpl.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java28
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelsAWT.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java6
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java7
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java2
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java7
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java597
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java11
29 files changed, 2140 insertions, 641 deletions
diff --git a/make/scripts/tests-x32-dbg.bat b/make/scripts/tests-x32-dbg.bat
index 91d1d6fbc..c89eee449 100755
--- a/make/scripts/tests-x32-dbg.bat
+++ b/make/scripts/tests-x32-dbg.bat
@@ -1,4 +1,9 @@
+set TEMP=\\jordan\data\Incoming\windows\temp
+set TMP=\\jordan\data\Incoming\windows\temp
+REM set TEMP=C:\Documents and Settings\jogamp\temp
+REM set TMP=C:\Documents and Settings\jogamp\temp
+
set BLD_SUB=build-win32
set J2RE_HOME=c:\jre1.7.0_67_x32
set JAVA_HOME=c:\jdk1.7.0_67_x32
@@ -31,6 +36,8 @@ REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.debug.GLContext"
REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.windows.cpu_affinity_mode=0"
REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
+REM set D_ARGS="-Djogamp.debug.IOUtil"
+set D_ARGS="-Djogl.debug.GLSLCode"
REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true"
REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true"
REM set D_ARGS="-Djogamp.debug.JNILibLoader=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLProfile=true"
diff --git a/make/scripts/tests-x64-dbg.bat b/make/scripts/tests-x64-dbg.bat
index 1f0b88139..a46e578ca 100755
--- a/make/scripts/tests-x64-dbg.bat
+++ b/make/scripts/tests-x64-dbg.bat
@@ -1,4 +1,9 @@
+set TEMP=\\jordan\data\Incoming\windows\temp
+set TMP=\\jordan\data\Incoming\windows\temp
+REM set TEMP=C:\Documents and Settings\jogamp\temp
+REM set TMP=C:\Documents and Settings\jogamp\temp
+
set BLD_SUB=build-win64
set J2RE_HOME=c:\jre1.7.0_67_x64
set JAVA_HOME=c:\jdk1.7.0_67_x64
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 00bd8571e..dc6802bb4 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -116,6 +116,7 @@ function jrun() {
#D_ARGS="-Dnativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG"
#D_ARGS="-Dnativewindow.debug.X11Util.ATI_HAS_NO_MULTITHREADING_BUG"
+ #D_ARGS="-Djogl.disable.opengldesktop"
#D_ARGS="-Djogl.disable.opengles"
#D_ARGS="-Djogl.disable.openglcore"
#D_ARGS="-Djogl.disable.openglarbcontext"
@@ -150,6 +151,12 @@ function jrun() {
#D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration"
#D_ARGS="-Dnativewindow.debug.GraphicsConfiguration"
#D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable"
+ #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Djogl.debug.GLProfile -Djogamp.common.utils.locks.Lock.timeout=600000 -Djogamp.debug.Lock"
+ #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.ProxySurface -Djogl.debug.GLProfile -Djogl.disable.opengldesktop"
+ #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.ProxySurface -Djogl.debug.GLProfile"
+ #D_ARGS="-Djogl.disable.surfacelesscontext -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Djogl.debug.GLJPanel -Djogl.debug.DebugGL"
+ #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLJPanel -Djogl.debug.DebugGL"
+ #D_ARGS="-Djogl.debug.GLJPanel"
#D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing"
#D_ARGS="-Djogl.debug.GLDrawable -Dnativewindow.debug.X11Util -Dnativewindow.debug.NativeWindow -Dnewt.debug.Display -Dnewt.debug.Screen -Dnewt.debug.Window"
#D_ARGS="-Djogl.debug.Animator"
@@ -398,8 +405,8 @@ function testawtswt() {
# HiDPI
#
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
+testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 $*
#testnoawt com.jogamp.opengl.test.junit.graph.demos.GPUUISceneNewtDemo $*
@@ -589,7 +596,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.newt.TestWindows01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $*
-testnoawt com.jogamp.opengl.test.junit.newt.TestWindowAndPointerIconNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.newt.TestWindowAndPointerIconNEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindows02NEWTAnimated $*
#testnoawt com.jogamp.opengl.test.junit.newt.TestGLWindows03NEWTAnimResize $*
@@ -785,13 +792,14 @@ testnoawt com.jogamp.opengl.test.junit.newt.TestWindowAndPointerIconNEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestTexture02AWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGImage01NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTCompareNewtAWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTBenchmarkNewtAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTCompareNewtAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTBenchmarkNewtAWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGTextureFromFileNEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGPixelRect00NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGPixelRect01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPixelFormat00NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPixelFormatUtil00NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPixelFormatUtil01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGPixelRect00NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGPixelRect01NEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGTextureFromFileAWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGTextureFromFileNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestTGATextureFromFileNEWT $*
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
index a09321d75..00bbd6ce7 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
@@ -58,41 +58,100 @@ public class GLPixelBuffer {
/** Allow {@link GL2ES3#GL_PACK_ROW_LENGTH}, or {@link GL2ES2#GL_UNPACK_ROW_LENGTH}. */
boolean getAllowRowStride();
- /** Called first to determine {@link GLPixelAttributes}. */
- GLPixelAttributes getAttributes(GL gl, int componentCount);
+ /**
+ * Returns RGB[A] {@link GLPixelAttributes} matching {@link GL}, {@code componentCount} and {@code pack}.
+ *
+ * @param gl the corresponding current {@link GL} context object
+ * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
+ */
+ GLPixelAttributes getAttributes(GL gl, int componentCount, boolean pack);
+
+ /**
+ * Returns the host {@link PixelFormat.Composition} matching {@link GL} and {@code componentCount}
+ * if required by implementation, otherwise {@code null}.
+ *
+ * @param glp the corresponding current {@link GL} context object
+ * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
+ */
+ PixelFormat.Composition getHostPixelComp(final GLProfile glp, final 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 gl the corresponding current {@link GL} context object
+ * @param hostPixComp host {@link PixelFormat pixel format}, i.e. of the source or sink depending on {@code pack},
+ * e.g. fetched via {@link #getHostPixelComp(GLProfile, int)}.
+ * If {@code null}, {@code pixelAttributes} instance maybe used or an exception is thrown,
+ * depending on implementation semantics.
+ * @param pixelAttributes the desired {@link GLPixelAttributes}, e.g. fetched via {@link #getAttributes(GL, int, boolean)}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
* @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.
+ * @see #getHostPixelComp(GLProfile, int)
+ * @see #getAttributes(GL, int, boolean)
*/
- GLPixelBuffer allocate(GL gl, GLPixelAttributes pixelAttributes, int width, int height, int depth, boolean pack, int minByteSize);
+ GLPixelBuffer allocate(GL gl, PixelFormat.Composition hostPixComp, GLPixelAttributes pixelAttributes,
+ boolean pack, int width, int height, int depth, int minByteSize);
}
/** Single {@link GLPixelBuffer} provider. */
public static interface SingletonGLPixelBufferProvider extends GLPixelBufferProvider {
- /** Return the last {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated} {@link GLPixelBuffer} w/ {@link GLPixelAttributes#componentCount}. */
- GLPixelBuffer getSingleBuffer(GLPixelAttributes pixelAttributes);
/**
- * Initializes the single {@link GLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+ * {@inheritDoc}
+ * <p>
+ * Being called to gather the initial {@link GLPixelBuffer},
+ * or a new replacement {@link GLPixelBuffer} if {@link GLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
+ * </p>
+ */
+ @Override
+ GLPixelBuffer allocate(GL gl, PixelFormat.Composition hostPixComp, GLPixelAttributes pixelAttributes,
+ boolean pack, int width, int height, int depth, int minByteSize);
+
+ /**
+ * Return the last {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated} {@link GLPixelBuffer}
+ * matching the given parameter.
+ * <p>
+ * May return {@code null} if none has been allocated yet.
+ * </p>
+ * <p>
+ * Returned {@link GLPixelBuffer} may be {@link GLPixelBuffer#isValid() invalid}.
+ * </p>
+ * @param hostPixComp host {@link PixelFormat pixel format}, i.e. of the source or sink depending on {@code pack},
+ * e.g. fetched via {@link #getHostPixelComp(GLProfile, int)}.
+ * If {@code null}, {@code pixelAttributes} instance maybe used or an exception is thrown,
+ * depending on implementation semantics.
+ * @param pixelAttributes the desired {@link GLPixelAttributes}, e.g. fetched via {@link #getAttributes(GL, int, boolean)}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
+ */
+ GLPixelBuffer getSingleBuffer(PixelFormat.Composition hostPixelComp, GLPixelAttributes pixelAttributes, boolean pack);
+ /**
+ * Initializes the single {@link GLPixelBuffer} w/ a given size,
+ * if not yet {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated}.
+ *
+ * @param glp
+ * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
+ * @param width
+ * @param height
+ * @param depth
* @return the newly initialized single {@link GLPixelBuffer}, or null if already allocated.
*/
- GLPixelBuffer initSingleton(int componentCount, int width, int height, int depth, boolean pack);
+ GLPixelBuffer initSingleton(GLProfile glp, int componentCount, boolean pack, int width, int height, int depth);
+
+ /** Dispose all resources.*/
+ void dispose();
}
public static class DefaultGLPixelBufferProvider implements GLPixelBufferProvider {
@@ -110,36 +169,24 @@ public class GLPixelBuffer {
public boolean getAllowRowStride() { return allowRowStride; }
@Override
- public GLPixelAttributes getAttributes(final GL gl, final int componentCount) {
- final GLContext ctx = gl.getContext();
- final int dFormat, dType;
-
- if( 1 == componentCount ) {
- if( gl.isGL3ES3() ) {
- // RED is supported on ES3 and >= GL3 [core]; ALPHA is deprecated on core
- dFormat = GL2ES2.GL_RED;
- } else {
- // ALPHA is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
- dFormat = GL.GL_ALPHA;
- }
- dType = GL.GL_UNSIGNED_BYTE;
- } else if( 3 == componentCount ) {
- dFormat = GL.GL_RGB;
- dType = GL.GL_UNSIGNED_BYTE;
- } else if( 4 == componentCount ) {
- final int _dFormat = ctx.getDefaultPixelDataFormat();
- final int dComps = GLBuffers.componentCount(_dFormat);
- if( dComps == componentCount ) {
- dFormat = _dFormat;
- dType = ctx.getDefaultPixelDataType();
- } else {
- dFormat = GL.GL_RGBA;
- dType = GL.GL_UNSIGNED_BYTE;
- }
- } else {
+ public GLPixelAttributes getAttributes(final GL gl, final int componentCount, final boolean pack) {
+ final GLPixelAttributes res = GLPixelAttributes.convert(gl, componentCount, pack);
+ if( null == res ) {
throw new GLException("Unsupported componentCount "+componentCount+", contact maintainer to enhance");
+ } else {
+ return res;
}
- return new GLPixelAttributes(componentCount, dFormat, dType);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns {@code null}!
+ * </p>
+ */
+ @Override
+ public PixelFormat.Composition getHostPixelComp(final GLProfile glp, final int componentCount) {
+ return null;
}
/**
@@ -149,13 +196,15 @@ public class GLPixelBuffer {
* </p>
*/
@Override
- public GLPixelBuffer allocate(final GL gl, final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
+ public GLPixelBuffer allocate(final GL gl, final PixelFormat.Composition hostPixComp, final GLPixelAttributes pixelAttributes,
+ final boolean pack, final int width, final int height, final int depth, final int minByteSize) {
+ // unused: hostPixComp
if( minByteSize > 0 ) {
- return new GLPixelBuffer(pixelAttributes, width, height, depth, pack, Buffers.newDirectByteBuffer(minByteSize), getAllowRowStride());
+ return new GLPixelBuffer(pixelAttributes, pack, width, height, depth, Buffers.newDirectByteBuffer(minByteSize), getAllowRowStride());
} else {
final 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), getAllowRowStride());
+ final int byteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.pfmt.comp.bytesPerPixel(), width, height, depth, pack);
+ return new GLPixelBuffer(pixelAttributes, pack, width, height, depth, Buffers.newDirectByteBuffer(byteSize), getAllowRowStride());
}
}
}
@@ -163,74 +212,190 @@ public class GLPixelBuffer {
/**
* Default {@link GLPixelBufferProvider} with {@link GLPixelBufferProvider#getAllowRowStride()} == <code>false</code>,
* utilizing best match for {@link GLPixelAttributes}
- * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}.
+ * and {@link GLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocating} a {@link ByteBuffer}.
*/
public static final GLPixelBufferProvider defaultProviderNoRowStride = new DefaultGLPixelBufferProvider(false);
/**
* Default {@link GLPixelBufferProvider} with {@link GLPixelBufferProvider#getAllowRowStride()} == <code>true</code>,
* utilizing best match for {@link GLPixelAttributes}
- * and {@link GLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocating} a {@link ByteBuffer}.
+ * and {@link GLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocating} a {@link ByteBuffer}.
*/
public static final GLPixelBufferProvider defaultProviderWithRowStride = new DefaultGLPixelBufferProvider(true);
/** 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, false);
-
- /** Pixel <i>source</i> component count, i.e. number of meaningful components. */
- 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;
+ public static final GLPixelAttributes UNDEF = new GLPixelAttributes(null, PixelFormat.LUMINANCE, 0, 0, true, false);
/**
- * 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
+ * Returns the matching {@link PixelFormat} for the given GL format and type if exists,
+ * otherwise returns <code>null</code>.
*/
- public GLPixelAttributes(final int dataFormat, final int dataType) {
- this(0 < dataFormat ? GLBuffers.componentCount(dataFormat) : 0, dataFormat, dataType);
+ public static final PixelFormat getPixelFormat(final int glFormat, final int glDataType) {
+ PixelFormat pixFmt = null;
+
+ switch(glFormat) {
+ case GL.GL_ALPHA:
+ case GL.GL_LUMINANCE:
+ case GL2ES2.GL_RED:
+ pixFmt = PixelFormat.LUMINANCE;
+ break;
+ case GL.GL_RGB:
+ switch(glDataType) {
+ case GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV:
+ pixFmt = PixelFormat.RGB565;
+ break;
+ case GL.GL_UNSIGNED_SHORT_5_6_5:
+ pixFmt = PixelFormat.BGR565;
+ break;
+ case GL.GL_UNSIGNED_BYTE:
+ pixFmt = PixelFormat.RGB888;
+ break;
+ }
+ break;
+ case GL.GL_RGBA:
+ switch(glDataType) {
+ case GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ pixFmt = PixelFormat.RGBA5551;
+ break;
+ case GL.GL_UNSIGNED_SHORT_5_5_5_1:
+ pixFmt = PixelFormat.ABGR1555;
+ break;
+ case GL.GL_UNSIGNED_BYTE:
+ pixFmt = PixelFormat.RGBA8888;
+ break;
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
+ pixFmt = PixelFormat.ABGR8888;
+ break;
+ }
+ break;
+ case GL2GL3.GL_BGR:
+ if( GL.GL_UNSIGNED_BYTE == glDataType ) {
+ pixFmt = PixelFormat.BGR888;
+ }
+ break;
+ case GL.GL_BGRA:
+ switch(glDataType) {
+ case GL2GL3.GL_UNSIGNED_INT_8_8_8_8:
+ pixFmt = PixelFormat.ARGB8888;
+ break;
+ case GL.GL_UNSIGNED_BYTE:
+ pixFmt = PixelFormat.BGRA8888;
+ break;
+ }
+ break;
+ }
+ return pixFmt;
}
+
/**
- * Using user specified source {@link #componentCount}.
- * @param componentCount source component count
- * @param dataFormat GL data format
- * @param dataType GL data type
+ * Returns the matching {@link GLPixelAttributes} for the given byte sized RGBA {@code componentCount} and {@link GL} if exists,
+ * otherwise returns {@code null}.
+ *
+ * @param gl the corresponding current {@link GL} context object
+ * @param componentCount RGBA component count, i.e. 1 (luminance, alpha or red), 3 (RGB) or 4 (RGBA)
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
*/
- public GLPixelAttributes(final int componentCount, final int dataFormat, final int dataType) {
- this(componentCount, dataFormat, dataType, true);
+ public static GLPixelAttributes convert(final GL gl, final int componentCount, final boolean pack) {
+ final int dFormat, dType;
+ final boolean glesReadMode = pack && gl.isGLES();
+
+ if( 1 == componentCount && !glesReadMode ) {
+ if( gl.isGL3ES3() ) {
+ // RED is supported on ES3 and >= GL3 [core]; ALPHA is deprecated on core
+ dFormat = GL2ES2.GL_RED;
+ } else {
+ // ALPHA is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
+ dFormat = GL.GL_ALPHA;
+ }
+ dType = GL.GL_UNSIGNED_BYTE;
+ } else if( 3 == componentCount && !glesReadMode ) {
+ dFormat = GL.GL_RGB;
+ dType = GL.GL_UNSIGNED_BYTE;
+ } else if( 4 == componentCount || glesReadMode ) {
+ final GLContext ctx = gl.getContext();
+ final int _dFormat = ctx.getDefaultPixelDataFormat();
+ final int dComps = GLBuffers.componentCount(_dFormat);
+ if( dComps == componentCount || 4 == dComps ) { // accept if desired component count or 4 components
+ dFormat = _dFormat;
+ dType = ctx.getDefaultPixelDataType();
+ } else {
+ dFormat = GL.GL_RGBA;
+ dType = GL.GL_UNSIGNED_BYTE;
+ }
+ } else {
+ return null;
+ }
+ return new GLPixelAttributes(dFormat, dType);
}
/**
- * Returns the matching {@link GLPixelAttributes} for the given {@link PixelFormat} and {@link GLProfile} if exists,
- * otherwise returns <code>null</code>.
+ * Returns the matching {@link GLPixelAttributes} for the given {@link GLProfile}, {@link PixelFormat} and {@code pack} if exists,
+ * otherwise returns {@code null}.
+ * @param glp the corresponding {@link GLProfile}
+ * @param pixFmt the to be matched {@link PixelFormat pixel format}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
*/
- public static final GLPixelAttributes convert(final PixelFormat pixFmt, final GLProfile glp) {
+ public static final GLPixelAttributes convert(final GLProfile glp, final PixelFormat pixFmt, final boolean pack) {
+ final int[] df = new int[1];
+ final int[] dt = new int[1];
+ convert(glp, pixFmt, pack, df, dt);
+ if( 0 != df[0] ) {
+ return new GLPixelAttributes(null, pixFmt, df[0], dt[0], true /* not used */, true);
+ }
+ return null;
+ }
+ private static final int convert(final GLProfile glp, final PixelFormat pixFmt, final boolean pack,
+ final int[] dfRes, final int[] dtRes) {
+ final boolean glesReadMode = pack && glp.isGLES();
int df = 0; // format
int dt = GL.GL_UNSIGNED_BYTE; // data type
switch(pixFmt) {
case LUMINANCE:
- if( glp.isGL3ES3() ) {
- // RED is supported on ES3 and >= GL3 [core]; ALPHA/LUMINANCE is deprecated on core
- df = GL2ES2.GL_RED;
- } else {
- // ALPHA/LUMINANCE is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
- df = GL.GL_LUMINANCE;
+ if( !glesReadMode ) {
+ if( glp.isGL3ES3() ) {
+ // RED is supported on ES3 and >= GL3 [core]; ALPHA/LUMINANCE is deprecated on core
+ df = GL2ES2.GL_RED;
+ } else {
+ // ALPHA/LUMINANCE is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
+ df = GL.GL_LUMINANCE;
+ }
}
break;
- case BGR888:
+ case RGB565:
if( glp.isGL2GL3() ) {
- df = GL2GL3.GL_BGR;
+ df = GL.GL_RGB; dt = GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV;
+ }
+ break;
+ case BGR565:
+ if( glp.isGL2GL3() ) {
+ df = GL.GL_RGB; dt = GL.GL_UNSIGNED_SHORT_5_6_5;
+ }
+ break;
+ case RGBA5551:
+ if( glp.isGL2GL3() ) {
+ df = GL.GL_RGBA; dt = GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV;
+ }
+ break;
+ case ABGR1555:
+ if( glp.isGL2GL3() ) {
+ df = GL.GL_RGBA; dt = GL.GL_UNSIGNED_SHORT_5_5_5_1;
}
break;
case RGB888:
- df = GL.GL_RGB;
+ if( !glesReadMode ) {
+ df = GL.GL_RGB;
+ }
+ break;
+ case BGR888:
+ if( glp.isGL2GL3() ) {
+ df = GL2GL3.GL_BGR;
+ }
break;
+ case RGBx8888:
case RGBA8888:
df = GL.GL_RGBA;
break;
@@ -239,85 +404,107 @@ public class GLPixelBuffer {
df = GL.GL_RGBA; dt = GL2GL3.GL_UNSIGNED_INT_8_8_8_8;
}
break;
- case BGRA8888:
- df = GL.GL_BGRA;
- break;
case ARGB8888:
if( glp.isGL2GL3() ) {
df = GL.GL_BGRA; dt = GL2GL3.GL_UNSIGNED_INT_8_8_8_8;
}
break;
- default:
+ case BGRx8888:
+ case BGRA8888:
+ if( glp.isGL2GL3() ) { // FIXME: or if( !glesReadMode ) ? BGRA n/a on GLES
+ df = GL.GL_BGRA;
+ }
break;
}
- if( 0 != df ) {
- return new GLPixelAttributes(pixFmt.componentCount, df, dt, true);
- }
- return null;
+ dfRes[0] = df;
+ dtRes[0] = dt;
+ return df;
}
- private GLPixelAttributes(final int componentCount, final int dataFormat, final int dataType, final boolean checkArgs) {
- this.componentCount = componentCount;
- this.format = dataFormat;
- this.type = dataType;
- this.bytesPerPixel = ( 0 < dataFormat && 0 < dataType ) ? GLBuffers.bytesPerPixel(dataFormat, dataType) : 0;
- if( checkArgs ) {
- if( 0 == componentCount || 0 == format || 0 == type ) {
- throw new GLException("Zero components, format and/or type: "+this);
- }
- if( 0 == bytesPerPixel ) {
- throw new GLException("Zero bytesPerPixel: "+this);
- }
+
+ /** The OpenGL pixel data format */
+ public final int format;
+ /** The OpenGL pixel data type */
+ public final int type;
+
+ /** {@link PixelFormat} describing the {@link PixelFormat.Composition component} layout */
+ public final PixelFormat pfmt;
+
+ @Override
+ public final int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = pfmt.hashCode();
+ hash = ((hash << 5) - hash) + format;
+ return ((hash << 5) - hash) + type;
+ }
+
+ @Override
+ public final boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if( obj instanceof GLPixelAttributes ) {
+ final GLPixelAttributes other = (GLPixelAttributes) obj;
+ return format == other.format &&
+ type == other.type &&
+ pfmt.equals(other.pfmt);
+ } else {
+ return false;
}
}
/**
- * Returns the matching {@link PixelFormat} of this {@link GLPixelAttributes} if exists,
- * otherwise returns <code>null</code>.
+ * Create a new {@link GLPixelAttributes} instance based on GL format and type.
+ * @param dataFormat GL data format
+ * @param dataType GL data type
+ * @throws GLException if {@link PixelFormat} could not be determined, see {@link #getPixelFormat(int, int)}.
*/
- public final PixelFormat getPixelFormat() {
- final PixelFormat pixFmt;
- // FIXME: Take 'type' into consideration and complete mapping!
- switch(format) {
- case GL.GL_ALPHA:
- case GL.GL_LUMINANCE:
- case GL2ES2.GL_RED:
- pixFmt = PixelFormat.LUMINANCE;
- break;
- case GL.GL_RGB:
- pixFmt = PixelFormat.RGB888;
- break;
- case GL.GL_RGBA:
- pixFmt = PixelFormat.RGBA8888;
- break;
- case GL2GL3.GL_BGR:
- pixFmt = PixelFormat.BGR888;
- break;
- case GL.GL_BGRA:
- pixFmt = PixelFormat.BGRA8888;
- break;
- default:
- switch( bytesPerPixel ) {
- case 1:
- pixFmt = PixelFormat.LUMINANCE;
- break;
- case 3:
- pixFmt = PixelFormat.RGB888;
- break;
- case 4:
- pixFmt = PixelFormat.RGBA8888;
- break;
- default:
- pixFmt = null;
- break;
- }
- break;
+ public GLPixelAttributes(final int dataFormat, final int dataType) throws GLException {
+ this(null, null, dataFormat, dataType, true /* not used */, true);
+ }
+
+ /**
+ * Create a new {@link GLPixelAttributes} instance based on {@link GLProfile}, {@link PixelFormat} and {@code pack}.
+ * @param glp the corresponding {@link GLProfile}
+ * @param pixFmt the to be matched {@link PixelFormat pixel format}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
+ * @throws GLException if GL format or type could not be determined, see {@link #convert(GLProfile, PixelFormat, boolean)}.
+ */
+ public GLPixelAttributes(final GLProfile glp, final PixelFormat pixFmt, final boolean pack) throws GLException {
+ this(glp, pixFmt, 0, 0, pack, true);
+ }
+
+ private GLPixelAttributes(final GLProfile glp, final PixelFormat pixFmt,
+ final int dataFormat, final int dataType, final boolean pack, final boolean checkArgs) throws GLException {
+ if( checkArgs && ( 0 == dataFormat || 0 == dataType ) ) {
+ if( null == pixFmt || null == glp ) {
+ throw new GLException("Zero format and/or type w/o pixFmt or glp: "+this);
+ }
+ final int[] df = new int[1];
+ final int[] dt = new int[1];
+ if( 0 == convert(glp, pixFmt, pack, df, dt) ) {
+ throw new GLException("Could not find format and type for "+pixFmt+" and "+glp+", "+this);
+ }
+ this.format = df[0];
+ this.type = dt[0];
+ this.pfmt = pixFmt;
+ } else {
+ this.format = dataFormat;
+ this.type = dataType;
+ this.pfmt = null != pixFmt ? pixFmt : getPixelFormat(dataFormat, dataType);
+ if( null == this.pfmt ) {
+ throw new GLException("Could not find PixelFormat for format and/or type: "+this);
+ }
+ }
+ if( checkArgs ) {
+ final int bytesPerPixel = GLBuffers.bytesPerPixel(this.format, this.type);
+ if( 0 == bytesPerPixel ) {
+ throw new GLException("Zero bytesPerPixel: "+this);
+ }
}
- return pixFmt;
}
@Override
public String toString() {
- return "PixelAttributes[comp "+componentCount+", fmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+", bytesPerPixel "+bytesPerPixel+"]";
+ return "PixelAttributes[fmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+", "+pfmt+"]";
}
}
@@ -339,14 +526,18 @@ public class GLPixelBuffer {
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. */
+ /**
+ * Data packing direction.
+ * <p>{@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.</p>
+ * <p>{@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.</p>
+ */
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)}.
+ * By default the {@link Buffer} is a {@link ByteBuffer}, due to {@link DefProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int)}.
* However, other {@link GLPixelBufferProvider} may utilize different {@link Buffer} types.
* </p>
*/
@@ -375,14 +566,16 @@ public class GLPixelBuffer {
/**
* @param pixelAttributes the desired {@link GLPixelAttributes}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
* @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 buffer the backing array
* @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link #requiresNewBuffer(GL, int, int, int)}.
+ * @param hostPixelComp the host {@link PixelFormat.Composition}
*/
- public GLPixelBuffer(final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final Buffer buffer, final boolean allowRowStride) {
+ public GLPixelBuffer(final GLPixelAttributes pixelAttributes, final boolean pack, final int width, final int height, final int depth, final Buffer buffer, final boolean allowRowStride) {
this.pixelAttributes = pixelAttributes;
this.width = width;
this.height = height;
@@ -462,7 +655,7 @@ public class GLPixelBuffer {
* @param newWidth new width in pixels
* @param newHeight new height in pixels
* @param newByteSize 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)
+ * @see GLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int)
*/
public boolean requiresNewBuffer(final GL gl, final int newWidth, final int newHeight, int newByteSize) {
if( !isValid() ) {
@@ -470,7 +663,7 @@ public class GLPixelBuffer {
}
if( 0 >= newByteSize ) {
final int[] tmp = { 0 };
- newByteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.bytesPerPixel, newWidth, newHeight, 1, true);
+ newByteSize = GLBuffers.sizeof(gl, tmp, pixelAttributes.pfmt.comp.bytesPerPixel(), newWidth, newHeight, 1, true);
}
if( allowRowStride ) {
return byteSize < newByteSize;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index e84a1d874..597498c9d 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -31,6 +31,7 @@ package com.jogamp.opengl.util;
import java.io.File;
import java.io.IOException;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES3;
import javax.media.opengl.GLAutoDrawable;
@@ -51,10 +52,10 @@ import com.jogamp.opengl.util.texture.TextureIO;
*/
public class GLReadBufferUtil {
protected final GLPixelBufferProvider pixelBufferProvider;
- protected final int componentCount, alignment;
protected final Texture readTexture;
protected final GLPixelStorageModes psm;
+ protected boolean hasAlpha;
protected GLPixelBuffer readPixelBuffer = null;
protected TextureData readTextureData = null;
@@ -68,10 +69,9 @@ public class GLReadBufferUtil {
public GLReadBufferUtil(final GLPixelBufferProvider pixelBufferProvider, final boolean alpha, final boolean write2Texture) {
this.pixelBufferProvider = pixelBufferProvider;
- this.componentCount = alpha ? 4 : 3 ;
- this.alignment = alpha ? 4 : 1 ;
this.readTexture = write2Texture ? new Texture(GL.GL_TEXTURE_2D) : null ;
this.psm = new GLPixelStorageModes();
+ this.hasAlpha = alpha; // preset
}
/** Returns the {@link GLPixelBufferProvider} used by this instance. */
@@ -81,7 +81,7 @@ public class GLReadBufferUtil {
return null!=readTextureData && null!=readPixelBuffer && readPixelBuffer.isValid();
}
- public boolean hasAlpha() { return 4 == componentCount ? true : false ; }
+ public boolean hasAlpha() { return hasAlpha; }
public GLPixelStorageModes getGLPixelStorageModes() { return psm; }
@@ -173,13 +173,13 @@ public class GLReadBufferUtil {
if(GL.GL_NO_ERROR != glerr0) {
System.err.println("Info: GLReadBufferUtil.readPixels: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
}
- final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
- final int internalFormat;
- if(gl.isGL2GL3() && 3 == componentCount) {
- internalFormat = GL.GL_RGB;
- } else {
- internalFormat = (4 == componentCount) ? GL.GL_RGBA : GL.GL_RGB;
- }
+ final int reqCompCount = hasAlpha ? 4 : 3;
+ final PixelFormat.Composition hostPixelComp = pixelBufferProvider.getHostPixelComp(gl.getGLProfile(), reqCompCount);
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, reqCompCount, true);
+ final int componentCount = pixelAttribs.pfmt.comp.componenCount();
+ hasAlpha = 0 <= pixelAttribs.pfmt.comp.find(PixelFormat.CType.A);
+ final int alignment = 4 == componentCount ? 4 : 1 ;
+ final int internalFormat = 4 == componentCount ? GL.GL_RGBA : GL.GL_RGB;
final boolean flipVertically;
if( drawable.isGLOriented() ) {
@@ -189,11 +189,11 @@ public class GLReadBufferUtil {
}
final int tmp[] = new int[1];
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, width, height, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.pfmt.comp.bytesPerPixel(), width, height, 1, true);
boolean newData = false;
if( null == readPixelBuffer || readPixelBuffer.requiresNewBuffer(gl, width, height, readPixelSize) ) {
- readPixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, width, height, 1, true, readPixelSize);
+ readPixelBuffer = pixelBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, width, height, 1, readPixelSize);
Buffers.rangeCheckBytes(readPixelBuffer.buffer, readPixelSize);
try {
readTextureData = new TextureData(
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
index 64da547c2..29e1cf353 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
@@ -137,7 +137,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
} else {
destFmt = ddestFmt; // user choice
}
- final int destStrideInBytes = Math.max(destMinStrideInBytes, destFmt.bytesPerPixel() * width);
+ final int destStrideInBytes = Math.max(destMinStrideInBytes, destFmt.comp.bytesPerPixel() * width);
final ByteBuffer destPixels = destDirectBuffer ? Buffers.newDirectByteBuffer(destStrideInBytes * height) :
ByteBuffer.allocate(destStrideInBytes * height);
{
@@ -153,7 +153,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
System.err.println("PNGPixelRect: indexed "+indexed+", alpha "+hasAlpha+", grayscale "+imgInfo.greyscale+", channels "+channels+"/"+imgInfo.channels+
", bytesPerPixel "+bytesPerPixel+"/"+imgInfo.bytesPixel+
", grayAlpha "+isGrayAlpha+", pixels "+width+"x"+height+", dpi "+dpiX+"x"+dpiY+", format "+srcFmt);
- System.err.println("PNGPixelRect: destFormat "+destFmt+" ("+ddestFmt+", bytesPerPixel "+destFmt.bytesPerPixel()+", fast-path "+(destFmt==srcFmt)+"), destDirectBuffer "+destDirectBuffer+", destIsGLOriented (flip) "+destIsGLOriented);
+ System.err.println("PNGPixelRect: destFormat "+destFmt+" ("+ddestFmt+", fast-path "+(destFmt==srcFmt)+"), destDirectBuffer "+destDirectBuffer+", destIsGLOriented (flip) "+destIsGLOriented);
System.err.println("PNGPixelRect: destStrideInBytes "+destStrideInBytes+" (destMinStrideInBytes "+destMinStrideInBytes+")");
}
@@ -227,7 +227,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
(byte)scanline[lineOff+1], // G
(byte)scanline[lineOff+2], // B
srcHasAlpha ? (byte)scanline[lineOff+3] : (byte)0xff); // A
- final int dbpp = dest_fmt.bytesPerPixel();
+ final int dbpp = dest_fmt.comp.bytesPerPixel();
d.put(dOff++, (byte) ( p )); // 1
if( 1 < dbpp ) {
d.put(dOff++, (byte) ( p >>> 8 )); // 2
@@ -261,7 +261,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
if(hasAlpha) {
line.scanline[lineOff + 3] = 0xff & ( p >>> 24 ); // A
}
- return srcOff + pixelformat.bytesPerPixel();
+ return srcOff + pixelformat.comp.bytesPerPixel();
}
private static void setPixelRGBA8(final PixelFormat pixelformat, final ImageLine line, final int lineOff, final int srcPix, final int bytesPerPixel, final boolean hasAlpha) {
@@ -304,7 +304,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
public void write(final OutputStream outstream, final boolean closeOutstream) throws IOException {
final int width = size.getWidth();
final int height = size.getHeight();
- final int bytesPerPixel = pixelformat.bytesPerPixel();
+ final int bytesPerPixel = pixelformat.comp.bytesPerPixel();
final ImageInfo imi = new ImageInfo(width, height, 8 /* bitdepth */,
(4 == bytesPerPixel) ? true : false /* alpha */,
(1 == bytesPerPixel) ? true : false /* grayscale */,
@@ -349,7 +349,7 @@ public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
final OutputStream outstream, final boolean closeOutstream) throws IOException {
final int width = size.getWidth();
final int height = size.getHeight();
- final int bytesPerPixel = pixelformat.bytesPerPixel();
+ final int bytesPerPixel = pixelformat.comp.bytesPerPixel();
final ImageInfo imi = new ImageInfo(width, height, 8 /* bitdepth */,
(4 == bytesPerPixel) ? true : false /* alpha */,
(1 == bytesPerPixel) ? true : false /* grayscale */,
diff --git a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
index 3b65b0824..bf7cf668c 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/RandomTileRenderer.java
@@ -176,7 +176,7 @@ public class RandomTileRenderer extends TileRendererBase {
final int srcY = 0;
final int srcWidth = currentTileWidth;
final int srcHeight = currentTileHeight;
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.pfmt.comp.bytesPerPixel(), srcWidth, srcHeight, 1, true);
tileBuffer.clear();
if( tileBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
throw new IndexOutOfBoundsException("Required " + readPixelSize + " bytes of buffer, only had " + tileBuffer);
@@ -200,9 +200,9 @@ public class RandomTileRenderer extends TileRendererBase {
psm.setPackRowLength(gl2es3, rowLength);
/* read the tile into the final image */
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.pfmt.comp.bytesPerPixel(), srcWidth, srcHeight, 1, true);
- final int ibPos = ( currentTileXPos + ( currentTileYPos * rowLength ) ) * pixelAttribs.bytesPerPixel; // skipPixels + skipRows
+ final int ibPos = ( currentTileXPos + ( currentTileYPos * rowLength ) ) * pixelAttribs.pfmt.comp.bytesPerPixel(); // skipPixels + skipRows
final int ibLim = ibPos + readPixelSize;
imageBuffer.clear();
if( imageBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
index d8410a102..fee2e5933 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/TileRenderer.java
@@ -479,7 +479,7 @@ public class TileRenderer extends TileRendererBase {
final int srcY = tileBorder;
final int srcWidth = tileSizeNB.getWidth();
final int srcHeight = tileSizeNB.getHeight();
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.pfmt.comp.bytesPerPixel(), srcWidth, srcHeight, 1, true);
tileBuffer.clear();
if( tileBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
throw new IndexOutOfBoundsException("Required " + readPixelSize + " bytes of buffer, only had " + tileBuffer);
@@ -503,11 +503,11 @@ public class TileRenderer extends TileRendererBase {
psm.setPackRowLength(gl2es3, rowLength);
/* read the tile into the final image */
- final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.bytesPerPixel, srcWidth, srcHeight, 1, true);
+ final int readPixelSize = GLBuffers.sizeof(gl, tmp, pixelAttribs.pfmt.comp.bytesPerPixel(), srcWidth, srcHeight, 1, true);
final int skipPixels = currentColumn * tileSizeNB.getWidth();
final int skipRows = currentRow * tileSizeNB.getHeight();
- final int ibPos = ( skipPixels + ( skipRows * rowLength ) ) * pixelAttribs.bytesPerPixel;
+ final int ibPos = ( skipPixels + ( skipRows * rowLength ) ) * pixelAttribs.pfmt.comp.bytesPerPixel();
final int ibLim = ibPos + readPixelSize;
imageBuffer.clear();
if( imageBuffer.requiresNewBuffer(gl, srcWidth, srcHeight, readPixelSize) ) {
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
index 04bc0a15d..81cb34239 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/AWTGLPixelBuffer.java
@@ -36,10 +36,14 @@ import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import java.nio.Buffer;
import java.nio.IntBuffer;
+import java.util.Iterator;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
+import javax.media.opengl.GLProfile;
import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IntObjectHashMap;
import com.jogamp.opengl.util.GLPixelBuffer;
/**
@@ -50,7 +54,7 @@ import com.jogamp.opengl.util.GLPixelBuffer;
* </p>
* <p>
* {@link AWTGLPixelBuffer} can be produced via {@link AWTGLPixelBufferProvider}'s
- * {@link AWTGLPixelBufferProvider#allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocate(..)}.
+ * {@link AWTGLPixelBufferProvider#allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocate(..)}.
* </p>
* <p>
* See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)} for {@link #allowRowStride} details.
@@ -61,30 +65,49 @@ import com.jogamp.opengl.util.GLPixelBuffer;
* </p>
*/
public class AWTGLPixelBuffer extends GLPixelBuffer {
- public static final GLPixelAttributes awtPixelAttributesIntRGBA4 = new GLPixelAttributes(4, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
- public static final GLPixelAttributes awtPixelAttributesIntRGB3 = new GLPixelAttributes(3, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
+ /**
+ * Ignoring componentCount, since otherwise no AWT/GL matching types are found.
+ * <p>
+ * Due to using RGBA and BGRA, pack/unpack usage has makes no difference.
+ * </p>
+ */
+ private static final GLPixelAttributes awtPixelAttributesIntBGRA = new GLPixelAttributes(GL.GL_BGRA, GL.GL_UNSIGNED_BYTE);
+ private static final GLPixelAttributes awtPixelAttributesIntRGBA = new GLPixelAttributes(GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
/** The underlying {@link BufferedImage}. */
public final BufferedImage image;
+ private final PixelFormat.Composition hostPixelComp;
+ private final int awtFormat;
+
/**
- *
+ * @param hostPixelComp the host {@link PixelFormat.Composition}
* @param pixelAttributes the desired {@link GLPixelAttributes}
+ * @param pack {@code true} for read mode GPU -> CPU, e.g. {@link GL#glReadPixels(int, int, int, int, int, int, Buffer) glReadPixels}.
+ * {@code false} for write mode CPU -> GPU, e.g. {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, Buffer) glTexImage2D}.
+ * @param awtFormat the used AWT format, i.e. {@link AWTGLPixelBufferProvider#getAWTFormat(GLProfile, int)}
* @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)}.
* If <code>true</code>, user shall decide whether to use a {@link #getAlignedImage(int, int) width-aligned image}.
*/
- public AWTGLPixelBuffer(final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final BufferedImage image,
- final Buffer buffer, final boolean allowRowStride) {
- super(pixelAttributes, width, height, depth, pack, buffer, allowRowStride);
+ public AWTGLPixelBuffer(final PixelFormat.Composition hostPixelComp,
+ final GLPixelAttributes pixelAttributes,
+ final boolean pack,
+ final int awtFormat, final int width, final int height, final int depth,
+ final BufferedImage image, final Buffer buffer, final boolean allowRowStride) {
+ super(pixelAttributes, pack, width, height, depth, buffer, allowRowStride);
this.image = image;
+ this.hostPixelComp = hostPixelComp;
+ this.awtFormat = awtFormat;
}
+ public final PixelFormat.Composition getHostPixelComp() { return hostPixelComp; }
+ public final int getAWTFormat() { return awtFormat; }
+
@Override
public void dispose() {
image.flush();
@@ -147,12 +170,57 @@ public class AWTGLPixelBuffer extends GLPixelBuffer {
public AWTGLPixelBufferProvider(final boolean allowRowStride) {
this.allowRowStride = allowRowStride;
}
+
@Override
public boolean getAllowRowStride() { return allowRowStride; }
@Override
- public GLPixelAttributes getAttributes(final GL gl, final int componentCount) {
- return 4 == componentCount ? awtPixelAttributesIntRGBA4 : awtPixelAttributesIntRGB3;
+ public GLPixelAttributes getAttributes(final GL gl, final int componentCount, final boolean pack) {
+ return gl.isGLES() ? awtPixelAttributesIntRGBA : awtPixelAttributesIntBGRA;
+ }
+
+ public GLPixelAttributes getAttributes(final GLProfile glp, final int componentCount) {
+ return glp.isGLES() ? awtPixelAttributesIntRGBA : awtPixelAttributesIntBGRA;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns a valid {@link PixelFormat.Composition} instance from {@link #getAWTPixelFormat(GLProfile, int)}.
+ * </p>
+ */
+ @Override
+ public PixelFormat.Composition getHostPixelComp(final GLProfile glp, final int componentCount) {
+ return getAWTPixelFormat(glp, componentCount).comp;
+ }
+
+ /**
+ * Returns one of
+ * <ul>
+ * <li>GL__, 4c -> 4c: {@link BufferedImage#TYPE_INT_ARGB} <-> {@link GL#GL_BGRA}</li>
+ * <li>GLES, 4c -> 4c: {@link BufferedImage#TYPE_INT_BGR} <-> {@link GL#GL_RGBA}</li>
+ * <li>GL__, 3c -> 4c: {@link BufferedImage#TYPE_INT_RGB} <-> {@link GL#GL_BGRA}</li>
+ * <li>GLES, 3c -> 4c: {@link BufferedImage#TYPE_INT_BGR} <-> {@link GL#GL_RGBA}</li>
+ * </ul>
+ * @param glp
+ * @param componentCount
+ * @return
+ */
+ public int getAWTFormat(final GLProfile glp, final int componentCount) {
+ if( 4 == componentCount ) {
+ // FIXME: 4 component solution BufferedImage.TYPE_INT_ARGB: GLES format missing (i.e. GL_BGRA)
+ return glp.isGLES() ? BufferedImage.TYPE_INT_BGR : BufferedImage.TYPE_INT_ARGB;
+ } else {
+ return glp.isGLES() ? BufferedImage.TYPE_INT_BGR : BufferedImage.TYPE_INT_RGB;
+ }
+ }
+
+ public PixelFormat getAWTPixelFormat(final GLProfile glp, final int componentCount) {
+ if( 4 == componentCount ) {
+ return glp.isGLES() ? PixelFormat.RGBx8888 : PixelFormat.BGRA8888;
+ } else {
+ return glp.isGLES() ? PixelFormat.RGBx8888 : PixelFormat.BGRx8888;
+ }
}
/**
@@ -162,11 +230,17 @@ public class AWTGLPixelBuffer extends GLPixelBuffer {
* </p>
*/
@Override
- public AWTGLPixelBuffer allocate(final GL gl, final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
- final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+ public AWTGLPixelBuffer allocate(final GL gl, final PixelFormat.Composition hostPixComp, final GLPixelAttributes pixelAttributes, final boolean pack,
+ final int width, final int height, final int depth, final int minByteSize) {
+ if( null == hostPixComp ) {
+ throw new IllegalArgumentException("Null hostPixComp");
+ }
+ final int awtFormat = getAWTFormat(gl.getGLProfile(), hostPixComp.componenCount());
+ final BufferedImage image = new BufferedImage(width, height, awtFormat);
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);
+ return new AWTGLPixelBuffer(hostPixComp, pixelAttributes, pack,
+ awtFormat, width, height, depth, image, ibuffer, allowRowStride);
}
}
@@ -174,15 +248,22 @@ public class AWTGLPixelBuffer extends GLPixelBuffer {
* 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}
+ * {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated}.
+ * A new {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, 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 implements SingletonGLPixelBufferProvider {
- private AWTGLPixelBuffer singleRGBA4 = null;
- private AWTGLPixelBuffer singleRGB3 = null;
+ private final IntObjectHashMap bufferMap = new IntObjectHashMap(8);
+
+ private static int getHashCode(final PixelFormat.Composition hostPixelComp, final GLPixelAttributes pixelAttributes, final boolean pack) {
+ // 31 * x == (x << 5) - x
+ int hash = hostPixelComp.hashCode();
+ hash = ((hash << 5) - hash) + pixelAttributes.hashCode();
+ // hash = ((hash << 5) - hash) + (pack ? 100 : 0); // no difference due to RGBA/BGRA only modes.
+ return hash;
+ }
/**
* @param allowRowStride If <code>true</code>, allow row-stride, otherwise not. See {@link AWTGLPixelBuffer#requiresNewBuffer(GL, int, int, int)}.
@@ -198,52 +279,72 @@ public class AWTGLPixelBuffer extends GLPixelBuffer {
* </p>
*/
@Override
- public AWTGLPixelBuffer allocate(final GL gl, final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
- if( 4 == pixelAttributes.componentCount ) {
- if( null == singleRGBA4 || singleRGBA4.requiresNewBuffer(gl, width, height, minByteSize) ) {
- singleRGBA4 = allocateImpl(pixelAttributes, width, height, depth, pack, minByteSize);
- }
- return singleRGBA4;
- } else {
- if( null == singleRGB3 || singleRGB3.requiresNewBuffer(gl, width, height, minByteSize) ) {
- singleRGB3 = allocateImpl(pixelAttributes, width, height, depth, pack, minByteSize);
+ public AWTGLPixelBuffer allocate(final GL gl, PixelFormat.Composition hostPixComp, final GLPixelAttributes pixelAttributes,
+ final boolean pack, final int width, final int height, final int depth, final int minByteSize) {
+ if( null == hostPixComp ) {
+ hostPixComp = pixelAttributes.pfmt.comp;
+ }
+ final int bufferKey = getHashCode(hostPixComp, pixelAttributes, pack);
+ AWTGLPixelBuffer r = (AWTGLPixelBuffer) bufferMap.get(bufferKey);
+ if( null == r || r.requiresNewBuffer(gl, width, height, minByteSize) ) {
+ if( null != r ) {
+ r.dispose();
}
- return singleRGB3;
+ r = allocateImpl(hostPixComp, pixelAttributes, pack,
+ getAWTFormat(gl.getGLProfile(), hostPixComp.componenCount()), width, height, depth, minByteSize);
+ bufferMap.put(bufferKey, r);
}
+ return r;
}
- private AWTGLPixelBuffer allocateImpl(final GLPixelAttributes pixelAttributes, final int width, final int height, final int depth, final boolean pack, final int minByteSize) {
- final BufferedImage image = new BufferedImage(width, height, 4 == pixelAttributes.componentCount ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+ private AWTGLPixelBuffer allocateImpl(final PixelFormat.Composition hostPixComp,
+ final GLPixelAttributes pixelAttributes,
+ final boolean pack,
+ final int awtFormat, final int width, final int height, final int depth,
+ final int minByteSize) {
+ final BufferedImage image = new BufferedImage(width, height, awtFormat);
final int[] readBackIntBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
final Buffer ibuffer = IntBuffer.wrap( readBackIntBuffer );
- return new AWTGLPixelBuffer(pixelAttributes, width, height, depth, pack, image, ibuffer, getAllowRowStride());
+ return new AWTGLPixelBuffer(hostPixComp, pixelAttributes, pack,
+ awtFormat, width, height, depth, image, ibuffer, getAllowRowStride());
}
- /** Return the last {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated} {@link AWTGLPixelBuffer} w/ {@link GLPixelAttributes#componentCount}. */
+ /**
+ * Return the last {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated}
+ * {@link AWTGLPixelBuffer}, if compatible w/ the given {@link PixelFormat.Composition} and {@link GLPixelAttributes}.
+ **/
@Override
- public AWTGLPixelBuffer getSingleBuffer(final GLPixelAttributes pixelAttributes) {
- return 4 == pixelAttributes.componentCount ? singleRGBA4 : singleRGB3;
+ public AWTGLPixelBuffer getSingleBuffer(final PixelFormat.Composition hostPixelComp, final GLPixelAttributes pixelAttributes, final boolean pack) {
+ return (AWTGLPixelBuffer) bufferMap.get(getHashCode(hostPixelComp, pixelAttributes, pack));
}
/**
- * Initializes the single {@link AWTGLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, GLPixelAttributes, int, int, int, boolean, int) allocated}.
+ * Initializes the single {@link AWTGLPixelBuffer} w/ a given size, if not yet {@link #allocate(GL, PixelFormat.Composition, GLPixelAttributes, boolean, int, int, int, int) allocated}.
* @return the newly initialized single {@link AWTGLPixelBuffer}, or null if already allocated.
*/
@Override
- public AWTGLPixelBuffer initSingleton(final int componentCount, final int width, final int height, final int depth, final boolean pack) {
- if( 4 == componentCount ) {
- if( null != singleRGBA4 ) {
- return null;
- }
- singleRGBA4 = allocateImpl(AWTGLPixelBuffer.awtPixelAttributesIntRGBA4, width, height, depth, pack, 0);
- return singleRGBA4;
- } else {
- if( null != singleRGB3 ) {
- return null;
- }
- singleRGB3 = allocateImpl(AWTGLPixelBuffer.awtPixelAttributesIntRGB3, width, height, depth, pack, 0);
- return singleRGB3;
+ public AWTGLPixelBuffer initSingleton(final GLProfile glp, final int componentCount,
+ final boolean pack, final int width, final int height, final int depth) {
+ final GLPixelAttributes pixelAttributes = getAttributes(glp, componentCount);
+ final PixelFormat awtPixelFormat = getAWTPixelFormat(glp, componentCount);
+ final int awtFormat = getAWTFormat(glp, componentCount);
+ final int bufferKey = getHashCode(awtPixelFormat.comp, pixelAttributes, pack);
+ AWTGLPixelBuffer r = (AWTGLPixelBuffer) bufferMap.get(bufferKey);
+ if( null != r ) {
+ return null;
+ }
+ r = allocateImpl(awtPixelFormat.comp, pixelAttributes, pack, awtFormat, width, height, depth, 0);
+ bufferMap.put(bufferKey, r);
+ return r;
+ }
+
+ @Override
+ public void dispose() {
+ for(final Iterator<IntObjectHashMap.Entry> i=bufferMap.iterator(); i.hasNext(); ) {
+ final AWTGLPixelBuffer b = (AWTGLPixelBuffer)i.next().value;
+ b.dispose();
}
+ bufferMap.clear();
}
}
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
index 6011afe7b..14fb90662 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
@@ -1125,12 +1125,12 @@ public class TextureIO {
final String fileSuffix) throws IOException {
if (PNG.equals(fileSuffix)) {
final PNGPixelRect image = PNGPixelRect.read(stream, null, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */);
- final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp);
+ final GLPixelAttributes glpa = new GLPixelAttributes(glp, image.getPixelformat(), false /* pack */);
if ( 0 == pixelFormat ) {
pixelFormat = glpa.format;
} // else FIXME: Actually not supported w/ preset pixelFormat!
if ( 0 == internalFormat ) {
- final boolean hasAlpha = 4 == glpa.bytesPerPixel;
+ final boolean hasAlpha = 4 == glpa.pfmt.comp.bytesPerPixel();
if(glp.isGL2ES3()) {
internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8;
} else {
@@ -1351,8 +1351,8 @@ public class TextureIO {
final GLPixelAttributes pixelAttribs = data.getPixelAttributes();
final int pixelFormat = pixelAttribs.format;
final int pixelType = pixelAttribs.type;
- final int bytesPerPixel = pixelAttribs.bytesPerPixel;
- final PixelFormat pixFmt = pixelAttribs.getPixelFormat();
+ final int bytesPerPixel = pixelAttribs.pfmt.comp.bytesPerPixel();
+ final PixelFormat pixFmt = pixelAttribs.pfmt;
if ( ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel) &&
( pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) {
Buffer buf0 = data.getBuffer();
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 8d23d79ff..edd5266b9 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -63,6 +63,7 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.ScalableSurface;
import javax.media.nativewindow.SurfaceUpdatedListener;
import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES3;
@@ -265,12 +266,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
private final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
- // For handling reshape events lazily: reshapeWidth -> panelWidth -> backend.width
+ /** For handling reshape events lazily: reshapeWidth -> panelWidth -> backend.width in pixel units (scaled) */
private int reshapeWidth;
+ /** For handling reshape events lazily: reshapeHeight -> panelHeight -> backend.height in pixel units (scaled) */
private int reshapeHeight;
- // Width of the actual GLJPanel: reshapeWidth -> panelWidth -> backend.width
+ /** Scaled pixel width of the actual GLJPanel: reshapeWidth -> panelWidth -> backend.width */
private int panelWidth = 0;
+ /** Scaled pixel height of the actual GLJPanel: reshapeHeight -> panelHeight -> backend.height */
private int panelHeight = 0;
// These are always set to (0, 0) except when the Java2D / OpenGL
@@ -1882,27 +1885,36 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
alignment = 4;
}
- final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount);
+ final PixelFormat awtPixelFormat = pixelBufferProvider.getAWTPixelFormat(gl.getGLProfile(), componentCount);
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, componentCount, true);
if( useSingletonBuffer ) { // attempt to fetch the latest AWTGLPixelBuffer
- pixelBuffer = (AWTGLPixelBuffer) ((SingletonGLPixelBufferProvider)pixelBufferProvider).getSingleBuffer(pixelAttribs);
+ pixelBuffer = (AWTGLPixelBuffer) ((SingletonGLPixelBufferProvider)pixelBufferProvider).getSingleBuffer(awtPixelFormat.comp, pixelAttribs, true);
}
if( null != pixelBuffer && pixelBuffer.requiresNewBuffer(gl, panelWidth, panelHeight, 0) ) {
pixelBuffer.dispose();
pixelBuffer = null;
alignedImage = null;
}
+ final boolean DEBUG_INIT;
if ( null == pixelBuffer ) {
if (0 >= panelWidth || 0 >= panelHeight ) {
return;
}
- pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, panelWidth, panelHeight, 1, true, 0);
+ pixelBuffer = pixelBufferProvider.allocate(gl, awtPixelFormat.comp, pixelAttribs, true, panelWidth, panelHeight, 1, 0);
if(DEBUG) {
System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" pixelBufferProvider isSingletonBufferProvider "+useSingletonBuffer+", 0x"+Integer.toHexString(pixelBufferProvider.hashCode())+", "+pixelBufferProvider.getClass().getSimpleName());
System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" pixelBuffer 0x"+Integer.toHexString(pixelBuffer.hashCode())+", "+pixelBuffer+", alignment "+alignment);
- System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" flippedVertical "+flipVertical+", glslTextureRaster "+(null!=glslTextureRaster));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" flippedVertical "+flipVertical+", glslTextureRaster "+(null!=glslTextureRaster)+", isGL2ES3 "+gl.isGL2ES3());
System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" panelSize "+panelWidth+"x"+panelHeight+" @ scale "+getPixelScaleStr());
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" pixelAttribs "+pixelAttribs);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: "+GLJPanel.this.getName()+" awtPixelFormat "+awtPixelFormat);
+ DEBUG_INIT = true;
+ } else {
+ DEBUG_INIT = false;
}
+ } else {
+ DEBUG_INIT = false;
}
if( offscreenDrawable.getSurfaceWidth() != panelWidth || offscreenDrawable.getSurfaceHeight() != panelHeight ) {
throw new InternalError("OffscreenDrawable panelSize mismatch (reshape missed): panelSize "+panelWidth+"x"+panelHeight+" != drawable "+offscreenDrawable.getSurfaceWidth()+"x"+offscreenDrawable.getSurfaceHeight()+", on thread "+getThreadName());
@@ -1937,6 +1949,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
final GL2ES3 gl2es3 = gl.getGL2ES3();
psm.setPackRowLength(gl2es3, panelWidth);
gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
+ if( DEBUG_INIT ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.0: fboDrawable "+offscreenDrawable);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.0: isGL2ES3, readBuffer 0x"+Integer.toHexString(gl2es3.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.0: def-readBuffer 0x"+Integer.toHexString(gl2es3.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.0: def-readFBO 0x"+Integer.toHexString(gl2es3.getDefaultReadFramebuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.0: bound-readFBO 0x"+Integer.toHexString(gl2es3.getBoundFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER)));
+ }
}
if(null != glslTextureRaster) { // implies flippedVertical
@@ -1965,9 +1984,26 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// gl.glClear(GL.GL_DEPTH_BUFFER_BIT); // fboFlipped runs w/o DEPTH!
glslTextureRaster.display(gl.getGL2ES2());
+ if( DEBUG_INIT ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: fboDrawable "+fboDrawable);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: read from fbo-rb "+fboFlipped.getReadFramebuffer()+", fbo "+fboFlipped);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: isGL2ES3, readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: def-readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: def-readFBO 0x"+Integer.toHexString(gl.getDefaultReadFramebuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: bound-readFBO 0x"+Integer.toHexString(gl.getBoundFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER)));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.1: "+GLJPanel.this.getName()+" pixelAttribs "+pixelAttribs);
+ }
gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
fboFlipped.unbind(gl);
+ if( DEBUG_INIT ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: fboDrawable "+fboDrawable);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: read from fbo-rb "+fboFlipped.getReadFramebuffer()+", fbo "+fboFlipped);
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: isGL2ES3, readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: def-readBuffer 0x"+Integer.toHexString(gl.getDefaultReadBuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: def-readFBO 0x"+Integer.toHexString(gl.getDefaultReadFramebuffer()));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0.2: bound-readFBO 0x"+Integer.toHexString(gl.getBoundFramebuffer(GL2ES3.GL_READ_FRAMEBUFFER)));
+ }
if( viewportChange ) {
gl.glViewport(usrViewport[0], usrViewport[1], usrViewport[2], usrViewport[3]);
}
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java
index a5f5b4702..b6fa68600 100644
--- a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java
+++ b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java
@@ -46,6 +46,7 @@ import java.util.Map.Entry;
import javax.imageio.ImageIO;
import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilitiesImmutable;
@@ -288,8 +289,9 @@ public class AWTTilePainter {
final int tWidth = renderer.getParam(TileRenderer.TR_TILE_WIDTH);
final int tHeight = renderer.getParam(TileRenderer.TR_TILE_HEIGHT);
final AWTGLPixelBufferProvider printBufferProvider = new AWTGLPixelBufferProvider( true /* allowRowStride */ );
- final GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, componentCount);
- tBuffer = printBufferProvider.allocate(gl, pixelAttribs, tWidth, tHeight, 1, true, 0);
+ final PixelFormat.Composition hostPixelComp = printBufferProvider.getHostPixelComp(gl.getGLProfile(), componentCount);
+ final GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, componentCount, true);
+ tBuffer = printBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, tWidth, tHeight, 1, 0);
renderer.setTileBuffer(tBuffer);
if( flipVertical ) {
vFlipImage = new BufferedImage(tBuffer.width, tBuffer.height, tBuffer.image.getType());
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java
index c7055099f..0f103bfb3 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java
@@ -36,6 +36,7 @@ import java.awt.image.DirectColorModel;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
+import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Hashtable;
@@ -54,9 +55,12 @@ public final class DirectDataBufferInt extends DataBuffer {
public static class BufferedImageInt extends BufferedImage {
final int customImageType;
- public BufferedImageInt (final int customImageType, final ColorModel cm, final WritableRaster raster, final Hashtable<?,?> properties) {
+ final DirectDataBufferInt dataBuffer;
+ public BufferedImageInt (final int customImageType, final ColorModel cm,
+ final DirectDataBufferInt dataBuffer, final WritableRaster raster, final Hashtable<?,?> properties) {
super(cm, raster, false /* isRasterPremultiplied */, properties);
this.customImageType = customImageType;
+ this.dataBuffer = dataBuffer;
}
/**
@@ -68,6 +72,11 @@ public final class DirectDataBufferInt extends DataBuffer {
return customImageType;
}
+ /**
+ * Returns the underlying {@link DirectDataBufferInt} associated with this instance via {@link Raster} {@link #getRaster() instance}.
+ */
+ public DirectDataBufferInt getDataBuffer() { return dataBuffer; }
+
@Override
public String toString() {
return "BufferedImageInt@"+Integer.toHexString(hashCode())
@@ -163,14 +172,18 @@ public final class DirectDataBufferInt extends DataBuffer {
// final WritableRaster raster = new SunWritableRaster(sppsm, dataBuffer, location);
final WritableRaster raster = new DirectWritableRaster(sppsm, dataBuffer, location);
- return new BufferedImageInt(imageType, colorModel, raster, properties);
+ return new BufferedImageInt(imageType, colorModel, dataBuffer, raster, properties);
}
- /** Default data bank. */
- private final IntBuffer data;
+ /** Default NIO data bank storage, {@link ByteBuffer} representation. */
+ private final ByteBuffer dataBytes;
+ /** Default NIO data bank storage, {@link IntBuffer} representation. */
+ private final IntBuffer dataInts;
- /** All data banks */
- private final IntBuffer bankdata[];
+ /** All NIO data banks, {@link ByteBuffer} representation. */
+ private final ByteBuffer bankdataBytes[];
+ /** All NIO data banks, {@link IntBuffer} representation. */
+ private final IntBuffer bankdataInts[];
/**
* Constructs an nio integer-based {@link DataBuffer} with a single bank
@@ -180,9 +193,12 @@ public final class DirectDataBufferInt extends DataBuffer {
*/
public DirectDataBufferInt(final int size) {
super(TYPE_INT, size);
- data = Buffers.newDirectIntBuffer(size);
- bankdata = new IntBuffer[1];
- bankdata[0] = data;
+ dataBytes = Buffers.newDirectByteBuffer(size * Buffers.SIZEOF_INT);
+ dataInts = dataBytes.asIntBuffer();
+ bankdataBytes = new ByteBuffer[1];
+ bankdataInts = new IntBuffer[1];
+ bankdataBytes[0] = dataBytes;
+ bankdataInts[0] = dataInts;
}
/**
@@ -194,11 +210,14 @@ public final class DirectDataBufferInt extends DataBuffer {
*/
public DirectDataBufferInt(final int size, final int numBanks) {
super(TYPE_INT,size,numBanks);
- bankdata = new IntBuffer[numBanks];
+ bankdataBytes = new ByteBuffer[numBanks];
+ bankdataInts = new IntBuffer[numBanks];
for (int i= 0; i < numBanks; i++) {
- bankdata[i] = Buffers.newDirectIntBuffer(size);
+ bankdataBytes[i] = Buffers.newDirectByteBuffer(size * Buffers.SIZEOF_INT);
+ bankdataInts[i] = bankdataBytes[i].asIntBuffer();
}
- data = bankdata[0];
+ dataBytes = bankdataBytes[0];
+ dataInts = bankdataInts[0];
}
/**
@@ -210,33 +229,57 @@ public final class DirectDataBufferInt extends DataBuffer {
* hold <code>size</code> elements.
* </p>
*
- * @param dataArray The integer array for the {@link DataBuffer}.
+ * @param dataArray The NIO {@link ByteBuffer} array, holding the integer data for the {@link DataBuffer}.
* @param size The size of the {@link DataBuffer} bank.
*/
- public DirectDataBufferInt(final IntBuffer dataArray, final int size) {
+ public DirectDataBufferInt(final ByteBuffer dataArray, final int size) {
super(TYPE_INT,size);
- data = dataArray;
- bankdata = new IntBuffer[1];
- bankdata[0] = data;
+ dataBytes = Buffers.nativeOrder(dataArray);
+ dataInts = dataBytes.asIntBuffer();
+ bankdataBytes = new ByteBuffer[1];
+ bankdataInts = new IntBuffer[1];
+ bankdataBytes[0] = dataBytes;
+ bankdataInts[0] = dataInts;
}
/**
- * Returns the default (first) int data array in {@link DataBuffer}.
+ * Returns the default (first) int data array in {@link DataBuffer} as an {@link IntBuffer} representation.
*
* @return The first integer data array.
+ * @see #getDataBytes()
*/
public IntBuffer getData() {
- return data;
+ return dataInts;
+ }
+ /**
+ * Returns the default (first) int data array in {@link DataBuffer} as a {@link ByteBuffer} representation.
+ *
+ * @return The first integer data array.
+ * @see #getData()
+ */
+ public ByteBuffer getDataBytes() {
+ return dataBytes;
}
/**
- * Returns the data array for the specified bank.
+ * Returns the data array for the specified bank as an {@link IntBuffer} representation.
*
* @param bank The bank whose data array you want to get.
* @return The data array for the specified bank.
+ * @see #getDataBytes(int)
*/
public IntBuffer getData(final int bank) {
- return bankdata[bank];
+ return bankdataInts[bank];
+ }
+ /**
+ * Returns the data array for the specified bank as a {@link ByteBuffer} representation.
+ *
+ * @param bank The bank whose data array you want to get.
+ * @return The data array for the specified bank.
+ * @see #getData(int)
+ */
+ public ByteBuffer getDataBytes(final int bank) {
+ return bankdataBytes[bank];
}
/**
@@ -249,7 +292,7 @@ public final class DirectDataBufferInt extends DataBuffer {
*/
@Override
public int getElem(final int i) {
- return data.get(i+offset);
+ return dataInts.get(i+offset);
}
/**
@@ -263,7 +306,7 @@ public final class DirectDataBufferInt extends DataBuffer {
*/
@Override
public int getElem(final int bank, final int i) {
- return bankdata[bank].get(i+offsets[bank]);
+ return bankdataInts[bank].get(i+offsets[bank]);
}
/**
@@ -277,7 +320,7 @@ public final class DirectDataBufferInt extends DataBuffer {
*/
@Override
public void setElem(final int i, final int val) {
- data.put(i+offset, val);
+ dataInts.put(i+offset, val);
}
/**
@@ -291,7 +334,7 @@ public final class DirectDataBufferInt extends DataBuffer {
*/
@Override
public void setElem(final int bank, final int i, final int val) {
- bankdata[bank].put(i+offsets[bank], val);
+ bankdataInts[bank].put(i+offsets[bank], val);
}
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java
index e5901f584..2016b2885 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java
@@ -28,6 +28,10 @@
package javax.media.nativewindow.util;
+import java.util.Arrays;
+
+import com.jogamp.common.util.IntBitfield;
+
/**
* Basic pixel formats
* <p>
@@ -60,7 +64,7 @@ package javax.media.nativewindow.util;
*/
public enum PixelFormat {
/**
- * Pixel size is 1 bytes (8 bits) with one component of size 1 byte (8 bits).
+ * Stride is 8 bits, 8 bits per pixel, 1 component of 8 bits.
* Compatible with:
* <ul>
* <li>OpenGL: data-format GL_ALPHA (< GL3), GL_RED (>= GL3), data-type GL_UNSIGNED_BYTE</li>
@@ -68,34 +72,138 @@ public enum PixelFormat {
* </ul>
* </p>
*/
- LUMINANCE(1, 8),
+ LUMINANCE(new CType[]{ CType.Y }, 1, 8, 8),
/**
- * Pixel size is 3 bytes (24 bits) with each component of size 1 byte (8 bits).
+ * Stride is 16 bits, 16 bits per pixel, 3 {@link PackedComposition#isUniform() discrete} components.
+ * <p>
+ * The {@link PackedComposition#isUniform() discrete} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>R: 0x1F << 0</li>
+ * <li>G: 0x3F << 5</li>
+ * <li>B: 0x1F << 11</li>
+ * </ol>
+ * </p>
* <p>
- * The components are interleaved in the order:
+ * Compatible with:
* <ul>
- * <li>Low to High: R, G, B</li>
+ * <li>OpenGL: data-format GL_RGB, data-type GL_UNSIGNED_SHORT_5_6_5_REV</li>
+ * <li>AWT: <i>None</i></li>
* </ul>
* </p>
+ */
+ RGB565(new CType[]{ CType.R, CType.G, CType.B },
+ new int[]{ 0x1F, 0x3F, 0x1F },
+ new int[]{ 0, 5, 5+6 },
+ 16 ),
+
+ /**
+ * Stride is 16 bits, 16 bits per pixel, 3 {@link PackedComposition#isUniform() discrete} components.
+ * <p>
+ * The {@link PackedComposition#isUniform() discrete} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>B: 0x1F << 0</li>
+ * <li>G: 0x3F << 5</li>
+ * <li>R: 0x1F << 11</li>
+ * </ol>
+ * </p>
* <p>
* Compatible with:
* <ul>
- * <li>OpenGL: data-format GL_RGB, data-type GL_UNSIGNED_BYTE</li>
+ * <li>OpenGL: data-format GL_RGB, data-type GL_UNSIGNED_SHORT_5_6_5</li>
+ * <li>AWT: <i>None</i></li>
+ * </ul>
+ * </p>
+ */
+ BGR565(new CType[]{ CType.B, CType.G, CType.R},
+ new int[]{ 0x1F, 0x3F, 0x1F },
+ new int[]{ 0, 5, 5+6 },
+ 16 ),
+
+ /**
+ * Stride is 16 bits, 16 bits per pixel, 4 {@link PackedComposition#isUniform() discrete} components.
+ * <p>
+ * The {@link PackedComposition#isUniform() discrete} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>R: 0x1F << 0</li>
+ * <li>G: 0x1F << 5</li>
+ * <li>B: 0x1F << 10</li>
+ * <li>A: 0x01 << 15</li>
+ * </ol>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_SHORT_1_5_5_5_REV</li>
+ * <li>AWT: <i>None</i></li>
+ * </ul>
+ * </p>
+ */
+ RGBA5551(new CType[]{ CType.R, CType.G, CType.B, CType.A},
+ new int[]{ 0x1F, 0x1F, 0x1F, 0x01 },
+ new int[]{ 0, 5, 5+5, 5+5+5 },
+ 16 ),
+
+ /**
+ * Stride is 16 bits, 16 bits per pixel, 4 {@link PackedComposition#isUniform() discrete} components.
+ * <p>
+ * The {@link PackedComposition#isUniform() discrete} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>A: 0x01 << 0</li>
+ * <li>B: 0x1F << 1</li>
+ * <li>G: 0x1F << 6</li>
+ * <li>R: 0x1F << 11</li>
+ * </ol>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_SHORT_5_5_5_1</li>
* <li>AWT: <i>None</i></li>
* </ul>
* </p>
*/
- RGB888(3, 24),
+ ABGR1555(new CType[]{ CType.A, CType.B, CType.G, CType.R },
+ new int[]{ 0x01, 0x1F, 0x1F, 0x1F },
+ new int[]{ 0, 1, 1+5, 1+5+5 },
+ 16 ),
/**
- * Pixel size is 3 bytes (24 bits) with each component of size 1 byte (8 bits).
+ * Stride 24 bits, 24 bits per pixel, 3 {@link PackedComposition#isUniform() uniform} components of 8 bits.
+ * <p>
+ * The {@link PackedComposition#isUniform() uniform} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>R: 0xFF << 0</li>
+ * <li>G: 0xFF << 8</li>
+ * <li>B: 0xFF << 16</li>
+ * </ol>
+ * </p>
* <p>
- * The components are interleaved in the order:
+ * Compatible with:
* <ul>
- * <li>Low to High: B, G, R</li>
+ * <li>OpenGL: data-format GL_RGB, data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: <i>None</i></li>
* </ul>
* </p>
+ */
+ RGB888(new CType[]{ CType.R, CType.G, CType.B }, 3, 8, 24),
+
+ /**
+ * Stride is 24 bits, 24 bits per pixel, 3 {@link PackedComposition#isUniform() uniform} components of of 8 bits.
+ * <p>
+ * The {@link PackedComposition#isUniform() uniform} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>B: 0xFF << 0</li>
+ * <li>G: 0xFF << 8</li>
+ * <li>R: 0xFF << 16</li>
+ * </ol>
+ * </p>
* <p>
* Compatible with:
* <ul>
@@ -104,16 +212,62 @@ public enum PixelFormat {
* </ul>
* </p>
*/
- BGR888(3, 24),
+ BGR888(new CType[]{ CType.B, CType.G, CType.R }, 3, 8, 24),
+
+ /**
+ * Stride is 32 bits, 24 bits per pixel, 3 {@link PackedComposition#isUniform() uniform} components of 8 bits.
+ * <p>
+ * The {@link PackedComposition#isUniform() uniform} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>R: 0xFF << 0</li>
+ * <li>G: 0xFF << 8</li>
+ * <li>B: 0xFF << 16</li>
+ * </ol>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_BYTE, with alpha discarded!</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_INT_BGR TYPE_INT_BGR}</li>
+ * </ul>
+ * </p>
+ */
+ RGBx8888(new CType[]{ CType.R, CType.G, CType.B }, 3, 8, 32),
/**
- * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * Stride is 32 bits, 24 bits per pixel, 3 {@link PackedComposition#isUniform() uniform} components of 8 bits.
+ * <p>
+ * The {@link PackedComposition#isUniform() uniform} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>B: 0xFF << 0</li>
+ * <li>G: 0xFF << 8</li>
+ * <li>R: 0xFF << 16</li>
+ * </ol>
+ * </p>
* <p>
- * The components are interleaved in the order:
+ * Compatible with:
* <ul>
- * <li>Low to High: R, G, B, A</li>
+ * <li>OpenGL: data-format GL_BGRA, data-type GL_UNSIGNED_BYTE - with alpha discarded!</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_INT_RGB TYPE_INT_RGB}</li>
* </ul>
* </p>
+ */
+ BGRx8888(new CType[]{ CType.B, CType.G, CType.R }, 3, 8, 32),
+
+ /**
+ * Stride is 32 bits, 32 bits per pixel, 4 {@link PackedComposition#isUniform() uniform} components of 8 bits.
+ * <p>
+ * The {@link PackedComposition#isUniform() uniform} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>R: 0xFF << 0</li>
+ * <li>G: 0xFF << 8</li>
+ * <li>B: 0xFF << 16</li>
+ * <li>A: 0xFF << 24</li>
+ * </ol>
+ * </p>
* <p>
* Compatible with:
* <ul>
@@ -125,33 +279,41 @@ public enum PixelFormat {
* </ul>
* </p>
*/
- RGBA8888(4, 32),
+ RGBA8888(new CType[]{ CType.R, CType.G, CType.B, CType.A }, 4, 8, 32),
/**
- * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * Stride is 32 bits, 32 bits per pixel, 4 {@link PackedComposition#isUniform() uniform} components of 8 bits.
* <p>
- * The components are interleaved in the order:
- * <ul>
- * <li>Low to High: A, B, G, R</li>
- * </ul>
+ * The {@link PackedComposition#isUniform() uniform} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>A: 0xFF << 0</li>
+ * <li>B: 0xFF << 8</li>
+ * <li>G: 0xFF << 16</li>
+ * <li>R: 0xFF << 24</li>
+ * </ol>
* </p>
* <p>
* Compatible with:
* <ul>
- * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_8_8_8_8</li>
+ * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_INT_8_8_8_8</li>
* <li>AWT: {@link java.awt.image.BufferedImage#TYPE_4BYTE_ABGR TYPE_4BYTE_ABGR}</li>
* </ul>
* </p>
*/
- ABGR8888(4, 32),
+ ABGR8888(new CType[]{ CType.A, CType.B, CType.G, CType.R }, 4, 8, 32),
/**
- * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * Stride is 32 bits, 32 bits per pixel, 4 {@link PackedComposition#isUniform() uniform} components of 8 bits.
* <p>
- * The components are interleaved in the order:
- * <ul>
- * <li>Low to High: A, R, G, B</li>
- * </ul>
+ * The {@link PackedComposition#isUniform() uniform} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>A: 0xFF << 0</li>
+ * <li>R: 0xFF << 8</li>
+ * <li>G: 0xFF << 16</li>
+ * <li>B: 0xFF << 24</li>
+ * </ol>
* </p>
* <p>
* Compatible with:
@@ -161,15 +323,19 @@ public enum PixelFormat {
* </ul>
* </p>
*/
- ARGB8888(4, 32),
+ ARGB8888(new CType[]{ CType.A, CType.R, CType.G, CType.B }, 4, 8, 32),
/**
- * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * Stride is 32 bits, 32 bits per pixel, 4 {@link PackedComposition#isUniform() uniform} components of 8 bits.
* <p>
- * The components are interleaved in the order:
- * <ul>
- * <li>Low to High: B, G, R, A</li>
- * </ul>
+ * The {@link PackedComposition#isUniform() uniform} {@link PixelFormat#composition components}
+ * are interleaved in the order Low to High:
+ * <ol>
+ * <li>B: 0xFF << 0</li>
+ * <li>G: 0xFF << 8</li>
+ * <li>R: 0xFF << 16</li>
+ * <li>A: 0xFF << 24</li>
+ * </ol>
* </p>
* <p>
* Compatible with:
@@ -181,17 +347,393 @@ public enum PixelFormat {
* </ul>
* </p>
*/
- BGRA8888(4, 32);
+ BGRA8888(new CType[]{ CType.B, CType.G, CType.R, CType.A }, 4, 8, 32);
+
+ /** Unique {@link Composition Pixel Composition}, i.e. layout of its components. */
+ public final Composition comp;
+
+ /**
+ * @param componentOrder {@link CType Component type} order of all components, see {@link Composition#componentBitMask()}.
+ * @param componentCount number of components
+ * @param bpc bits per component
+ * @param bitStride stride bits to next pixel
+ */
+ private PixelFormat(final CType[] componentOrder, final int componentCount, final int bpc, final int bitStride) {
+ this.comp = new PackedComposition(componentOrder, componentCount, bpc, bitStride);
+ }
+
+ /**
+ * @param componentOrder {@link CType Component type} order of all components, see {@link Composition#componentBitMask()}.
+ * @param componentMask bit-mask of of all components, see {@link Composition##componentBitMask()}.
+ * @param componentBitShift bit-shift of all components, see {@link Composition##componentBitMask()}.
+ * @param bitStride stride bits to next pixel
+ */
+ private PixelFormat(final CType[] componentOrder, final int[] componentMask, final int[] componentBitShift, final int bitStride) {
+ this.comp = new PackedComposition(componentOrder, componentMask, componentBitShift, bitStride);
+ }
+
+ /**
+ * Returns the unique matching {@link PixelFormat} of the given {@link Composition}
+ * or {@code null} if none is available.
+ */
+ public static PixelFormat valueOf(final Composition comp) {
+ final PixelFormat[] all = PixelFormat.values();
+ for(int i=all.length-1; i>=0; i--) {
+ final PixelFormat pf = all[i];
+ if( comp.hashCode() == pf.comp.hashCode() && comp.equals(pf.comp) ) {
+ return pf;
+ }
+ }
+ return null;
+ }
+
+ /** Component types */
+ public static enum CType {
+ /** Red component */
+ R,
+ /** Green component */
+ G,
+ /** Blue component */
+ B,
+ /** Alpha component */
+ A,
+ /** Luminance component, e.g. grayscale or Y of YUV */
+ Y,
+ /** U component of YUV */
+ U,
+ /** V component of YUV */
+ V;
+ }
+
+ /**
+ * Pixel composition, i.e. layout of its components.
+ */
+ public static interface Composition {
+ /** {@value} */
+ public static final int UNDEF = -1;
+
+ /**
+ * Returns {@code true} if all components are of same bit-size, e.g. {@link PixelFormat#RGBA8888 RGBA8888},
+ * otherwise {@code false}, e.g. {@link PixelFormat#RGBA5551 RGBA5551}
+ */
+ boolean isUniform();
+
+ /**
+ * Returns {@code true} if all components are packed, i.e. interleaved, e.g. {@link PixelFormat#RGBA8888 RGBA8888},
+ * otherwise {@code false}.
+ */
+ boolean isInterleaved();
+
+ /** Number of components per pixel, e.g. 3 for {@link PixelFormat#RGBx8888 RGBx8888}. */
+ int componenCount();
+ /** Number of bits per pixel, e.g. 24 bits for {@link PixelFormat#RGBx8888 RGBx8888}. */
+ int bitsPerPixel();
+ /**
+ * Bit distance between pixels.
+ * <p>
+ * For packed pixels e.g. 32 bits for {@link PixelFormat#RGBx8888 RGBx8888}.
+ * </p>
+ */
+ int bitStride();
+ /** Number of bytes per pixel, i.e. packed {@link #bitStride()} in bytes, e.g. 4 for {@link PixelFormat#RGBx8888 RGBx8888}. */
+ int bytesPerPixel();
+ /**
+ * Returns the {@link CType Component type} order of all components, see {@link #componentBitMask()}.
+ */
+ CType[] componentOrder();
+ /**
+ * Returns the index of given {@link CType} within {@link #componentOrder()}, -1 if not exists.
+ */
+ int find(final PixelFormat.CType s);
+ /**
+ * Returns the un-shifted bit-mask of all components.
+ * <p>
+ * Components mask is returned in the order Low-Index to High-Index, e.g.:
+ * <ul>
+ * <li>{@link PixelFormat#RGB565 RGB565}: 0: R 0x1F, 1: G 0x3F, 2: B 0x1F</li>
+ * <li>{@link PixelFormat#RGBA5551 RGBA5551}: 0: R 0x1F, 1: G 0x1F, 2: B 0x1F, 3: A 0x01</li>
+ * <li>{@link PixelFormat#RGBA8888 RGBA8888}: 0: R 0xFF, 1: G 0xFF, 2: B 0xFF, 3: A 0xFF</li>
+ * </ul>
+ * </p>
+ * <p>
+ */
+ int[] componentBitMask();
+ /**
+ * Returns the number of bits of all components, see {@link #componentBitMask()}.
+ */
+ int[] componentBitCount();
+ /**
+ * Returns the bit-shift of all components, see {@link #componentBitMask()}.
+ */
+ int[] componentBitShift();
+
+ /**
+ * Decodes a component from the shifted pixel data with a {@link #bytesPerPixel()} of up to 32bit.
+ * @param shifted complete pixel encoded into on 32bit integer
+ * @param cIdx the desired component index
+ * @return the decoded component value
+ */
+ int decodeSingleI32(final int shifted, final int cIdx);
+ /**
+ * Decodes a component from the shifted pixel data with a {@link #bytesPerPixel()} of up to 64bit.
+ * @param shifted complete pixel encoded into on 64bit integer
+ * @param cIdx the desired component index
+ * @return the decoded component value
+ */
+ int decodeSingleI64(final long shifted, final int cIdx);
+
+ int encodeSingleI32(final int norm, final int cIdx);
+ long encodeSingleI64(final int norm, final int cIdx);
+
+ int encode3CompI32(final int c1NormI32, final int c2NormI32, final int c3NormI32);
+ int encode4CompI32(final int c1NormI32, final int c2NormI32, final int c3NormI32, final int c4NormI32);
+
+ int encodeSingleI8(final byte normalI8, final int cIdx);
+ int encode3CompI8(final byte c1NormI8, final byte c2NormI8, final byte c3NormI8);
+ int encode4CompI8(final byte c1NormI8, final byte c2NormI8, final byte c3NormI8, final byte c4NormI8);
+
+ float toFloat(final int i32, final int cIdx, final boolean i32Shifted);
+ int fromFloat(final float f, final int cIdx, final boolean shiftResult);
+
+ int defaultValue(final int cIdx, final boolean shiftResult);
+
+ /**
+ * Returns cached immutable hash value, see {@link Object#hashCode()}.
+ */
+ int hashCode();
+ /**
+ * Returns {@link Object#equals(Object)}
+ */
+ boolean equals(final Object o);
+
+ /**
+ * Returns {@link Object#toString()}.
+ */
+ String toString();
+ }
+
+ /**
+ * Packed pixel composition, see {@link Composition}.
+ * <p>
+ * Components are interleaved, i.e. packed.
+ * </p>
+ */
+ public static class PackedComposition implements Composition {
+ private final CType[] compOrder;
+ private final int[] compMask;
+ private final int[] compBitCount;
+ private final int[] compBitShift;
+ private final int bitsPerPixel;
+ private final int bitStride;
+ private final boolean uniform;
+ private final int hashCode;
+
+ public final String toString() {
+ return String.format("PackedComp[order %s, stride %d, bpp %d, uni %b, comp %d: %s]",
+ Arrays.toString(compOrder), bitStride, bitsPerPixel, uniform,
+ compMask.length, toHexString(compBitCount, compMask, compBitShift));
+ }
+
+ /**
+ * @param componentOrder {@link CType Component type} order of all components, see {@link #componentBitMask()}.
+ * @param componentCount number of components
+ * @param bpc bits per component
+ * @param bitStride stride bits to next pixel
+ */
+ public PackedComposition(final CType[] componentOrder, final int componentCount, final int bpc, final int bitStride) {
+ this.compOrder = componentOrder;
+ this.compMask = new int[componentCount];
+ this.compBitShift = new int[componentCount];
+ this.compBitCount = new int[componentCount];
+ final int compMask = ( 1 << bpc ) - 1;
+ for(int i=0; i<componentCount; i++) {
+ this.compMask[i] = compMask;
+ this.compBitShift[i] = bpc * i;
+ this.compBitCount[i] = bpc;
+ }
+ this.uniform = true;
+ this.bitsPerPixel = bpc * componentCount;
+ this.bitStride = bitStride;
+ if( this.bitStride < this.bitsPerPixel ) {
+ throw new IllegalArgumentException(String.format("bit-stride %d < bitsPerPixel %d", this.bitStride, this.bitsPerPixel));
+ }
+ this.hashCode = hashCodeImpl();
+ }
- /** Number of components per pixel, e.g. 4 for RGBA. */
- public final int componentCount;
- /** Number of bits per pixel, e.g. 32 for RGBA. */
- public final int bitsPerPixel;
- /** Number of bytes per pixel, e.g. 4 for RGBA. */
- public final int bytesPerPixel() { return (7+bitsPerPixel)/8; }
+ /**
+ * @param componentOrder {@link CType Component type} order of all components, see {@link #componentBitMask()}.
+ * @param componentMask bit-mask of of all components, see {@link #componentBitMask()}.
+ * @param componentBitShift bit-shift of all components, see {@link #componentBitMask()}.
+ * @param bitStride stride bits to next pixel
+ */
+ public PackedComposition(final CType[] componentOrder, final int[] componentMask, final int[] componentBitShift, final int bitStride) {
+ this.compOrder = componentOrder;
+ this.compMask = componentMask;
+ this.compBitShift = componentBitShift;
+ this.compBitCount = new int[componentMask.length];
+ int bpp = 0;
+ boolean uniform = true;
+ for(int i = componentMask.length-1; i>=0; i--) {
+ final int cmask = componentMask[i];
+ final int bitCount = IntBitfield.getBitCount(cmask);
+ bpp += bitCount;
+ this.compBitCount[i] = bitCount;
+ if( i > 0 && uniform ) {
+ uniform = componentMask[i-1] == cmask;
+ }
+ }
+ this.uniform = uniform;
+ this.bitsPerPixel = bpp;
+ this.bitStride = bitStride;
+ if( this.bitStride < this.bitsPerPixel ) {
+ throw new IllegalArgumentException(String.format("bit-stride %d < bitsPerPixel %d", this.bitStride, this.bitsPerPixel));
+ }
+ this.hashCode = hashCodeImpl();
+ }
+
+ @Override
+ public final boolean isUniform() { return uniform; }
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Instances of {@link PackedComposition} returns {@code true}.
+ * </p>
+ */
+ @Override
+ public final boolean isInterleaved() { return true; }
+ @Override
+ public final int componenCount() { return compMask.length; }
+ @Override
+ public final int bitsPerPixel() { return bitsPerPixel; }
+ @Override
+ public final int bitStride() { return bitStride; }
+ @Override
+ public final int bytesPerPixel() { return (7+bitStride)/8; }
+ @Override
+ public final CType[] componentOrder() { return compOrder; }
+ @Override
+ public final int find(final PixelFormat.CType s) { return PixelFormatUtil.find(s, compOrder, false /* mapRGB2Y */); }
+ @Override
+ public final int[] componentBitMask() { return compMask; }
+ @Override
+ public final int[] componentBitCount() { return compBitCount; }
+ @Override
+ public final int[] componentBitShift() { return compBitShift; }
+
+ @Override
+ public final int decodeSingleI32(final int shifted, final int cIdx) {
+ return ( shifted >>> compBitShift[cIdx] ) & compMask[cIdx];
+ }
+ @Override
+ public final int decodeSingleI64(final long shifted, final int cIdx) {
+ return ( (int)( 0xffffffffL & ( shifted >>> compBitShift[cIdx] ) ) ) & compMask[cIdx];
+ }
+ @Override
+ public final int encodeSingleI32(final int norm, final int cIdx) {
+ return ( norm & compMask[cIdx] ) << compBitShift[cIdx] ;
+ }
+ @Override
+ public final long encodeSingleI64(final int norm, final int cIdx) {
+ return ( 0xffffffffL & ( norm & compMask[cIdx] ) ) << compBitShift[cIdx] ;
+ }
+ @Override
+ public final int encode3CompI32(final int c1NormI32, final int c2NormI32, final int c3NormI32) {
+ return ( c1NormI32 & compMask[0] ) << compBitShift[0] |
+ ( c2NormI32 & compMask[1] ) << compBitShift[1] |
+ ( c3NormI32 & compMask[2] ) << compBitShift[2] ;
+ }
+ @Override
+ public final int encode4CompI32(final int c1NormI32, final int c2NormI32, final int c3NormI32, final int c4NormI32) {
+ return ( c1NormI32 & compMask[0] ) << compBitShift[0] |
+ ( c2NormI32 & compMask[1] ) << compBitShift[1] |
+ ( c3NormI32 & compMask[2] ) << compBitShift[2] |
+ ( c4NormI32 & compMask[3] ) << compBitShift[3] ;
+ }
+ @Override
+ public final int encodeSingleI8(final byte normI8, final int cIdx) {
+ return ( normI8 & compMask[cIdx] ) << compBitShift[cIdx] ;
+ }
+ @Override
+ public final int encode3CompI8(final byte c1NormI8, final byte c2NormI8, final byte c3NormI8) {
+ return ( c1NormI8 & compMask[0] ) << compBitShift[0] |
+ ( c2NormI8 & compMask[1] ) << compBitShift[1] |
+ ( c3NormI8 & compMask[2] ) << compBitShift[2] ;
+ }
+ @Override
+ public final int encode4CompI8(final byte c1NormI8, final byte c2NormI8, final byte c3NormI8, final byte c4NormI8) {
+ return ( c1NormI8 & compMask[0] ) << compBitShift[0] |
+ ( c2NormI8 & compMask[1] ) << compBitShift[1] |
+ ( c3NormI8 & compMask[2] ) << compBitShift[2] |
+ ( c4NormI8 & compMask[3] ) << compBitShift[3] ;
+ }
+
+ @Override
+ public final float toFloat(final int i32, final int cIdx, final boolean i32Shifted) {
+ if( i32Shifted ) {
+ return ( ( i32 >>> compBitShift[cIdx] ) & compMask[cIdx] ) / (float)( compMask[cIdx] ) ;
+ } else {
+ return ( i32 & compMask[cIdx] ) / (float)( compMask[cIdx] ) ;
+ }
+ }
+ @Override
+ public final int fromFloat(final float f, final int cIdx, final boolean shiftResult) {
+ final int v = (int)(f * compMask[cIdx] + 0.5f);
+ return shiftResult ? v << compBitShift[cIdx] : v;
+ }
+
+ @Override
+ public final int defaultValue(final int cIdx, final boolean shiftResult) {
+ final int v = ( CType.A == compOrder[cIdx] || CType.Y == compOrder[cIdx] )
+ ? compMask[cIdx] : 0;
+ return shiftResult ? v << compBitShift[cIdx] : v;
+ }
+
+ @Override
+ public final int hashCode() { return hashCode; }
+ private final int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + bitStride;
+ hash = ((hash << 5) - hash) + bitsPerPixel;
+ hash = ((hash << 5) - hash) + compMask.length;
+ for(int i=compOrder.length-1; i>=0; i--) {
+ hash = ((hash << 5) - hash) + compOrder[i].ordinal();
+ }
+ for(int i=compMask.length-1; i>=0; i--) {
+ hash = ((hash << 5) - hash) + compMask[i];
+ }
+ for(int i=compBitShift.length-1; i>=0; i--) {
+ hash = ((hash << 5) - hash) + compBitShift[i];
+ }
+ return hash;
+ }
+
+ @Override
+ public final boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if( obj instanceof PackedComposition ) {
+ final PackedComposition other = (PackedComposition) obj;
+ return bitStride == other.bitStride &&
+ bitsPerPixel == other.bitsPerPixel &&
+ Arrays.equals(compOrder, other.compOrder) &&
+ Arrays.equals(compMask, other.compMask) &&
+ Arrays.equals(compBitShift, other.compBitShift);
+ } else {
+ return false;
+ }
+ }
+ }
- private PixelFormat(final int componentCount, final int bpp) {
- this.componentCount = componentCount;
- this.bitsPerPixel = bpp;
+ private static String toHexString(final int[] bitCount, final int[] mask, final int[] shift) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ final int l = mask.length;
+ for(int i=0; i < l; i++) {
+ if(i > 0) {
+ sb.append(", ");
+ }
+ sb.append(bitCount[i]).append(": ").
+ append("0x").append(Integer.toHexString(mask[i])).append(" << ").append(shift[i]);
+ }
+ return sb.append("]").toString();
}
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
index 21bfa8a54..a449f8706 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
@@ -27,10 +27,12 @@
*/
package javax.media.nativewindow.util;
+import java.io.IOException;
import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
+import java.util.Arrays;
import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.Bitstream;
/**
* Pixel Rectangle Utilities.
@@ -39,46 +41,157 @@ import com.jogamp.common.nio.Buffers;
* </p>
*/
public class PixelFormatUtil {
- public static interface PixelSink {
- /** Return the sink's destination pixelformat. */
- PixelFormat getPixelformat();
+ private static boolean DEBUG = false;
+ public static class ComponentMap {
/**
- * Returns stride in byte-size, i.e. byte count from one line to the next.
- * <p>
- * Must be >= {@link #getPixelformat()}.{@link PixelFormat#bytesPerPixel() bytesPerPixel()} * {@link #getSize()}.{@link DimensionImmutable#getWidth() getWidth()}.
- * </p>
+ * Contains the source index for each destination index,
+ * length is {@link Composition#componenCount()} of destination.
*/
- int getStride();
+ final int[] dst2src;
+ /**
+ * Contains the destination index for each source index,
+ * length is {@link Composition#componenCount()} of source.
+ */
+ final int[] src2dst;
/**
- * Returns <code>true</code> if the sink's memory is laid out in
- * OpenGL's coordinate system, <i>origin at bottom left</i>.
- * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
+ * Contains the source index of RGBA components.
*/
- boolean isGLOriented();
+ final int[] srcRGBA;
+ final boolean hasSrcRGB;
+
+ public ComponentMap(final PixelFormat.Composition src, final PixelFormat.Composition dst) {
+ final int sCompCount = src.componenCount();
+ final int dCompCount = dst.componenCount();
+ final PixelFormat.CType[] sCompOrder = src.componentOrder();
+ final PixelFormat.CType[] dCompOrder = dst.componentOrder();
+
+ dst2src = new int[dCompCount];
+ for(int dIdx=0; dIdx<dCompCount; dIdx++) {
+ dst2src[dIdx] = PixelFormatUtil.find(dCompOrder[dIdx], sCompOrder, true);
+ }
+ src2dst = new int[sCompCount];
+ for(int sIdx=0; sIdx<sCompCount; sIdx++) {
+ src2dst[sIdx] = PixelFormatUtil.find(sCompOrder[sIdx], dCompOrder, true);
+ }
+ srcRGBA = new int[4];
+ srcRGBA[0] = PixelFormatUtil.find(PixelFormat.CType.R, sCompOrder, false);
+ srcRGBA[1] = PixelFormatUtil.find(PixelFormat.CType.G, sCompOrder, false);
+ srcRGBA[2] = PixelFormatUtil.find(PixelFormat.CType.B, sCompOrder, false);
+ srcRGBA[3] = PixelFormatUtil.find(PixelFormat.CType.A, sCompOrder, false);
+ hasSrcRGB = 0 <= srcRGBA[0] && 0 <= srcRGBA[1] && 0 <= srcRGBA[2];
+ }
}
+
+ public static final int find(final PixelFormat.CType s,
+ final PixelFormat.CType[] pool, final boolean mapRGB2Y) {
+ int i=pool.length-1;
+ while( i >= 0 && pool[i] != s) { i--; }
+
+ if( 0 > i && mapRGB2Y && 1 == pool.length && pool[0] == PixelFormat.CType.Y &&
+ ( PixelFormat.CType.R == s ||
+ PixelFormat.CType.G == s ||
+ PixelFormat.CType.B == s ) )
+ {
+ // Special case, fallback for RGB mapping -> LUMINANCE/Y
+ return 0;
+ } else {
+ return i;
+ }
+ }
+
/**
- * Pixel sink for up-to 32bit.
+ * Returns shifted bytes from the given {@code data} at given {@code offset}
+ * of maximal 4 {@code bytesPerPixel}.
+ * @param bytesPerPixel number of bytes per pixel to fetch, a maximum of 4 are allowed
+ * @param data byte buffer covering complete pixel at position {@code offset}
+ * @param offset byte offset of pixel {@code data} start
+ * @return the shifted 32bit integer value of the pixel
*/
- public static interface PixelSink32 extends PixelSink {
- /**
- * Will be invoked over all rows top-to down
- * and all columns left-to-right.
- * <p>
- * Shall consider dest pixelformat and only store as much components
- * as defined, up to 32bit.
- * </p>
- * <p>
- * Implementation may better write single bytes from low-to-high bits,
- * e.g. {@link ByteOrder#LITTLE_ENDIAN} order.
- * Otherwise a possible endian conversion must be taken into consideration.
- * </p>
- * @param x
- * @param y
- * @param pixel
- */
- void store(int x, int y, int pixel);
+ public static int getShiftedI32(final int bytesPerPixel, final byte[] data, final int offset) {
+ if( bytesPerPixel <= 4 ) {
+ int shiftedI32 = 0;
+ for(int i=0; i<bytesPerPixel; i++) {
+ shiftedI32 |= ( 0xff & data[offset+i] ) << 8*i;
+ }
+ return shiftedI32;
+ } else {
+ throw new UnsupportedOperationException(bytesPerPixel+" bytesPerPixel too big, i.e. > 4");
+ }
+ }
+ /**
+ * Returns shifted bytes from the given {@code data} at given {@code offset}
+ * of maximal 8 {@code bytesPerPixel}.
+ * @param bytesPerPixel number of bytes per pixel to fetch, a maximum of 4 are allowed
+ * @param data byte buffer covering complete pixel at position {@code offset}
+ * @param offset byte offset of pixel {@code data} start
+ * @return the shifted 64bit integer value of the pixel
+ */
+ public static long getShiftedI64(final int bytesPerPixel, final byte[] data, final int offset) {
+ if( bytesPerPixel <= 8 ) {
+ long shiftedI64 = 0;
+ for(int i=0; i<bytesPerPixel; i++) {
+ shiftedI64 |= ( 0xff & data[offset+i] ) << 8*i;
+ }
+ return shiftedI64;
+ } else {
+ throw new UnsupportedOperationException(bytesPerPixel+" bytesPerPixel too big, i.e. > 8");
+ }
+ }
+ /**
+ * Returns shifted bytes from the given {@code data} at current position
+ * of maximal 4 {@code bytesPerPixel}.
+ * @param bytesPerPixel number of bytes per pixel to fetch, a maximum of 4 are allowed
+ * @param data byte buffer covering complete pixel at position {@code offset}
+ * @param retainDataPos if true, absolute {@link ByteBuffer#get(int)} is used and the {@code data} position stays unchanged.
+ * Otherwise relative {@link ByteBuffer#get()} is used and the {@code data} position changes.
+ * @return the shifted 32bit integer value of the pixel
+ */
+ public static int getShiftedI32(final int bytesPerPixel, final ByteBuffer data, final boolean retainDataPos) {
+ if( bytesPerPixel <= 4 ) {
+ int shiftedI32 = 0;
+ if( retainDataPos ) {
+ final int offset = data.position();
+ for(int i=0; i<bytesPerPixel; i++) {
+ shiftedI32 |= ( 0xff & data.get(offset+i) ) << 8*i;
+ }
+ } else {
+ for(int i=0; i<bytesPerPixel; i++) {
+ shiftedI32 |= ( 0xff & data.get() ) << 8*i;
+ }
+ }
+ return shiftedI32;
+ } else {
+ throw new UnsupportedOperationException(bytesPerPixel+" bytesPerPixel too big, i.e. > 4");
+ }
+ }
+ /**
+ * Returns shifted bytes from the given {@code data} at current position
+ * of maximal 8 {@code bytesPerPixel}.
+ * @param bytesPerPixel number of bytes per pixel to fetch, a maximum of 4 are allowed
+ * @param data byte buffer covering complete pixel at position {@code offset}
+ * @param retainDataPos if true, absolute {@link ByteBuffer#get(int)} is used and the {@code data} position stays unchanged.
+ * Otherwise relative {@link ByteBuffer#get()} is used and the {@code data} position changes.
+ * @return the shifted 64bit integer value of the pixel
+ */
+ public static long getShiftedI64(final int bytesPerPixel, final ByteBuffer data, final boolean retainDataPos) {
+ if( bytesPerPixel <= 8 ) {
+ long shiftedI64 = 0;
+ if( retainDataPos ) {
+ final int offset = data.position();
+ for(int i=0; i<bytesPerPixel; i++) {
+ shiftedI64 |= ( 0xff & data.get(offset+i) ) << 8*i;
+ }
+ } else {
+ for(int i=0; i<bytesPerPixel; i++) {
+ shiftedI64 |= ( 0xff & data.get() ) << 8*i;
+ }
+ }
+ return shiftedI64;
+ } else {
+ throw new UnsupportedOperationException(bytesPerPixel+" bytesPerPixel too big, i.e. > 8");
+ }
}
/**
@@ -87,8 +200,14 @@ public class PixelFormatUtil {
*/
public static PixelFormat getReversed(final PixelFormat fmt) {
switch(fmt) {
- case LUMINANCE:
- return PixelFormat.LUMINANCE;
+ case RGB565:
+ return PixelFormat.BGR565;
+ case BGR565:
+ return PixelFormat.RGB565;
+ case RGBA5551:
+ return PixelFormat.ABGR1555;
+ case ABGR1555:
+ return PixelFormat.RGBA5551;
case RGB888:
return PixelFormat.BGR888;
case BGR888:
@@ -102,42 +221,14 @@ public class PixelFormatUtil {
case BGRA8888:
return PixelFormat.ABGR8888;
default:
- throw new InternalError("Unhandled format "+fmt);
+ return fmt;
}
}
- public static int getValue32(final PixelFormat src_fmt, final ByteBuffer src, int srcOff) {
- switch(src_fmt) {
+ public static int convertToInt32(final PixelFormat dst_fmt, final byte r, final byte g, final byte b, final byte a) {
+ switch(dst_fmt) {
case LUMINANCE: {
- final byte c1 = src.get(srcOff++);
- return ( 0xff ) << 24 | ( 0xff & c1 ) << 16 | ( 0xff & c1 ) << 8 | ( 0xff & c1 );
- }
- case RGB888:
- case BGR888: {
- final byte c1 = src.get(srcOff++);
- final byte c2 = src.get(srcOff++);
- final byte c3 = src.get(srcOff++);
- return ( 0xff ) << 24 | ( 0xff & c3 ) << 16 | ( 0xff & c2 ) << 8 | ( 0xff & c1 );
- }
- case RGBA8888:
- case ABGR8888:
- case ARGB8888:
- case BGRA8888: {
- final byte c1 = src.get(srcOff++);
- final byte c2 = src.get(srcOff++);
- final byte c3 = src.get(srcOff++);
- final byte c4 = src.get(srcOff++);
- return ( 0xff & c4 ) << 24 | ( 0xff & c3 ) << 16 | ( 0xff & c2 ) << 8 | ( 0xff & c1 );
- }
- default:
- throw new InternalError("Unhandled format "+src_fmt);
- }
- }
-
- public static int convertToInt32(final PixelFormat dest_fmt, final byte r, final byte g, final byte b, final byte a) {
- switch(dest_fmt) {
- case LUMINANCE: {
- final byte l = ( byte) ( ( ( ( 0xff & r ) + ( 0xff & g ) + ( 0xff & b ) ) / 3 ) );
+ final byte l = ( byte) ( ( ( ( 0xff & r ) + ( 0xff & g ) + ( 0xff & b ) ) / 3 ) * a );
return ( 0xff ) << 24 | ( 0xff & l ) << 16 | ( 0xff & l ) << 8 | ( 0xff & l );
}
case RGB888:
@@ -153,11 +244,11 @@ public class PixelFormatUtil {
case BGRA8888:
return ( 0xff & a ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b );
default:
- throw new InternalError("Unhandled format "+dest_fmt);
+ throw new InternalError("Unhandled format "+dst_fmt);
}
}
- public static int convertToInt32(final PixelFormat dest_fmt, final PixelFormat src_fmt, final ByteBuffer src, int srcOff) {
+ public static int convertToInt32(final PixelFormat dst_fmt, final PixelFormat src_fmt, final ByteBuffer src, int srcOff) {
final byte r, g, b, a;
switch(src_fmt) {
case LUMINANCE:
@@ -205,7 +296,7 @@ public class PixelFormatUtil {
default:
throw new InternalError("Unhandled format "+src_fmt);
}
- return convertToInt32(dest_fmt, r, g, b, a);
+ return convertToInt32(dst_fmt, r, g, b, a);
}
public static int convertToInt32(final PixelFormat dest_fmt, final PixelFormat src_fmt, final int src_pixel) {
@@ -259,115 +350,251 @@ public class PixelFormatUtil {
return convertToInt32(dest_fmt, r, g, b, a);
}
- public static PixelRectangle convert32(final PixelRectangle src,
- final PixelFormat destFmt, final int ddestStride, final boolean isGLOriented,
- final boolean destIsDirect) {
+ public static PixelRectangle convert(final PixelRectangle src,
+ final PixelFormat destFmt, final int ddestStride, final boolean isGLOriented,
+ final boolean destIsDirect) {
final int width = src.getSize().getWidth();
final int height = src.getSize().getHeight();
- final int bpp = destFmt.bytesPerPixel();
+ final int bpp = destFmt.comp.bytesPerPixel();
final int destStride;
if( 0 != ddestStride ) {
destStride = ddestStride;
- if( destStride < bpp * width ) {
- throw new IllegalArgumentException("Invalid stride "+destStride+", must be greater than bytesPerPixel "+bpp+" * width "+width);
- }
} else {
destStride = bpp * width;
}
final int capacity = destStride*height;
- final ByteBuffer bb = destIsDirect ? Buffers.newDirectByteBuffer(capacity) : ByteBuffer.allocate(capacity).order(src.getPixels().order());
-
- // System.err.println("XXX: SOURCE "+src);
- // System.err.println("XXX: DEST fmt "+destFmt+", stride "+destStride+" ("+ddestStride+"), isGL "+isGLOriented+", "+width+"x"+height+", capacity "+capacity+", "+bb);
-
- final PixelFormatUtil.PixelSink32 imgSink = new PixelFormatUtil.PixelSink32() {
- public void store(final int x, final int y, final int pixel) {
- int o = destStride*y+x*bpp;
- bb.put(o++, (byte) ( pixel )); // 1
- if( 3 <= bpp ) {
- bb.put(o++, (byte) ( pixel >>> 8 )); // 2
- bb.put(o++, (byte) ( pixel >>> 16 )); // 3
- if( 4 <= bpp ) {
- bb.put(o++, (byte) ( pixel >>> 24 )); // 4
- }
- }
- }
- @Override
- public final PixelFormat getPixelformat() {
- return destFmt;
- }
- @Override
- public final int getStride() {
- return destStride;
- }
- @Override
- public final boolean isGLOriented() {
- return isGLOriented;
- }
- };
- convert32(imgSink, src);
- return new PixelRectangle.GenericPixelRect(destFmt, src.getSize(), destStride, isGLOriented, bb);
+ final ByteBuffer destBB = destIsDirect ? Buffers.newDirectByteBuffer(capacity) : ByteBuffer.allocate(capacity).order(src.getPixels().order());
+ convert(src, destBB, destFmt, isGLOriented, destStride);
+ return new PixelRectangle.GenericPixelRect(destFmt, src.getSize(), destStride, isGLOriented, destBB);
}
- public static void convert32(final PixelSink32 destInt32, final PixelRectangle src) {
- convert32(destInt32,
- src.getPixels(), src.getPixelformat(),
- src.isGLOriented(),
- src.getSize().getWidth(), src.getSize().getHeight(),
- src.getStride());
+ /**
+ * @param src
+ * @param dst_bb {@link ByteBuffer} sink
+ * @param dst_fmt destination {@link PixelFormat}
+ * @param dst_glOriented if true, the source memory is laid out in OpenGL's coordinate system, <i>origin at bottom left</i>,
+ * otherwise <i>origin at top left</i>.
+ * @param dst_lineStride line stride in byte-size for destination, i.e. byte count from one line to the next.
+ * Must be >= {@link PixelFormat.Composition#bytesPerPixel() dst_fmt.comp.bytesPerPixel()} * width
+ * or {@code zero} for default stride.
+ *
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException if {@code src_lineStride} or {@code dst_lineStride} is invalid
+ */
+ public static void convert(final PixelRectangle src,
+ final ByteBuffer dst_bb, final PixelFormat dst_fmt, final boolean dst_glOriented, final int dst_lineStride)
+ throws IllegalStateException
+ {
+ convert(src.getSize().getWidth(), src.getSize().getHeight(),
+ src.getPixels(), src.getPixelformat(), src.isGLOriented(), src.getStride(),
+ dst_bb, dst_fmt, dst_glOriented, dst_lineStride);
}
+
/**
- *
- * @param dest32 32bit pixel sink
- * @param src_bb
- * @param src_fmt
+ * @param width width of the to be converted pixel rectangle
+ * @param height height of the to be converted pixel rectangle
+ * @param src_bb {@link ByteBuffer} source
+ * @param src_fmt source {@link PixelFormat}
* @param src_glOriented if true, the source memory is laid out in OpenGL's coordinate system, <i>origin at bottom left</i>,
* otherwise <i>origin at top left</i>.
- * @param width
- * @param height
- * @param strideInBytes stride in byte-size, i.e. byte count from one line to the next.
- * If zero, stride is set to <code>width * bytes-per-pixel</code>.
- * If not zero, value must be >= <code>width * bytes-per-pixel</code>.
- * @param stride_bytes stride in byte-size, i.e. byte count from one line to the next.
- * Must be >= {@link PixelFormat#bytesPerPixel() src_fmt.bytesPerPixel()} * width.
- * @throws IllegalArgumentException if <code>strideInBytes</code> is invalid
+ * @param src_lineStride line stride in byte-size for source, i.e. byte count from one line to the next.
+ * Must be >= {@link PixelFormat.Composition#bytesPerPixel() src_fmt.comp.bytesPerPixel()} * width
+ * or {@code zero} for default stride.
+ * @param dst_bb {@link ByteBuffer} sink
+ * @param dst_fmt destination {@link PixelFormat}
+ * @param dst_glOriented if true, the source memory is laid out in OpenGL's coordinate system, <i>origin at bottom left</i>,
+ * otherwise <i>origin at top left</i>.
+ * @param dst_lineStride line stride in byte-size for destination, i.e. byte count from one line to the next.
+ * Must be >= {@link PixelFormat.Composition#bytesPerPixel() dst_fmt.comp.bytesPerPixel()} * width
+ * or {@code zero} for default stride.
+ *
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException if {@code src_lineStride} or {@code dst_lineStride} is invalid
*/
- public static void convert32(final PixelSink32 dest32,
- final ByteBuffer src_bb, final PixelFormat src_fmt, final boolean src_glOriented, final int width, final int height, int stride_bytes) {
- final int src_bpp = src_fmt.bytesPerPixel();
- if( 0 != stride_bytes ) {
- if( stride_bytes < src_bpp * width ) {
- throw new IllegalArgumentException("Invalid stride "+stride_bytes+", must be greater than bytesPerPixel "+src_bpp+" * width "+width);
+ public static void convert(final int width, final int height,
+ final ByteBuffer src_bb, final PixelFormat src_fmt, final boolean src_glOriented, int src_lineStride,
+ final ByteBuffer dst_bb, final PixelFormat dst_fmt, final boolean dst_glOriented, int dst_lineStride
+ ) throws IllegalStateException, IllegalArgumentException {
+ final PixelFormat.Composition src_comp = src_fmt.comp;
+ final PixelFormat.Composition dst_comp = dst_fmt.comp;
+ final int src_bpp = src_comp.bytesPerPixel();
+ final int dst_bpp = dst_comp.bytesPerPixel();
+
+ if( 0 != src_lineStride ) {
+ if( src_lineStride < src_bpp * width ) {
+ throw new IllegalArgumentException(String.format("Invalid %s stride %d, must be greater than bytesPerPixel %d * width %d",
+ "source", src_lineStride, src_bpp, width));
}
} else {
- stride_bytes = src_bpp * width;
+ src_lineStride = src_bpp * width;
+ }
+ if( 0 != dst_lineStride ) {
+ if( dst_lineStride < dst_bpp * width ) {
+ throw new IllegalArgumentException(String.format("Invalid %s stride %d, must be greater than bytesPerPixel %d * width %d",
+ "destination", dst_lineStride, dst_bpp, width));
+ }
+ } else {
+ dst_lineStride = dst_bpp * width;
+ }
+
+ // final int src_comp_bitStride = src_comp.bitStride();
+ final int dst_comp_bitStride = dst_comp.bitStride();
+ final boolean vert_flip = src_glOriented != dst_glOriented;
+ final boolean fast_copy = src_comp.equals(dst_comp) && 0 == dst_comp_bitStride%8;
+ if( DEBUG ) {
+ System.err.println("XXX: size "+width+"x"+height+", fast_copy "+fast_copy);
+ System.err.println("XXX: SRC fmt "+src_fmt+", "+src_comp+", stride "+src_lineStride+", isGLOrient "+src_glOriented);
+ System.err.println("XXX: DST fmt "+dst_fmt+", "+dst_comp+", stride "+dst_lineStride+", isGLOrient "+dst_glOriented);
}
- final PixelFormat dest_fmt = dest32.getPixelformat();
- final boolean vert_flip = src_glOriented != dest32.isGLOriented();
- final boolean fast_copy = src_fmt == dest_fmt && dest_fmt.bytesPerPixel() == 4 ;
- // System.err.println("XXX: SRC fmt "+src_fmt+", stride "+stride_bytes+", isGL "+src_glOriented+", "+width+"x"+height);
- // System.err.println("XXX: DST fmt "+dest_fmt+", fast_copy "+fast_copy);
if( fast_copy ) {
// Fast copy
for(int y=0; y<height; y++) {
- int o = vert_flip ? ( height - 1 - y ) * stride_bytes : y * stride_bytes;
+ int src_off = vert_flip ? ( height - 1 - y ) * src_lineStride : y * src_lineStride;
+ int dst_off = dst_lineStride*y;
for(int x=0; x<width; x++) {
- dest32.store(x, y, getValue32(src_fmt, src_bb, o));
- o += src_bpp;
+ dst_bb.put(dst_off+0, src_bb.get(src_off+0)); // 1
+ if( 2 <= dst_bpp ) {
+ dst_bb.put(dst_off+1, src_bb.get(src_off+1)); // 2
+ if( 3 <= dst_bpp ) {
+ dst_bb.put(dst_off+2, src_bb.get(src_off+2)); // 3
+ if( 4 <= dst_bpp ) {
+ dst_bb.put(dst_off+3, src_bb.get(src_off+3)); // 4
+ }
+ }
+ }
+ src_off += src_bpp;
+ dst_off += dst_bpp;
}
}
} else {
// Conversion
- for(int y=0; y<height; y++) {
- int o = vert_flip ? ( height - 1 - y ) * stride_bytes : y * stride_bytes;
- for(int x=0; x<width; x++) {
- dest32.store( x, y, convertToInt32( dest_fmt, src_fmt, src_bb, o));
- o += src_bpp;
+ final ComponentMap cmap = new ComponentMap(src_fmt.comp, dst_fmt.comp);
+
+ final Bitstream.ByteBufferStream srcBBS = new Bitstream.ByteBufferStream(src_bb);
+ final Bitstream<ByteBuffer> srcBitStream = new Bitstream<ByteBuffer>(srcBBS, false /* outputMode */);
+ srcBitStream.setThrowIOExceptionOnEOF(true);
+
+ final Bitstream.ByteBufferStream dstBBS = new Bitstream.ByteBufferStream(dst_bb);
+ final Bitstream<ByteBuffer> dstBitStream = new Bitstream<ByteBuffer>(dstBBS, true /* outputMode */);
+ dstBitStream.setThrowIOExceptionOnEOF(true);
+
+ if( DEBUG ) {
+ System.err.println("XXX: cmap.dst2src "+Arrays.toString(cmap.dst2src));
+ System.err.println("XXX: cmap.src2dst "+Arrays.toString(cmap.src2dst));
+ System.err.println("XXX: cmap.srcRGBA "+Arrays.toString(cmap.srcRGBA));
+ System.err.println("XXX: srcBitStream "+srcBitStream);
+ System.err.println("XXX: dstBitStream "+dstBitStream);
+ }
+ try {
+ for(int y=0; y<height; y++) {
+ final int src_off = vert_flip ? ( height - 1 - y ) * src_lineStride * 8 : y * src_lineStride * 8;
+ // final int dst_off = dst_lineStride*8*y;
+ srcBitStream.position(src_off);
+ for(int x=0; x<width; x++) {
+ convert(cmap, dst_comp, dstBitStream, src_comp, srcBitStream);
+ }
+ // srcBitStream.skip(( src_lineStride * 8 ) - ( src_comp_bitStride * width ));
+ dstBitStream.skip(( dst_lineStride * 8 ) - ( dst_comp_bitStride * width ));
+ }
+ } catch(final IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ if( DEBUG ) {
+ System.err.println("XXX: srcBitStream "+srcBitStream);
+ System.err.println("XXX: dstBitStream "+dstBitStream);
+ }
+ }
+ }
+
+ public static void convert(final ComponentMap cmap,
+ final PixelFormat.Composition dstComp,
+ final Bitstream<ByteBuffer> dstBitStream,
+ final PixelFormat.Composition srcComp,
+ final Bitstream<ByteBuffer> srcBitStream) throws IllegalStateException, IOException {
+ final int sCompCount = srcComp.componenCount();
+ final int dCompCount = dstComp.componenCount();
+ final int[] sc = new int[sCompCount];
+ final int[] dcDef = new int[dCompCount];
+ final int[] srcCompBitCount = srcComp.componentBitCount();
+ final int[] srcCompBitMask = srcComp.componentBitMask();
+ final int[] dstCompBitCount = dstComp.componentBitCount();
+
+ // Fill w/ source values
+ for(int sIdx=0; sIdx<sCompCount; sIdx++) {
+ sc[sIdx] = srcBitStream.readBits31(srcCompBitCount[sIdx]) & srcCompBitMask[sIdx];
+ }
+ srcBitStream.skip(srcComp.bitStride() - srcComp.bitsPerPixel());
+
+ // Cache missing defaults
+ for(int i=0; i<dCompCount; i++) {
+ dcDef[i] = dstComp.defaultValue(i, false);
+ }
+
+ if( 1 == dCompCount &&
+ PixelFormat.CType.Y == dstComp.componentOrder()[0] &&
+ cmap.hasSrcRGB
+ )
+ {
+ // RGB[A] -> Y conversion
+ final int r = sc[cmap.srcRGBA[0]];
+ final int g = sc[cmap.srcRGBA[1]];
+ final int b = sc[cmap.srcRGBA[2]];
+ final float rF = srcComp.toFloat(r, cmap.srcRGBA[0], false);
+ final float gF = srcComp.toFloat(g, cmap.srcRGBA[1], false);
+ final float bF = srcComp.toFloat(b, cmap.srcRGBA[2], false);
+ final int a;
+ final float aF;
+ /** if( 0 <= cmap.srcRGBA[3] ) { // disable premultiplied-alpha
+ a = sc[cmap.srcRGBA[3]];
+ aF = srcComp.toFloat(a, false, cmap.srcRGBA[3]);
+ } else */ {
+ a = 1;
+ aF = 1f;
+ }
+ final float lF = ( rF + gF + bF ) * aF / 3f;
+ final int v = dstComp.fromFloat(lF, 0, false);
+
+ dstBitStream.writeBits31(dstCompBitCount[0], v);
+ dstBitStream.skip(dstComp.bitStride() - dstComp.bitsPerPixel());
+ if( DEBUG ) {
+ if( srcBitStream.position() <= 8*4 ) {
+ System.err.printf("convert: rgb[a] -> Y: rgb 0x%02X 0x%02X 0x%02X 0x%02X -> %f %f %f %f"+
+ " -> %f -> dstC 0 0x%08X (%d bits: %s)%n",
+ r, g, b, a,
+ rF, gF, bF, aF,
+ lF, v, dstCompBitCount[0], Bitstream.toBinString(true, v, dstCompBitCount[0])
+ );
+ }
+ }
+ return;
+ }
+
+ for(int dIdx=0; dIdx<dCompCount; dIdx++) {
+ int sIdx;
+ if( 0 <= ( sIdx = cmap.dst2src[dIdx] ) ) {
+ final float f = srcComp.toFloat(sc[sIdx], sIdx, false);
+ final int v = dstComp.fromFloat(f, dIdx, false);
+ dstBitStream.writeBits31(dstCompBitCount[dIdx], v);
+ if( DEBUG ) {
+ if( srcBitStream.position() <= 8*4 ) {
+ System.err.printf("convert: srcC %d: 0x%08X -> %f -> dstC %d 0x%08X (%d bits: %s)%n",
+ sIdx, sc[sIdx], f, dIdx, v, dstCompBitCount[dIdx], Bitstream.toBinString(true, v, dstCompBitCount[dIdx]));
+ }
+ }
+ } else {
+ dstBitStream.writeBits31(dstCompBitCount[dIdx], dcDef[dIdx]);
+ if( DEBUG ) {
+ if( srcBitStream.position() <= 8*4 ) {
+ System.err.printf("convert: srcC %d: undef -> dstC %d 0x%08X (%d bits: %s)%n",
+ sIdx, dIdx, dcDef[dIdx], dstCompBitCount[dIdx], Bitstream.toBinString(true, dcDef[dIdx], dstCompBitCount[dIdx]));
+ }
}
}
}
+ dstBitStream.skip(dstComp.bitStride() - dstComp.bitsPerPixel());
+ return;
}
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java
index 96c1f7b33..f4fc99aee 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java
@@ -113,11 +113,11 @@ public interface PixelRectangle {
throws IllegalArgumentException, IndexOutOfBoundsException
{
if( 0 != strideInBytes ) {
- if( strideInBytes < pixelformat.bytesPerPixel() * size.getWidth()) {
- throw new IllegalArgumentException("Invalid stride "+strideInBytes+", must be greater than bytesPerPixel "+pixelformat.bytesPerPixel()+" * width "+size.getWidth());
+ if( strideInBytes < pixelformat.comp.bytesPerPixel() * size.getWidth()) {
+ throw new IllegalArgumentException("Invalid stride "+strideInBytes+", must be greater than bytesPerPixel "+pixelformat.comp.bytesPerPixel()+" * width "+size.getWidth());
}
} else {
- strideInBytes = pixelformat.bytesPerPixel() * size.getWidth();
+ strideInBytes = pixelformat.comp.bytesPerPixel() * size.getWidth();
}
final int reqBytes = strideInBytes * size.getHeight();
if( pixels.limit() < reqBytes ) {
@@ -148,7 +148,7 @@ public interface PixelRectangle {
synchronized (this) {
if( !hashCodeComputed ) {
// 31 * x == (x << 5) - x
- int hash = 31 + pixelformat.hashCode();
+ int hash = pixelformat.comp.hashCode();
hash = ((hash << 5) - hash) + size.hashCode();
hash = ((hash << 5) - hash) + strideInBytes;
hash = ((hash << 5) - hash) + ( isGLOriented ? 1 : 0);
diff --git a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
index b0eda63b6..1dce9218c 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
@@ -37,6 +37,7 @@ import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
import java.awt.image.BufferedImage;
+import java.nio.ByteBuffer;
import java.util.HashMap;
import javax.swing.JComponent;
@@ -50,6 +51,8 @@ import javax.media.nativewindow.util.PixelFormat;
import javax.media.nativewindow.util.PixelFormatUtil;
import javax.swing.MenuSelectionManager;
+import com.jogamp.nativewindow.awt.DirectDataBufferInt;
+
import jogamp.nativewindow.jawt.JAWTUtil;
public class AWTMisc {
@@ -210,25 +213,13 @@ public class AWTMisc {
private static synchronized Cursor createCursor(final PixelRectangle pixelrect, final Point hotSpot) {
final int width = pixelrect.getSize().getWidth();
final int height = pixelrect.getSize().getHeight();
- final BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); // PixelFormat.BGRA8888
- final PixelFormatUtil.PixelSink32 imgSink = new PixelFormatUtil.PixelSink32() {
- public void store(final int x, final int y, final int pixel) {
- img.setRGB(x, y, pixel);
- }
- @Override
- public final PixelFormat getPixelformat() {
- return PixelFormat.BGRA8888;
- }
- @Override
- public int getStride() {
- return width*4;
- }
- @Override
- public final boolean isGLOriented() {
- return false;
- }
- };
- PixelFormatUtil.convert32(imgSink, pixelrect);
+ // final BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); // PixelFormat.BGRA8888
+ final DirectDataBufferInt.BufferedImageInt img =
+ DirectDataBufferInt.createBufferedImage(width, height, BufferedImage.TYPE_INT_ARGB,
+ null /* location */, null /* properties */);
+ final ByteBuffer imgBuffer = img.getDataBuffer().getDataBytes();
+ PixelFormatUtil.convert(pixelrect, imgBuffer, PixelFormat.BGRA8888, false /* dst_glOriented */, width*4 /* dst_lineStride */);
+
final Toolkit toolkit = Toolkit.getDefaultToolkit();
return toolkit.createCustomCursor(img, hotSpot, pixelrect.toString());
}
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index 5f67c95c1..c94d7d40e 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -165,7 +165,7 @@ public abstract class DisplayImpl extends Display {
final PixelRectangle fpixelrect;
if( getNativePointerIconPixelFormat() != pixelrect.getPixelformat() || pixelrect.isGLOriented() ) {
// conversion !
- fpixelrect = PixelFormatUtil.convert32(pixelrect, getNativePointerIconPixelFormat(),
+ fpixelrect = PixelFormatUtil.convert(pixelrect, getNativePointerIconPixelFormat(),
0 /* ddestStride */, false /* isGLOriented */, getNativePointerIconForceDirectNIO() );
if( DEBUG_POINTER_ICON ) {
System.err.println("createPointerIconRES.0: Conversion-FMT "+pixelrect+" -> "+fpixelrect);
diff --git a/src/newt/classes/jogamp/newt/PointerIconImpl.java b/src/newt/classes/jogamp/newt/PointerIconImpl.java
index 546a463de..f2b24a3b3 100644
--- a/src/newt/classes/jogamp/newt/PointerIconImpl.java
+++ b/src/newt/classes/jogamp/newt/PointerIconImpl.java
@@ -154,7 +154,7 @@ public class PointerIconImpl implements PointerIcon {
}
@Override
public final int getStride() {
- return size.getWidth() * pixelformat.bytesPerPixel();
+ return size.getWidth() * pixelformat.comp.bytesPerPixel();
}
@Override
public final boolean isGLOriented() {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java
index ae11c9d54..3e2476563 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java
@@ -70,6 +70,7 @@ import com.jogamp.opengl.util.FPSAnimator;
public class TestGearsES2GLJPanelAWT extends UITestCase {
static Dimension wsize, rwsize=null;
static boolean forceES2 = false;
+ static boolean forceES3 = false;
static boolean forceGL3 = false;
static boolean forceGLFFP = false;
static boolean shallUsePBuffer = false;
@@ -117,6 +118,8 @@ public class TestGearsES2GLJPanelAWT extends UITestCase {
protected void runTestGL(final GLCapabilities caps)
throws AWTException, InterruptedException, InvocationTargetException
{
+ System.err.println("Requesting: "+caps);
+
final JFrame frame = new JFrame("Swing GLJPanel");
Assert.assertNotNull(frame);
@@ -302,12 +305,14 @@ public class TestGearsES2GLJPanelAWT extends UITestCase {
final GLProfile glp;
if(forceGL3) {
glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES3) {
+ glp = GLProfile.get(GLProfile.GLES3);
} else if(forceES2) {
glp = GLProfile.get(GLProfile.GLES2);
} else if(forceGLFFP) {
glp = GLProfile.getMaxFixedFunc(true);
} else {
- glp = GLProfile.getGL2ES2();
+ glp = GLProfile.getDefault();
}
final GLCapabilities caps = new GLCapabilities( glp );
if(useMSAA) {
@@ -406,7 +411,24 @@ public class TestGearsES2GLJPanelAWT extends UITestCase {
}
@Test
- public void test30_GL3()
+ public void test30_GLES3()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+
+ if( !GLProfile.isAvailable(GLProfile.GLES3) ) {
+ System.err.println("GLES3 n/a");
+ return;
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GLES3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test40_GL3()
throws AWTException, InterruptedException, InvocationTargetException
{
if( manualTest ) {
@@ -447,6 +469,8 @@ public class TestGearsES2GLJPanelAWT extends UITestCase {
duration = MiscUtils.atol(args[i], duration);
} else if(args[i].equals("-es2")) {
forceES2 = true;
+ } else if(args[i].equals("-es3")) {
+ forceES3 = true;
} else if(args[i].equals("-gl3")) {
forceGL3 = true;
} else if(args[i].equals("-glFFP")) {
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 11d9da780..c22a6fdf8 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
@@ -99,7 +99,7 @@ public class TestGearsES2GLJPanelsAWT extends UITestCase {
if( initSingleBuffer ) {
singleAWTGLPixelBufferProvider = new SingleAWTGLPixelBufferProvider( glp.isGL2ES3() /* allowRowStride */);
- singleAWTGLPixelBufferProvider.initSingleton(4, 600, 600, 1, true);
+ singleAWTGLPixelBufferProvider.initSingleton(null, 4, true, 600, 600, 1);
} else {
singleAWTGLPixelBufferProvider = null;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java
index 546420057..ed20ccd97 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering2GL2NEWT.java
@@ -40,6 +40,7 @@ import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -117,8 +118,9 @@ public class TestRandomTiledRendering2GL2NEWT extends UITestCase {
@Override
public void init(final GLAutoDrawable drawable) {
final GL gl = drawable.getGL();
- final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3);
- final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0);
+ final PixelFormat.Composition hostPixelComp = pixelBufferProvider.getHostPixelComp(gl.getGLProfile(), 3);
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3, true);
+ final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, imageWidth, imageHeight, 1, 0);
renderer.setImageBuffer(pixelBuffer);
if( drawable.isGLOriented() ) {
flipVertically[0] = false;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java
index b128f8691..a9d159684 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestRandomTiledRendering3GL2AWT.java
@@ -48,6 +48,7 @@ import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -136,8 +137,9 @@ public class TestRandomTiledRendering3GL2AWT extends UITestCase {
@Override
public void init(final GLAutoDrawable drawable) {
final GL gl = drawable.getGL();
- final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3);
- final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0);
+ final PixelFormat.Composition hostPixelComp = pixelBufferProvider.getHostPixelComp(gl.getGLProfile(), 3);
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3, true);
+ final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, imageWidth, imageHeight, 1, 0);
renderer.setImageBuffer(pixelBuffer);
if( drawable.isGLOriented() ) {
flipVertically[0] = false;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java
index 9dee67e5e..1f7016b7c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering1GL2NEWT.java
@@ -39,6 +39,7 @@ import com.jogamp.opengl.util.texture.TextureIO;
import java.io.File;
import java.io.IOException;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -121,8 +122,9 @@ public class TestTiledRendering1GL2NEWT extends UITestCase {
final GLPixelBuffer.GLPixelBufferProvider pixelBufferProvider = GLPixelBuffer.defaultProviderWithRowStride;
final boolean[] flipVertically = { false };
- final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3);
- final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0);
+ final PixelFormat.Composition hostPixelComp = pixelBufferProvider.getHostPixelComp(gl.getGLProfile(), 3);
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3, true);
+ final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, imageWidth, imageHeight, 1, 0);
renderer.setImageBuffer(pixelBuffer);
flipVertically[0] = false;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java
index e979ac966..e792ecaa2 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledRendering2NEWT.java
@@ -40,6 +40,8 @@ import com.jogamp.opengl.util.texture.TextureIO;
import java.io.File;
import java.io.IOException;
+
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -197,8 +199,9 @@ public class TestTiledRendering2NEWT extends UITestCase {
@Override
public void init(final GLAutoDrawable drawable) {
final GL gl = drawable.getGL();
- final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3);
- final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, pixelAttribs, imageWidth, imageHeight, 1, true, 0);
+ final PixelFormat.Composition hostPixelComp = pixelBufferProvider.getHostPixelComp(gl.getGLProfile(), 3);
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(gl, 3, true);
+ final GLPixelBuffer pixelBuffer = pixelBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, imageWidth, imageHeight, 1, 0);
renderer.setImageBuffer(pixelBuffer);
if( drawable.isGLOriented() ) {
flipVertically[0] = false;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java
index 2eb8b45c3..1a146adb6 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT.java
@@ -112,7 +112,7 @@ public class TestBug817GLReadBufferUtilGLCTXDefFormatTypeES2NEWT extends UITestC
public void dispose(final GLAutoDrawable drawable) {}
public void display(final GLAutoDrawable drawable) {
final GLPixelBufferProvider pixelBufferProvider = screenshot.getPixelBufferProvider();
- final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(drawable.getGL(), readAlpha ? 4 : 3);
+ final GLPixelAttributes pixelAttribs = pixelBufferProvider.getAttributes(drawable.getGL(), readAlpha ? 4 : 3, true);
System.err.println("GLPixelAttributes: "+pixelAttribs);
snapshot(displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java
index 4a324f594..3f910ed36 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java
@@ -73,9 +73,10 @@ public class TestPNGPixelRect01NEWT extends UITestCase {
final GLProfile glp = GLProfile.getGL2ES2();
final PNGPixelRect image = PNGPixelRect.read(istream, destFmt, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */);
Assert.assertNotNull(image);
- final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp);
- final boolean hasAlpha = 4 == glpa.bytesPerPixel;
- System.err.println("PNGPixelRect: "+basename+", "+image+", glpa "+glpa);
+ System.err.println("PNGPixelRect: "+basename+", "+image);
+ final GLPixelAttributes glpa = new GLPixelAttributes(glp, image.getPixelformat(), false /* pack */);
+ final boolean hasAlpha = 4 == glpa.pfmt.comp.bytesPerPixel();
+ System.err.println("GLPixelAttributes: "+glpa);
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
final GLCapabilities caps = new GLCapabilities(glp);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java
index 1b549fa96..6193ad1a7 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java
@@ -36,12 +36,14 @@ import javax.media.nativewindow.util.Dimension;
import javax.media.nativewindow.util.PixelFormat;
import javax.media.nativewindow.util.PixelFormatUtil;
import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat.CType;
import org.junit.Assert;
import org.junit.Test;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
+import com.jogamp.common.util.Bitstream;
import com.jogamp.opengl.test.junit.util.UITestCase;
/**
@@ -50,142 +52,401 @@ import com.jogamp.opengl.test.junit.util.UITestCase;
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestPixelFormatUtil00NEWT extends UITestCase {
+ static final byte undef_val = (byte)0xFF;
+ static final PixelFormat.Composition comp_val = PixelFormat.RGBA8888.comp;
+ static final float red___valF;
+ static final float green_valF;
+ static final float blue__valF;
+ static final float alpha_valF;
+ static final float lum___valF;
+ static {
+ // Using am equal stepping of 0x30 = 48 between each RGBA and undefined values,
+ // dividing 0xff equally by 5 excluding zero.
+ final byte red___val = (byte)0x30;
+ final byte green_val = (byte)0x60;
+ final byte blue__val = (byte)0x90;
+ final byte alpha_val = (byte)0xC0;
+ red___valF = comp_val.toFloat(red___val, 0, false);
+ green_valF = comp_val.toFloat(green_val, 1, false);
+ blue__valF = comp_val.toFloat(blue__val, 2, false);
+ alpha_valF = comp_val.toFloat(alpha_val, 3, false);
+ lum___valF = ( red___valF + green_valF + blue__valF ) / 3f;
+ }
+
+ @Test
+ public void testConversion00() throws InterruptedException, IOException, MalformedURLException {
+ {
+ final PixelFormat fmt = PixelFormat.RGBA5551;
+ final PixelFormat.Composition comp = fmt.comp;
+ System.err.printf("%s, %s:%n", fmt, comp);
+ final int u16_alpha = comp.encode4CompI8((byte)comp.fromFloat(red___valF, 0, false),
+ (byte)comp.fromFloat(green_valF, 0, false),
+ (byte)comp.fromFloat(blue__valF, 0, false),
+ (byte)comp.fromFloat(alpha_valF, 0, false));
+ final int u16_undef = comp.encode4CompI8((byte)comp.fromFloat(red___valF, 0, false),
+ (byte)comp.fromFloat(green_valF, 0, false),
+ (byte)comp.fromFloat(blue__valF, 0, false),
+ undef_val);
+ System.err.printf(" u16_alpha %s%n", Bitstream.toHexBinString(true, u16_alpha, comp.bitsPerPixel()));
+ System.err.printf(" u16_undef %s%n", Bitstream.toHexBinString(true, u16_undef, comp.bitsPerPixel()));
+ {
+ final byte c4NormI8_alpha = (byte)comp.fromFloat(alpha_valF, 0, false);
+ final byte c4NormI8_undef = undef_val;
+ final int compBitShift = 15;
+ final int compMask = 0x1;
+ final int v_alpha = ( c4NormI8_alpha & compMask ) << compBitShift ;
+ final int v_undef = ( c4NormI8_undef & compMask ) << compBitShift ;
+ System.err.printf(" xx_alpha %s%n", Bitstream.toHexBinString(true, v_alpha, comp.bitsPerPixel()));
+ System.err.printf(" xx_undef %s%n", Bitstream.toHexBinString(true, v_undef, comp.bitsPerPixel()));
+ }
+ }
+ {
+ final int r8 = 0x30;
+ final int g8 = 0x60;
+ final int b8 = 0x90;
+ final int a8 = 0xC0;
+
+ final int l1 = 0x1;
+ final int r5 = 0x6;
+ final int g6 = 0xC;
+ final int b5 = 0x6;
+
+ final PixelFormat rgba8888Fmt = PixelFormat.RGBA8888;
+ final PixelFormat.Composition rgba8888Comp = rgba8888Fmt.comp;
+ final PixelFormat rgb565Fmt = PixelFormat.RGB565;
+ final PixelFormat.Composition rgb565Comp = rgb565Fmt.comp;
+ final PixelFormat lumFmt = PixelFormat.LUMINANCE;
+ final PixelFormat.Composition lumComp = lumFmt.comp;
+ System.err.printf("%s, %s -> %s %s%n", rgb565Fmt, rgb565Comp, lumFmt, lumComp);
+
+ {
+ final float r8f = rgba8888Comp.toFloat(r8, 0, false);
+ final int r8fi = rgba8888Comp.fromFloat(r8f, 0, false);
+ final float g8f = rgba8888Comp.toFloat(g8, 1, false);
+ final int g8fi = rgba8888Comp.fromFloat(g8f, 1, false);
+ final float b8f = rgba8888Comp.toFloat(b8, 2, false);
+ final int b8fi = rgba8888Comp.fromFloat(b8f, 2, false);
+ final float a8f = rgba8888Comp.toFloat(a8, 3, false);
+ final int a8fi = rgba8888Comp.fromFloat(a8f, 3, false);
+
+ System.err.printf("res00.0.r %s -> %f -> %s%n", Bitstream.toHexBinString(true, r8, 8), r8f, Bitstream.toHexBinString(true, r8fi, 8));
+ System.err.printf("res00.0.g %s -> %f -> %s%n", Bitstream.toHexBinString(true, g8, 8), g8f, Bitstream.toHexBinString(true, g8fi, 8));
+ System.err.printf("res00.0.b %s -> %f -> %s%n", Bitstream.toHexBinString(true, b8, 8), b8f, Bitstream.toHexBinString(true, b8fi, 8));
+ System.err.printf("res00.0.a %s -> %f -> %s%n", Bitstream.toHexBinString(true, a8, 8), a8f, Bitstream.toHexBinString(true, a8fi, 8));
+ }
+ {
+ final float res00_0 = ( red___valF + green_valF + blue__valF ) / 3f;
+ final int res00 = rgba8888Comp.fromFloat(res00_0, 0, false);
+ System.err.printf("res01.0 ( %f + %f + %f ) / 3f = %f -> %s%n",
+ red___valF, green_valF, blue__valF, res00_0, Bitstream.toHexBinString(true, res00, 8));
+ }
+ {
+ final float res00_0 = ( red___valF + green_valF + blue__valF ) / 3f;
+ final int res00 = lumComp.fromFloat(res00_0, 0, false);
+ System.err.printf("res02.1 ( %f + %f + %f ) / 3f = %f -> %s%n",
+ red___valF, green_valF, blue__valF, res00_0, Bitstream.toHexBinString(true, res00, 8));
+ }
+ {
+ // sourceNorm static -> lum
+ final int rl1 = lumComp.fromFloat(red___valF, 0, false);
+ final int gl1 = lumComp.fromFloat(green_valF, 0, false);
+ final int bl1 = lumComp.fromFloat(blue__valF, 0, false);
+ final float rl2 = lumComp.toFloat(rl1, 0, false);
+ final float gl2 = lumComp.toFloat(gl1, 0, false);
+ final float bl2 = lumComp.toFloat(bl1, 0, false);
+ System.err.printf("res20.l1 ( %s + %s + %s )%n",
+ Bitstream.toHexBinString(true, rl1, 8),
+ Bitstream.toHexBinString(true, gl1, 8),
+ Bitstream.toHexBinString(true, bl1, 8));
+ System.err.printf("res20.l2 ( %f + %f + %f )%n", rl2, gl2, bl2);
+ final float res02_l2_0 = ( rl2 + gl2 + bl2 ) / 3f;
+ final int res02_l2_x = lumComp.fromFloat(res02_l2_0, 0, false);
+ System.err.printf("res20.l3 ( %f + %f + %f ) / 3f = %f -> %s%n",
+ rl2, gl2, bl2, res02_l2_0, Bitstream.toHexBinString(true, res02_l2_x, 8));
+
+ // rescale lum -> rgb565
+ final int r_1 = rgb565Comp.fromFloat(rl2, 0, false);
+ final int g_1 = rgb565Comp.fromFloat(gl2, 1, false);
+ final int b_1 = rgb565Comp.fromFloat(bl2, 2, false);
+ final float r_2 = rgb565Comp.toFloat(r_1, 0, false);
+ final float g_2 = rgb565Comp.toFloat(g_1, 1, false);
+ final float b_2 = rgb565Comp.toFloat(b_1, 2, false);
+ System.err.printf("res20._1 ( %s + %s + %s )%n",
+ Bitstream.toHexBinString(true, r_1, 8),
+ Bitstream.toHexBinString(true, g_1, 8),
+ Bitstream.toHexBinString(true, b_1, 8));
+ System.err.printf("res20._2 ( %f + %f + %f )%n", r_2, g_2, b_2);
+ final float res02__3_0 = ( r_2 + g_2 + b_2 ) / 3f;
+ final int res02__3_x = lumComp.fromFloat(res02__3_0, 0, false);
+ System.err.printf("res20._3 ( %f + %f + %f ) / 3f = %f -> %s%n",
+ r_2, g_2, b_2, res02__3_0, Bitstream.toHexBinString(true, res02__3_x, 8));
+ }
+ {
+ // sourceNorm static -> lum
+ // rescale lum -> rgb565
+ final float rF = rgb565Comp.toFloat(rescaleComp(lumComp, 0, rgb565Comp, 0, red___valF), 0, false);
+ final float gF = rgb565Comp.toFloat(rescaleComp(lumComp, 0, rgb565Comp, 1, green_valF), 1, false);
+ final float bF = rgb565Comp.toFloat(rescaleComp(lumComp, 0, rgb565Comp, 2, blue__valF), 2, false);
+ final float res01_0 = ( rF + gF + bF ) / 3f;
+ final int res01 = lumComp.fromFloat(res01_0, 0, false);
+ System.err.printf("res30.xx ( %f + %f + %f ) / 3f = %f -> %s%n",
+ rF, gF, bF, res01_0, Bitstream.toHexBinString(true, res01, 8));
+ }
+ {
+ final float rF = rgb565Comp.toFloat(r5, 0, false);
+ final float gF = rgb565Comp.toFloat(g6, 1, false);
+ final float bF = rgb565Comp.toFloat(b5, 2, false);
+
+ final float lF = ( rF + gF + bF ) / 3f;
+ final int res00 = lumComp.fromFloat(lF, 0, false);
+
+ System.err.printf("res40 ( %f + %f + %f ) / 3f = %s%n",
+ rF, gF, bF, Bitstream.toHexBinString(true, res00, 8));
+ }
+ }
+
+ }
+
@Test
public void testConversion01_srcS000_BE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException {
- testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
- 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ testConversionImpl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
}
@Test
public void testConversion02_srcS000_LE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException {
- testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.LITTLE_ENDIAN, false /* srcIsGLOriented */,
- 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ testConversionImpl(0 /* srcMinStrideInBytes */, ByteOrder.LITTLE_ENDIAN, false /* srcIsGLOriented */,
+ 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
}
@Test
public void testConversion03_srcS000_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
- testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
- 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ testConversionImpl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
}
@Test
public void testConversion04_srcS259_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
- testPNG00Impl(259 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
- 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ testConversionImpl(259 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
}
@Test
public void testConversion05_srcS301_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
- testPNG00Impl(301 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
- 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ testConversionImpl(301 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
}
- static final byte red___val = (byte)0x01;
- static final byte green_val = (byte)0x02;
- static final byte blue__val = (byte)0x03;
- static final byte alpha_val = (byte)0x04;
- static final byte undef_val = (byte)0xff;
-
- static final void getComponents(final int srcComps, final PixelFormat fmt, final byte[] components) {
+ /**
+ * Note: Fixes bit-rounding errors, i.e. RGBA5551: A 0.6f -> 0x01 -> 1f ... -> RGBA8888: A 0xff
+ */
+ static final float sourceNorm(final PixelFormat.Composition srcComp, final int sIdx, final float f) {
+ if( sIdx >= 0 && sIdx < srcComp.componenCount() ) {
+ return srcComp.toFloat(srcComp.fromFloat(f, sIdx, false), sIdx, false);
+ } else {
+ return 0f;
+ }
+ }
+ static final byte rescaleComp(final PixelFormat.Composition srcComp, final int sIdx,
+ final PixelFormat.Composition dstComp, final int dIdx, final float f) {
+ if( dIdx >= 0 && dIdx < dstComp.componenCount() ) {
+ return (byte)dstComp.fromFloat(sourceNorm(srcComp, sIdx, f), dIdx, false);
+ } else {
+ return (byte)0;
+ }
+ }
+ static final void getComponentData(final PixelFormat srcFmt, final PixelFormat dstFmt, final byte[] components) {
+ final PixelFormat.Composition srcComp = srcFmt.comp;
+ final PixelFormat.Composition dstComp = dstFmt.comp;
final byte b1, b2, b3, b4;
- if( 1 == srcComps ) {
+ int u16;
+ if( PixelFormat.LUMINANCE == srcFmt ) {
// LUM -> Fmt Conversion
- switch(fmt) {
+ switch(dstFmt) {
case LUMINANCE:
- b1 = red___val;
+ b1 = rescaleComp(srcComp, 0, dstComp, 0, lum___valF);
b2 = undef_val;
b3 = undef_val;
b4 = undef_val;
break;
- case RGB888:
- b1 = red___val;
- b2 = red___val;
- b3 = red___val;
+ case RGB565:
+ case BGR565:
+ u16 = dstComp.encode3CompI8(
+ rescaleComp(srcComp, 0, dstComp, 0, lum___valF),
+ rescaleComp(srcComp, 0, dstComp, 1, lum___valF),
+ rescaleComp(srcComp, 0, dstComp, 2, lum___valF));
+ b1 = (byte)( u16 & 0xff );
+ b2 = (byte)( ( u16 >>> 8 ) & 0xff );
+ b3 = undef_val;
b4 = undef_val;
break;
- case BGR888:
- b1 = red___val;
- b2 = red___val;
- b3 = red___val;
+ case RGBA5551:
+ u16 = dstComp.encode4CompI8(
+ rescaleComp(srcComp, 0, dstComp, 0, lum___valF),
+ rescaleComp(srcComp, 0, dstComp, 1, lum___valF),
+ rescaleComp(srcComp, 0, dstComp, 2, lum___valF),
+ undef_val);
+ b1 = (byte)( u16 & 0xff );
+ b2 = (byte)( ( u16 >>> 8 ) & 0xff );
+ b3 = undef_val;
b4 = undef_val;
break;
+ case ABGR1555:
+ u16 = dstComp.encode4CompI8(
+ undef_val,
+ rescaleComp(srcComp, 0, dstComp, 0, lum___valF),
+ rescaleComp(srcComp, 0, dstComp, 1, lum___valF),
+ rescaleComp(srcComp, 0, dstComp, 2, lum___valF) );
+ b1 = (byte)( u16 & 0xff );
+ b2 = (byte)( ( u16 >>> 8 ) & 0xff );
+ b3 = undef_val;
+ b4 = undef_val;
+ break;
+ case BGRx8888:
+ case RGBx8888:
+ case RGB888:
+ case BGR888:
case RGBA8888:
- b1 = red___val;
- b2 = red___val;
- b3 = red___val;
+ b1 = rescaleComp(srcComp, 0, dstComp, 0, lum___valF);
+ b2 = rescaleComp(srcComp, 0, dstComp, 1, lum___valF);
+ b3 = rescaleComp(srcComp, 0, dstComp, 2, lum___valF);
b4 = undef_val;
break;
case ABGR8888:
+ case ARGB8888:
b1 = undef_val;
- b2 = red___val;
- b3 = red___val;
- b4 = red___val;
+ b2 = rescaleComp(srcComp, 0, dstComp, 1, lum___valF);
+ b3 = rescaleComp(srcComp, 0, dstComp, 2, lum___valF);
+ b4 = rescaleComp(srcComp, 0, dstComp, 3, lum___valF);
break;
case BGRA8888:
- b1 = red___val;
- b2 = red___val;
- b3 = red___val;
+ b1 = rescaleComp(srcComp, 0, dstComp, 0, lum___valF);
+ b2 = rescaleComp(srcComp, 0, dstComp, 1, lum___valF);
+ b3 = rescaleComp(srcComp, 0, dstComp, 2, lum___valF);
b4 = undef_val;
break;
- case ARGB8888:
- b1 = undef_val;
- b2 = red___val;
- b3 = red___val;
- b4 = red___val;
- break;
default:
- throw new InternalError("Unhandled format "+fmt);
+ throw new InternalError("Unhandled format "+dstFmt);
}
} else {
+ final int srcIdxR = srcComp.find(CType.R);
+ final int srcIdxG = srcComp.find(CType.G);
+ final int srcIdxB = srcComp.find(CType.B);
+ final int srcIdxA = srcComp.find(CType.A);
+ final boolean srcHasAlpha = 0 <= srcIdxA;
+ final boolean srcHasRGB = 0 <= srcIdxR && 0 <= srcIdxG && 0 <= srcIdxB;
// 1:1 values
- switch(fmt) {
+ switch(dstFmt) {
case LUMINANCE:
- if( srcComps > 1 ) {
- b1 = ( red___val + green_val+ blue__val ) / 3;
+ if( srcHasRGB ) {
+ final float rF = sourceNorm(srcComp, srcIdxR, red___valF);
+ final float gF = sourceNorm(srcComp, srcIdxG, green_valF);
+ final float bF = sourceNorm(srcComp, srcIdxB, blue__valF);
+ b1 = (byte)dstComp.fromFloat( ( rF + gF + bF ) / 3f, 0, false);
b2 = undef_val;
b3 = undef_val;
b4 = undef_val;
} else {
- b1 = red___val;
+ b1 = rescaleComp(srcComp, 0, dstComp, 0, red___valF);
b2 = undef_val;
b3 = undef_val;
b4 = undef_val;
}
break;
+ case RGB565:
+ u16 = dstComp.encode3CompI8(
+ rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF),
+ rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF),
+ rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF));
+ b1 = (byte)( u16 & 0xff );
+ b2 = (byte)( ( u16 >>> 8 ) & 0xff );
+ b3 = undef_val;
+ b4 = undef_val;
+ break;
+ case BGR565:
+ u16 = dstComp.encode3CompI8(
+ rescaleComp(srcComp, srcIdxB, dstComp, 0, blue__valF),
+ rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF),
+ rescaleComp(srcComp, srcIdxR, dstComp, 2, red___valF));
+ b1 = (byte)( u16 & 0xff );
+ b2 = (byte)( ( u16 >>> 8 ) & 0xff );
+ b3 = undef_val;
+ b4 = undef_val;
+ break;
+ case RGBA5551:
+ u16 = dstComp.encode4CompI8(
+ rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF),
+ rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF),
+ rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF),
+ srcHasAlpha ? rescaleComp(srcComp, srcIdxA, dstComp, 3, alpha_valF) : undef_val);
+ b1 = (byte)( u16 & 0xff );
+ b2 = (byte)( ( u16 >>> 8 ) & 0xff );
+ b3 = undef_val;
+ b4 = undef_val;
+ break;
+ case ABGR1555:
+ u16 = dstComp.encode4CompI8(
+ srcHasAlpha ? rescaleComp(srcComp, srcIdxA, dstComp, 0, alpha_valF) : undef_val,
+ rescaleComp(srcComp, srcIdxB, dstComp, 1, blue__valF),
+ rescaleComp(srcComp, srcIdxG, dstComp, 2, green_valF),
+ rescaleComp(srcComp, srcIdxR, dstComp, 3, red___valF) );
+ b1 = (byte)( u16 & 0xff );
+ b2 = (byte)( ( u16 >>> 8 ) & 0xff );
+ b3 = undef_val;
+ b4 = undef_val;
+ break;
+ case RGBx8888:
case RGB888:
- b1 = red___val;
- b2 = green_val;
- b3 = blue__val;
+ b1 = rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF);
+ b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF);
+ b3 = rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF);
b4 = undef_val;
break;
+ case BGRx8888:
case BGR888:
- b1 = blue__val;
- b2 = green_val;
- b3 = red___val;
+ b1 = rescaleComp(srcComp, srcIdxB, dstComp, 0, blue__valF);
+ b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF);
+ b3 = rescaleComp(srcComp, srcIdxR, dstComp, 2, red___valF);
b4 = undef_val;
break;
case RGBA8888:
- b1 = red___val;
- b2 = green_val;
- b3 = blue__val;
- b4 = srcComps > 3 ? alpha_val : undef_val;
+ b1 = rescaleComp(srcComp, srcIdxR, dstComp, 0, red___valF);
+ b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF);
+ b3 = rescaleComp(srcComp, srcIdxB, dstComp, 2, blue__valF);
+ if( srcHasAlpha ) {
+ b4 = rescaleComp(srcComp, srcIdxA, dstComp, 3, alpha_valF);
+ } else {
+ b4 = undef_val;
+ }
break;
case ABGR8888:
- b1 = srcComps > 3 ? alpha_val : undef_val;
- b2 = blue__val;
- b3 = green_val;
- b4 = red___val;
+ if( srcHasAlpha ) {
+ b1 = rescaleComp(srcComp, srcIdxA, dstComp, 0, alpha_valF);
+ } else {
+ b1 = undef_val;
+ }
+ b2 = rescaleComp(srcComp, srcIdxB, dstComp, 1, blue__valF);
+ b3 = rescaleComp(srcComp, srcIdxG, dstComp, 2, green_valF);
+ b4 = rescaleComp(srcComp, srcIdxR, dstComp, 3, red___valF);
break;
case BGRA8888:
- b1 = blue__val;
- b2 = green_val;
- b3 = red___val;
- b4 = srcComps > 3 ? alpha_val : undef_val;
+ b1 = rescaleComp(srcComp, srcIdxB, dstComp, 0, blue__valF);
+ b2 = rescaleComp(srcComp, srcIdxG, dstComp, 1, green_valF);
+ b3 = rescaleComp(srcComp, srcIdxR, dstComp, 2, red___valF);
+ if( srcHasAlpha ) {
+ b4 = rescaleComp(srcComp, srcIdxA, dstComp, 3, alpha_valF);
+ } else {
+ b4 = undef_val;
+ }
break;
case ARGB8888:
- b1 = srcComps > 3 ? alpha_val : undef_val;
- b2 = red___val;
- b3 = green_val;
- b4 = blue__val;
+ if( srcHasAlpha ) {
+ b1 = rescaleComp(srcComp, srcIdxA, dstComp, 0, alpha_valF);
+ } else {
+ b1 = undef_val;
+ }
+ b2 = rescaleComp(srcComp, srcIdxR, dstComp, 1, red___valF);
+ b3 = rescaleComp(srcComp, srcIdxG, dstComp, 2, green_valF);
+ b4 = rescaleComp(srcComp, srcIdxB, dstComp, 3, blue__valF);
break;
default:
- throw new InternalError("Unhandled format "+fmt);
+ throw new InternalError("Unhandled format "+dstFmt);
}
}
components[0] = b1;
@@ -193,85 +454,120 @@ public class TestPixelFormatUtil00NEWT extends UITestCase {
components[2] = b3;
components[3] = b4;
}
- private void testPNG00Impl(final int srcMinStrideInBytes, final ByteOrder srcByteOrder, final boolean srcIsGLOriented,
+ private void testConversionImpl(final int srcMinStrideInBytes, final ByteOrder srcByteOrder, final boolean srcIsGLOriented,
final int destMinStrideInBytes, final boolean destIsGLOriented)
throws InterruptedException, IOException, MalformedURLException
{
System.err.println("Test00: srcMinStrideInBytes "+srcMinStrideInBytes+", srcByteOrder "+srcByteOrder+", srcIsGLOriented "+srcIsGLOriented+
", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented);
- final PixelFormat[] formats = PixelFormat.values();
+ // final PixelFormat[] srcFormats = { PixelFormat.LUMINANCE };
+ // final PixelFormat[] dstFormats = { PixelFormat.RGBx8888 };
+ // final PixelFormat[] dstFormats = { PixelFormat.RGB5551 };
+ // final PixelFormat[] dstFormats = { PixelFormat.RGB888 };
+ // final PixelFormat[] srcFormats = { PixelFormat.RGB888 };
+ // final PixelFormat[] dstFormats = { PixelFormat.RGB565 };
+ final PixelFormat[] srcFormats = PixelFormat.values();
+ final PixelFormat[] dstFormats = PixelFormat.values();
final int width = 64, height = 64;
- for(int i=0; i<formats.length; i++) {
- final PixelFormat srcFmt = formats[i];
- final int srcBpp = srcFmt.bytesPerPixel();
+ for(int i=0; i<srcFormats.length; i++) {
+ final PixelFormat srcFmt = srcFormats[i];
+ final int srcBpp = srcFmt.comp.bytesPerPixel();
final int srcStrideBytes = Math.max(srcMinStrideInBytes, width*srcBpp);
final ByteBuffer srcPixels = ByteBuffer.allocate(height*srcStrideBytes).order(srcByteOrder);
- final byte[] srcComponents = new byte[4];
- getComponents(srcFmt.componentCount, srcFmt, srcComponents);
+ final byte[] srcData = new byte[4];
+ getComponentData(srcFmt, srcFmt, srcData);
for(int y=0; y<height; y++) {
int o = y*srcStrideBytes;
for(int x=0; x<width; x++) {
switch(srcFmt) {
case LUMINANCE:
- srcPixels.put(o++, srcComponents[0]);
+ srcPixels.put(o++, srcData[0]);
+ break;
+ case BGR565:
+ case RGB565:
+ case ABGR1555:
+ case RGBA5551:
+ srcPixels.put(o++, srcData[0]);
+ srcPixels.put(o++, srcData[1]);
break;
case RGB888:
case BGR888:
- srcPixels.put(o++, srcComponents[0]);
- srcPixels.put(o++, srcComponents[1]);
- srcPixels.put(o++, srcComponents[2]);
+ srcPixels.put(o++, srcData[0]);
+ srcPixels.put(o++, srcData[1]);
+ srcPixels.put(o++, srcData[2]);
break;
+ case RGBx8888:
+ case BGRx8888:
case RGBA8888:
case ABGR8888:
case BGRA8888:
case ARGB8888:
- srcPixels.put(o++, srcComponents[0]);
- srcPixels.put(o++, srcComponents[1]);
- srcPixels.put(o++, srcComponents[2]);
- srcPixels.put(o++, srcComponents[3]);
+ srcPixels.put(o++, srcData[0]);
+ srcPixels.put(o++, srcData[1]);
+ srcPixels.put(o++, srcData[2]);
+ srcPixels.put(o++, srcData[3]);
break;
default:
throw new InternalError("Unhandled format "+srcFmt);
}
}
}
- final PixelRectangle imageSrc = new PixelRectangle.GenericPixelRect(srcFmt, new Dimension(width, height), srcStrideBytes, srcIsGLOriented, srcPixels);
+ final PixelRectangle imageSrc = new PixelRectangle.GenericPixelRect(srcFmt, new Dimension(width, height),
+ srcStrideBytes, srcIsGLOriented, srcPixels);
+
System.err.println("CONVERT["+i+"][*]: Image0 - Orig: "+imageSrc);
- testComponents(imageSrc, 0, 0, srcComponents);
- testComponents(imageSrc, width-1, height-1, srcComponents);
+ System.err.printf("Source %s, %s%n", srcFmt, srcFmt.comp);
+ System.err.printf("Source Data: %s%n", Bitstream.toHexBinString(true, srcData, 0, srcFmt.comp.bytesPerPixel()));
+ testComponents(imageSrc, 0, 0, srcData, 0);
+ testComponents(imageSrc, width-1, height-1, srcData, 0);
- for(int j=0; j<formats.length; j++) {
- final PixelFormat destFmt = formats[j];
- System.err.println("CONVERT["+i+"]["+j+"]: "+srcFmt+" -> "+destFmt);
+ final int maxDelta = 12;
- final int destStrideBytes = Math.max(destMinStrideInBytes, width*destFmt.bytesPerPixel());
+ for(int j=0; j<dstFormats.length; j++) {
+ final PixelFormat destFmt = dstFormats[j];
+ System.err.println("CONVERT["+i+"]["+j+"]: "+srcFmt+" -> "+destFmt);
+ final int destStrideBytes = Math.max(destMinStrideInBytes, width*destFmt.comp.bytesPerPixel());
final byte[] destComponents = new byte[4];
- getComponents(srcFmt.componentCount, destFmt, destComponents);
- final PixelRectangle imageConv1 = PixelFormatUtil.convert32(imageSrc, destFmt, destStrideBytes, destIsGLOriented, false /* nio */);
- System.err.println("CONVERT["+i+"]["+j+"]: Conv1: "+imageConv1);
- testComponents(imageConv1, 0, 0, destComponents);
- testComponents(imageConv1, width-1, height-1, destComponents);
+ getComponentData(srcFmt, destFmt, destComponents);
+ System.err.printf("Source %s, %s%n", srcFmt, srcFmt.comp);
+ System.err.printf("Source Data: %s%n", Bitstream.toHexBinString(true, srcData, 0, srcFmt.comp.bytesPerPixel()));
+ System.err.printf("Dest %s, %s%n", destFmt, destFmt.comp);
+ System.err.printf("Dest Data: %s%n", Bitstream.toHexBinString(true, destComponents, 0, destFmt.comp.bytesPerPixel()));
+ final PixelRectangle imageConv1 = PixelFormatUtil.convert(imageSrc, destFmt, destStrideBytes, destIsGLOriented, false /* nio */);
+ System.err.println("CONVERT["+i+"]["+j+"]: Conv1: "+imageConv1+", maxDelta "+maxDelta);
+ System.err.printf("Conv1 Data: %s%n", Bitstream.toHexBinString(true, imageConv1.getPixels(), 0, destFmt.comp.bytesPerPixel()));
+ testComponents(imageConv1, 0, 0, destComponents, maxDelta);
+ testComponents(imageConv1, width-1, height-1, destComponents, maxDelta);
if( PixelFormat.LUMINANCE != srcFmt && PixelFormat.LUMINANCE == destFmt ) {
// Cannot convert: RGB* -> LUM -> RGB*
System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to RGB* -> LUM");
- } else if( srcFmt.componentCount > destFmt.componentCount ) {
+ } else if( srcFmt.comp.componenCount() > destFmt.comp.componenCount() ) {
// Cannot convert back if: src.componentCount > dest.componentCount
System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to src.componentCount > dest.componentCount");
} else {
- final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, imageSrc.getPixelformat(), imageSrc.getStride(), imageSrc.isGLOriented(), false /* nio */);
- System.err.println("CONVERT["+i+"]["+j+"]: Conv2: "+imageConv2);
- testComponents(imageConv2, 0, 0, srcComponents);
- testComponents(imageConv2, width-1, height-1, srcComponents);
+ final PixelRectangle imageConv2 = PixelFormatUtil.convert(imageConv1, imageSrc.getPixelformat(), imageSrc.getStride(), imageSrc.isGLOriented(), false /* nio */);
+ System.err.println("CONVERT["+i+"]["+j+"]: Conv2: "+imageConv2+", maxDelta "+maxDelta);
+ System.err.printf("Conv2 Data: %s%n", Bitstream.toHexBinString(true, imageConv2.getPixels(), 0, srcFmt.comp.bytesPerPixel()));
+ final byte[] destReComponents = new byte[4];
+ getComponentData(destFmt, srcFmt, destReComponents);
+ System.err.printf("DestRe Data: %s%n", Bitstream.toHexBinString(true, destReComponents, 0, srcFmt.comp.bytesPerPixel()));
+ testComponents(imageConv2, 0, 0, destReComponents, maxDelta);
+ testComponents(imageConv2, width-1, height-1, destReComponents, maxDelta);
+ /**
+ * Due to 'dead' components or value range re-scale,
+ * identity comparison on byte level is not correct.
+ *
if( imageSrc.getStride() == imageConv1.getStride() ) {
Assert.assertEquals(imageSrc.getPixels(), imageConv2.getPixels());
}
+ */
}
}
}
}
- private void dumpComponents(final PixelRectangle image, int x1, int y1, final int w, final int h) {
+ static void dumpComponents(final PixelRectangle image, int x1, int y1, final int w, final int h) {
if( x1 + w >= image.getSize().getWidth() ) {
x1 = image.getSize().getWidth() - w;
}
@@ -280,7 +576,7 @@ public class TestPixelFormatUtil00NEWT extends UITestCase {
}
System.err.print("PixelsBytes "+x1+"/"+y1+" "+w+"x"+h+":");
final ByteBuffer bb = image.getPixels();
- final int bpp = image.getPixelformat().bytesPerPixel();
+ final int bpp = image.getPixelformat().comp.bytesPerPixel();
for(int y = y1; y< y1+h; y++) {
System.err.printf("%n[%3d][%3d] ", x1, y);
int o = y * image.getStride()+x1*bpp;
@@ -311,51 +607,58 @@ public class TestPixelFormatUtil00NEWT extends UITestCase {
}
System.err.println();
}
- private void testComponents(final PixelRectangle image, final int x, final int y, final byte[] components) {
+
+ static final void assertEquals(final int a, final int b, final int maxDelta) {
+ final int d = Math.abs( a - b );
+ Assert.assertTrue(String.format("Not equal: abs(%s - %s) = %d, > %d maxDelta",
+ Bitstream.toHexBinString(true, a, 8), Bitstream.toHexBinString(true, b, 8), d, maxDelta),
+ d <= maxDelta);
+ }
+ static final boolean equals(final int a, final int b, final int maxDelta) {
+ final int d = Math.abs( a - b );
+ return d <= maxDelta;
+ }
+
+ /**
+ *
+ * @param image actual data
+ * @param x position in actual data
+ * @param y position in actual data
+ * @param expData expected data
+ * @param maxDelta the maximum delta between expected {@code components} and actual {@code image} data
+ */
+ static void testComponents(final PixelRectangle image, final int x, final int y, final byte[] expData, final int maxDelta) {
dumpComponents(image, x, y, 3, 3);
+ final PixelFormat.Composition imgComp = image.getPixelformat().comp;
final ByteBuffer bb = image.getPixels();
- final int bpp = image.getPixelformat().bytesPerPixel();
- int o = y * image.getStride()+x*bpp;
- switch(bpp) {
- case 1: {
- final byte c1 = bb.get(o++);
- final boolean equal = c1==components[0];
- System.err.printf("Test [%3d][%3d] exp 0x%02X == has 0x%02X : %b%n",
- x, y, components[0], c1, equal );
- Assert.assertEquals(components[0], c1);
- }
- break;
- case 2: {
- final byte c1 = bb.get(o++), c2 = bb.get(o++);
- final boolean equal = c1==components[0] && c2==components[1];
- System.err.printf("Test [%3d][%3d] exp 0x%02X%02X == has 0x%02X%02X : %b%n",
- x, y, components[1], components[0], c2, c1, equal );
- Assert.assertEquals(components[0], c1);
- Assert.assertEquals(components[1], c2);
- }
- break;
- case 3: {
- final byte c1 = bb.get(o++), c2 = bb.get(o++), c3 = bb.get(o++);
- final boolean equal = c1==components[0] && c2==components[1] && c3==components[2];
- System.err.printf("Test [%3d][%3d] exp 0x%02X%02X%02X == has 0x%02X%02X%02X : %b%n",
- x, y, components[2], components[1], components[0], c3, c2, c1, equal );
- Assert.assertEquals(components[0], c1);
- Assert.assertEquals(components[1], c2);
- Assert.assertEquals(components[2], c3);
- }
- break;
- case 4: {
- final byte c1 = bb.get(o++), c2 = bb.get(o++), c3 = bb.get(o++), c4 = bb.get(o++);
- final boolean equal = c1==components[0] && c2==components[1] && c3==components[2] && c4==components[3];
- System.err.printf("Test [%3d][%3d] exp 0x%02X%02X%02X%02X == has 0x%02X%02X%02X%02X : %b%n",
- x, y, components[3], components[2], components[1], components[0], c4, c3, c2, c1, equal );
- Assert.assertEquals(components[0], c1);
- Assert.assertEquals(components[1], c2);
- Assert.assertEquals(components[2], c3);
- Assert.assertEquals(components[3], c4);
- }
- break;
+ final int bytesPerPixel = imgComp.bytesPerPixel();
+ final int compCount = imgComp.componenCount();
+ final int[] compBitCount = imgComp.componentBitCount();
+
+ final int srcPixOffset = y * image.getStride()+x*bytesPerPixel;
+ final int bbPos = bb.position();
+ bb.position(bbPos+srcPixOffset);
+
+ final long srcPix64 = PixelFormatUtil.getShiftedI64(imgComp.bytesPerPixel(), bb, true);
+ final int[] srcComponents = new int[compCount];
+ final long expPix64 = PixelFormatUtil.getShiftedI64(imgComp.bytesPerPixel(), expData, 0);
+ final int[] expComponents = new int[compCount];
+ boolean equal = true;
+ for(int i=0; i<compCount; i++) {
+ srcComponents[i] = imgComp.decodeSingleI64(srcPix64, i);
+ expComponents[i] = imgComp.decodeSingleI64(expPix64, i);
+ equal = equal && equals(srcComponents[i], expComponents[i], maxDelta);
}
+ System.err.printf("Test [%3d][%3d] exp ", x, y);
+ for(int i=0; i<compCount; i++) { System.err.printf("%s ", Bitstream.toHexBinString(true, expComponents[i], compBitCount[i])); }
+ System.err.printf("==%nTest [%3d][%3d] has ", x, y);
+ for(int i=0; i<compCount; i++) { System.err.printf("%s ", Bitstream.toHexBinString(true, srcComponents[i], compBitCount[i])); }
+ System.err.printf(": equal %b%n%n", equal);
+ for(int i=0; i<compCount; i++) {
+ assertEquals(srcComponents[i], expComponents[i], maxDelta);
+ }
+
+ bb.position(bbPos);
}
public static void main(final String args[]) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java
index eba920032..37c8c4494 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java
@@ -40,6 +40,7 @@ import org.junit.Test;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
+import com.jogamp.common.util.Bitstream;
import com.jogamp.common.util.IOUtil;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.PNGPixelRect;
@@ -86,15 +87,21 @@ public class TestPixelFormatUtil01NEWT extends UITestCase {
final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), srcFmt, false /* directBuffer */, destMinStrideInBytes, false /* isGLOriented */);
System.err.println("PNGPixelRect - Orig: "+image1);
+ System.err.printf("Image Data: %s%n", Bitstream.toHexBinString(true, image1.getPixels(), 0, image1.getPixelformat().comp.bytesPerPixel()));
+ TestPixelFormatUtil00NEWT.dumpComponents(image1, 0, 0, 3, 3);
final PixelFormat[] formats = new PixelFormat[] { PixelFormat.RGBA8888, PixelFormat.ABGR8888, PixelFormat.BGRA8888, PixelFormat.ARGB8888 };
for(int i=0; i<formats.length; i++) {
final PixelFormat destFmt = formats[i];
System.err.println("CONVERT["+i+"]: "+srcFmt+" -> "+destFmt);
- final PixelRectangle imageConv1 = PixelFormatUtil.convert32(image1, destFmt, destMinStrideInBytes, destIsGLOriented, false /* nio */);
+ final PixelRectangle imageConv1 = PixelFormatUtil.convert(image1, destFmt, destMinStrideInBytes, destIsGLOriented, false /* nio */);
System.err.println("PNGPixelRect - Conv1: "+imageConv1);
- final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, image1.getPixelformat(), image1.getStride(), image1.isGLOriented(), false /* nio */);
+ System.err.printf("Conv1 Data: %s%n", Bitstream.toHexBinString(true, imageConv1.getPixels(), 0, imageConv1.getPixelformat().comp.bytesPerPixel()));
+ TestPixelFormatUtil00NEWT.dumpComponents(imageConv1, 0, 0, 3, 3);
+ final PixelRectangle imageConv2 = PixelFormatUtil.convert(imageConv1, image1.getPixelformat(), image1.getStride(), image1.isGLOriented(), false /* nio */);
System.err.println("PNGPixelRect - Conv2: "+imageConv2);
+ System.err.printf("Conv2 Data: %s%n", Bitstream.toHexBinString(true, imageConv2.getPixels(), 0, imageConv2.getPixelformat().comp.bytesPerPixel()));
+ TestPixelFormatUtil00NEWT.dumpComponents(imageConv2, 0, 0, 3, 3);
Assert.assertEquals(image1.getPixels(), imageConv2.getPixels());
}
}