summaryrefslogtreecommitdiffstats
path: root/src/nativewindow
diff options
context:
space:
mode:
Diffstat (limited to 'src/nativewindow')
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/GenericUpstreamSurfacelessHook.java88
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java93
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java7
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java28
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java4
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java8
-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/javax/media/nativewindow/util/SurfaceSize.java2
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java37
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java3
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java29
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java55
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java4
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java2
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java5
-rw-r--r--src/nativewindow/native/macosx/OSXmisc.m56
18 files changed, 1324 insertions, 252 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/GenericUpstreamSurfacelessHook.java b/src/nativewindow/classes/com/jogamp/nativewindow/GenericUpstreamSurfacelessHook.java
new file mode 100644
index 000000000..3fd5ad902
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/GenericUpstreamSurfacelessHook.java
@@ -0,0 +1,88 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.nativewindow;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+
+public class GenericUpstreamSurfacelessHook extends UpstreamSurfaceHookMutableSize {
+ /**
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)},
+ * not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)},
+ * not the actual dummy surface height,
+ * The latter is platform specific and small
+ */
+ public GenericUpstreamSurfacelessHook(final int width, final int height) {
+ super(width, height);
+ }
+
+ @Override
+ public final void create(final ProxySurface s) {
+ final AbstractGraphicsDevice device = s.getGraphicsConfiguration().getScreen().getDevice();
+ device.lock();
+ try {
+ if(0 == device.getHandle()) {
+ device.open();
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ if( 0 != s.getSurfaceHandle() ) {
+ throw new InternalError("Upstream surface not null: "+s);
+ }
+ s.addUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS |
+ ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE |
+ ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
+ } finally {
+ device.unlock();
+ }
+ }
+
+ @Override
+ public final void destroy(final ProxySurface s) {
+ if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ final AbstractGraphicsDevice device = s.getGraphicsConfiguration().getScreen().getDevice();
+ if( !s.containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS ) ) {
+ throw new InternalError("Owns upstream surface, but not a valid zero surface: "+s);
+ }
+ if( 0 != s.getSurfaceHandle() ) {
+ throw new InternalError("Owns upstream valid zero surface, but non zero surface: "+s);
+ }
+ device.lock();
+ try {
+ s.clearUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS | ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ } finally {
+ device.unlock();
+ }
+ }
+ }
+}
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/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index 6498ebd1e..32e4add75 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -37,6 +37,7 @@
package com.jogamp.nativewindow.awt;
+import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.awt.AWTEDTExecutor;
import com.jogamp.common.util.locks.LockFactory;
@@ -558,7 +559,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
surfaceLock.unlock();
if(DEBUG) {
System.err.println("JAWTWindow: Can't lock surface, component peer n/a. Component displayable "+component.isDisplayable()+", "+component);
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
} else {
determineIfApplet();
@@ -765,7 +766,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
// avoid deadlock ..
if(DEBUG) {
System.err.println("Warning: JAWT Lock hold, but not the AWT tree lock: "+this);
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
if( null == storage ) {
storage = new Point();
@@ -788,7 +789,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
if(LOCK_SURFACE_NOT_READY == lockRes) {
if(DEBUG) {
System.err.println("Warning: JAWT Lock couldn't be acquired: "+this);
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
return null;
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
index d21994ea5..a38a48b85 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java
@@ -34,11 +34,14 @@ package com.jogamp.nativewindow.egl;
import javax.media.nativewindow.*;
+import com.jogamp.common.util.VersionNumber;
+
/** Encapsulates a graphics device on EGL platforms.
*/
public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
- final long[] nativeDisplayID = new long[1];
- /* final */ EGLDisplayLifecycleCallback eglLifecycleCallback;
+ private final long[] nativeDisplayID = new long[1];
+ private /* final */ EGLDisplayLifecycleCallback eglLifecycleCallback;
+ private VersionNumber eglVersion = VersionNumber.zeroVersion;
/**
* Hack to allow inject a EGL termination call.
@@ -52,9 +55,11 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
* Implementation should issue an <code>EGL.eglGetDisplay(nativeDisplayID)</code>
* inclusive <code>EGL.eglInitialize(eglDisplayHandle, ..)</code> call.
* @param nativeDisplayID in/out array of size 1, passing the requested nativeVisualID, may return a different revised nativeVisualID handle
+ * @param major out array for EGL major version
+ * @param minor out array for EGL minor version
* @return the initialized EGL display ID, or <code>0</code> if not successful
*/
- public long eglGetAndInitDisplay(long[] nativeDisplayID);
+ public long eglGetAndInitDisplay(final long[] nativeDisplayID, final int[] major, final int[] minor);
/**
* Implementation should issue an <code>EGL.eglTerminate(eglDisplayHandle)</code> call.
@@ -79,6 +84,9 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
this.eglLifecycleCallback = eglLifecycleCallback;
}
+ /** EGL server version as returned by {@code eglInitialize(..)}. Only valid after {@link #open()}. */
+ public VersionNumber getEGLVersion() { return eglVersion; }
+
public long getNativeDisplayID() { return nativeDisplayID[0]; }
@Override
@@ -98,11 +106,16 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
if(DEBUG) {
System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.open(): "+this);
}
- handle = eglLifecycleCallback.eglGetAndInitDisplay(nativeDisplayID);
+ final int[] major = { 0 };
+ final int[] minor = { 0 };
+ handle = eglLifecycleCallback.eglGetAndInitDisplay(nativeDisplayID, major, minor);
if(0 == handle) {
+ eglVersion = VersionNumber.zeroVersion;
throw new NativeWindowException("EGLGraphicsDevice.open() failed: "+this);
+ } else {
+ eglVersion = new VersionNumber(major[0], minor[0], 0);
+ return true;
}
- return true;
}
return false;
}
@@ -142,5 +155,10 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
eglLifecycleCallback = (EGLDisplayLifecycleCallback) newOwnership;
return oldOwnership;
}
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()+"[type "+getType()+", v"+eglVersion+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", owner "+isHandleOwner()+", "+toolkitLock+"]";
+ }
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
index 3f8113baa..c73f544b0 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java
@@ -33,7 +33,9 @@
package javax.media.nativewindow;
+import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.util.ReflectionUtil;
+
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.DefaultGraphicsConfigurationFactoryImpl;
@@ -226,7 +228,7 @@ public abstract class GraphicsConfigurationFactory {
throw new IllegalArgumentException("Given capabilities class must implement CapabilitiesImmutable");
}
if(DEBUG) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
System.err.println("GraphicsConfigurationFactory.getFactory: "+deviceType.getName()+", "+capabilitiesType.getName());
dumpFactories();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
index 7a69b9a40..377dd55cd 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
@@ -65,6 +65,14 @@ public interface ProxySurface extends MutableSurface {
*/
public static final int OPT_UPSTREAM_WINDOW_INVISIBLE = 1 << 8;
+ /**
+ * Implementation specific bitvalue stating the upstream's {@link NativeSurface}'s zero handle is valid.
+ * @see #addUpstreamOptionBits(int)
+ * @see #clearUpstreamOptionBits(int)
+ * @see #getUpstreamOptionBits()
+ */
+ public static final int OPT_UPSTREAM_SURFACELESS = 1 << 9;
+
/** Allow redefining the AbstractGraphicsConfiguration */
public void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg);
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/javax/media/nativewindow/util/SurfaceSize.java b/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java
index 601e6dd71..fe1fa3b9d 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java
@@ -105,7 +105,7 @@ public class SurfaceSize implements Comparable<SurfaceSize> {
@Override
public final int hashCode() {
// 31 * x == (x << 5) - x
- int hash = 31 + getResolution().hashCode();
+ int hash = getResolution().hashCode();
hash = ((hash << 5) - hash) + getBitsPerPixel();
return hash;
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
index deb685b51..10d957186 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
@@ -28,6 +28,8 @@
package jogamp.nativewindow;
+import java.io.PrintStream;
+
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
@@ -279,6 +281,13 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
sink.append("WINDOW_INVISIBLE");
needsOr = true;
}
+ if( 0 != ( implBitfield & OPT_UPSTREAM_SURFACELESS ) ) {
+ if(needsOr) {
+ sink.append(" | ");
+ }
+ sink.append("SURFACELESS");
+ needsOr = true;
+ }
sink.append(" ]");
return sink;
}
@@ -297,6 +306,34 @@ public abstract class ProxySurfaceImpl implements ProxySurface {
@Override
public final void clearUpstreamOptionBits(final int v) { implBitfield &= ~v; }
+ public static void dumpHierarchy(final PrintStream out, final ProxySurface s) {
+ out.println("Surface Hierarchy of "+s.getClass().getName());
+ dumpHierarchy(out, s, "");
+ out.println();
+ }
+ private static void dumpHierarchy(final PrintStream out, final NativeSurface s, String indentation) {
+ indentation = indentation + " ";
+ out.println(indentation+"Surface device "+s.getGraphicsConfiguration().getScreen().getDevice());
+ out.println(indentation+"Surface size "+s.getSurfaceWidth()+"x"+s.getSurfaceHeight()+", handle 0x"+Long.toHexString(s.getSurfaceHandle()));
+ if( s instanceof ProxySurfaceImpl ) {
+ final ProxySurface ps = (ProxySurface)s;
+ out.println(indentation+"Upstream options "+ps.getUpstreamOptionBits(null).toString());
+
+ final UpstreamSurfaceHook psUSH = ps.getUpstreamSurfaceHook();
+ if( null != psUSH ) {
+ out.println(indentation+"Upstream Hook "+psUSH.getClass().getName());
+ final NativeSurface upstreamSurface = psUSH.getUpstreamSurface();
+ indentation = indentation + " ";
+ if( null != upstreamSurface ) {
+ out.println(indentation+"Upstream Hook's Surface "+upstreamSurface.getClass().getName());
+ dumpHierarchy(out, upstreamSurface, indentation);
+ } else {
+ out.println(indentation+"Upstream Hook's Surface NULL");
+ }
+ }
+ }
+ }
+
@Override
public StringBuilder toString(StringBuilder sink) {
if(null == sink) {
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java
index 881fd56a6..b187921e4 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/SharedResourceToolkitLock.java
@@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import javax.media.nativewindow.ToolkitLock;
+import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.util.LongObjectHashMap;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
@@ -63,7 +64,7 @@ public class SharedResourceToolkitLock implements ToolkitLock {
if(DEBUG || verbose || handle2Lock.size() > 0 ) {
System.err.println("SharedResourceToolkitLock: Shutdown (open: "+handle2Lock.size()+")");
if(DEBUG) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
if( handle2Lock.size() > 0) {
dumpOpenDisplayConnections();
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/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index cf163bd82..9af74d9f5 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -31,6 +31,8 @@ import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
import com.jogamp.common.util.Function;
import com.jogamp.common.util.FunctionTask;
@@ -107,6 +109,58 @@ public class OSXUtil implements ToolkitProperties {
return (Insets) GetInsets0(windowOrView);
}
+ /**
+ * Returns the pixel-scale of the NSScreen, with the highest
+ * {@link RectangleImmutable#coverage(RectangleImmutable) coverage} of the given rectangle in window units.
+ * <p>
+ * If no coverage is detected the pixel-scale of the first NSScreen is returned.
+ * </p>
+ * @param r arbitrary rectangle in window units
+ * @param screenIndexOut storage returning the native screen index containing the given rectangle
+ */
+ public static double GetPixelScale(final RectangleImmutable r, final int[] screenIndexOut) {
+ if( DEBUG ) {
+ System.err.printf("GetPixelScale covering %s%n", r.toString());
+ }
+ final int screenCount;
+ final RectangleImmutable[] screenBounds;
+ final double[] pixelScales;
+ {
+ final double[] sd = GetScreenData0();
+ if( 0 != sd.length % 5 ) {
+ throw new InternalError("GetScreenData0 didn't return multiple of 5 but "+sd.length);
+ }
+ screenCount = sd.length / 5;
+ screenBounds = new RectangleImmutable[screenCount];
+ pixelScales = new double[screenCount] ;
+ for(int i=0; i<screenCount; i++) {
+ final int j = i*5;
+ pixelScales[i] = sd[j+0];
+ screenBounds[i] = new Rectangle((int)sd[j+1], (int)sd[j+2], (int)sd[j+3], (int)sd[j+4]);
+ if( DEBUG ) {
+ System.err.printf("GetPixelScale.Screen[%d]: scale %f, bounds[%f / %f %f x %f]%n",
+ i, pixelScales[i], sd[j+1], sd[j+2], sd[j+3], sd[j+4]);
+ }
+ }
+ }
+ double pixelScale = pixelScales[0];
+ screenIndexOut[0] = 0;
+ float maxCoverage = Float.MIN_VALUE;
+ for(int i=screenCount-1; i>=0; i--) {
+ final RectangleImmutable sb = screenBounds[i];
+ final float coverage = sb.coverage(r);
+ if( coverage > maxCoverage ) {
+ maxCoverage = coverage;
+ screenIndexOut[0] = i;
+ pixelScale = pixelScales[i];
+ }
+ }
+ if( DEBUG ) {
+ System.err.printf("GetPixelScale Result: screen %d, scale %f%n%n", screenIndexOut[0], pixelScale);
+ }
+ return pixelScale;
+ }
+
public static double GetPixelScale(final int screenIndex) {
return GetPixelScale0(screenIndex);
}
@@ -393,6 +447,7 @@ public class OSXUtil implements ToolkitProperties {
private static native boolean isNSWindow0(long object);
private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y);
private static native Object GetInsets0(long windowOrView);
+ private static native double[] GetScreenData0();
private static native double GetPixelScale0(int screenIndex);
private static native double GetPixelScale1(long windowOrView);
private static native long CreateNSWindow0(int x, int y, int width, int height);
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
index c409b6a39..b3cd977d4 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIUtil.java
@@ -31,6 +31,8 @@ import javax.media.nativewindow.util.Point;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.NativeWindowFactory;
+import com.jogamp.common.ExceptionUtils;
+
import jogamp.nativewindow.NWJNILibLoader;
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.ToolkitProperties;
@@ -132,7 +134,7 @@ public class GDIUtil implements ToolkitProperties {
SetProcessThreadsAffinityMask0(affinityMask, verbose);
}
- private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
+ private static final void dumpStack() { ExceptionUtils.dumpStack(System.err); } // Callback for JNI
/** Creates WNDCLASSEX instance */
static native boolean CreateWindowClass0(long hInstance, String clazzName, long wndProc, long iconSmallHandle, long iconBigHandle);
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
index 7e61ba6d0..1b3b207f6 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
@@ -44,7 +44,7 @@ public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize
s.setSurfaceHandle(windowHandle);
s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
}
- s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ s.addUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
} finally {
device.unlock();
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index 2414248b4..786be7cd7 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -45,6 +45,7 @@ import jogamp.nativewindow.Debug;
import jogamp.nativewindow.NWJNILibLoader;
import jogamp.nativewindow.ToolkitProperties;
+import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.util.LongObjectHashMap;
import com.jogamp.common.util.PropertyAccess;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
@@ -196,7 +197,7 @@ public class X11Util implements ToolkitProperties {
", pending (open in creation order): "+pendingDisplayList.size()+
")");
if(DEBUG) {
- Thread.dumpStack();
+ ExceptionUtils.dumpStack(System.err);
}
if( openDisplayList.size() > 0) {
X11Util.dumpOpenDisplayConnections();
@@ -615,7 +616,7 @@ public class X11Util implements ToolkitProperties {
}
private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI
- private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
+ private static final void dumpStack() { ExceptionUtils.dumpStack(System.err); } // Callback for JNI
private static native boolean initialize0(boolean debug);
private static native void shutdown0();
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index 127b329d1..997bafba0 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -249,6 +249,62 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0
return res;
}
+static CGDirectDisplayID GetCGDirectDisplayIDByNSScreen(NSScreen *screen) {
+ // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?!
+ NSDictionary * dict = [screen deviceDescription];
+ NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"];
+ // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size
+ return (CGDirectDisplayID) [val integerValue];
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetScreenData0
+ * Signature: ()[F
+ */
+JNIEXPORT jdoubleArray JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenData0
+ (JNIEnv *env, jclass unused)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ CGFloat pixelScale;
+ CGDirectDisplayID display;
+ NSRect dBounds;
+ NSScreen *screen;
+ NSArray *screens = [NSScreen screens];
+ int sCount = [screens count];
+ jdouble res[sCount*5];
+ int i,j;
+
+ for(i=0; i<sCount; i++) {
+ j = i*5;
+ screen = (NSScreen *) [screens objectAtIndex: i];
+ pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen backingScaleFactor]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+ display = GetCGDirectDisplayIDByNSScreen(screen);
+ dBounds = CGDisplayBounds (display); // origin top-left
+ res[j+0] = (jdouble)pixelScale;
+ res[j+1] = (jdouble)dBounds.origin.x;
+ res[j+2] = (jdouble)dBounds.origin.y;
+ res[j+3] = (jdouble)dBounds.size.width;
+ res[j+4] = (jdouble)dBounds.size.height;
+ }
+
+ jdoubleArray jniRes = (*env)->NewDoubleArray(env, sCount*5); // x,y,w,h,scale
+ if (jniRes == NULL) {
+ NativewindowCommon_throwNewRuntimeException(env, "Could not allocate double array of size %d", sCount*5);
+ }
+ (*env)->SetDoubleArrayRegion(env, jniRes, 0, sCount*5, res);
+
+ [pool release];
+
+ return jniRes;
+}
+
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: GetPixelScale0