aboutsummaryrefslogtreecommitdiffstats
path: root/src/nativewindow/classes/com
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2015-02-02 02:38:55 +0100
committerSven Gothel <[email protected]>2015-02-02 02:38:55 +0100
commit78b4918b207e16b967e8335fb8ec1b31c706c507 (patch)
tree736cf80d089eb5e9df7f349035936daaa78f230d /src/nativewindow/classes/com
parent1ec82447e464d5308442581f14d32f9775928454 (diff)
Bug 682 - Relocating javax.media.opengl.* -> com.jogamp.opengl.* (Part 2)
Relocation javax.media.nativewindow.* -> com.jogamp.nativewindow.* Relocation javax.media.opengl.* -> com.jogamp.opengl.*
Diffstat (limited to 'src/nativewindow/classes/com')
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsConfiguration.java81
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsDevice.java166
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsScreen.java57
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/Capabilities.java414
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesChooser.java70
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesImmutable.java139
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/DefaultCapabilitiesChooser.java172
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsConfiguration.java134
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsDevice.java253
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsScreen.java71
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/GraphicsConfigurationFactory.java435
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/MutableSurface.java44
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/NativeSurface.java238
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/NativeSurfaceHolder.java41
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/NativeWindow.java204
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowException.java68
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java716
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/OffscreenLayerOption.java61
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/OffscreenLayerSurface.java86
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/ProxySurface.java135
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/ScalableSurface.java107
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/SurfaceUpdatedListener.java51
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/ToolkitLock.java78
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHook.java66
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/VisualIDHolder.java136
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/WindowClosingProtocol.java73
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/package.html101
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/Dimension.java128
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/DimensionImmutable.java68
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/Insets.java136
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/InsetsImmutable.java71
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/PixelFormat.java739
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/PixelFormatUtil.java600
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/PixelRectangle.java194
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/Point.java190
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/PointImmutable.java63
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/Rectangle.java237
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/RectangleImmutable.java87
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/util/SurfaceSize.java113
39 files changed, 6823 insertions, 0 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsConfiguration.java
new file mode 100644
index 000000000..684f1f86a
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsConfiguration.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.nativewindow;
+
+/** A marker interface describing a graphics configuration, visual, or
+ pixel format in a toolkit-independent manner. */
+public interface AbstractGraphicsConfiguration extends VisualIDHolder, Cloneable {
+ public Object clone();
+
+ /**
+ * Return the screen this graphics configuration is valid for
+ */
+ public AbstractGraphicsScreen getScreen();
+
+ /**
+ * Return the capabilities reflecting this graphics configuration,
+ * which may differ from the capabilities used to choose this configuration.
+ *
+ * @return An immutable instance of the Capabilities to avoid mutation by
+ * the user.
+ */
+ public CapabilitiesImmutable getChosenCapabilities();
+
+ /**
+ * Return the capabilities used to choose this graphics configuration.
+ *
+ * These may be used to reconfigure the NativeWindow in case
+ * the device changes in a multiple screen environment.
+ *
+ * @return An immutable instance of the Capabilities to avoid mutation by
+ * the user.
+ */
+ public CapabilitiesImmutable getRequestedCapabilities();
+
+ /**
+ * In case the implementation utilizes a delegation pattern to wrap abstract toolkits,
+ * this method shall return the native {@link AbstractGraphicsConfiguration},
+ * otherwise this instance.
+ * @see NativeSurface#getGraphicsConfiguration()
+ */
+ public AbstractGraphicsConfiguration getNativeGraphicsConfiguration();
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsDevice.java
new file mode 100644
index 000000000..7b630b1ea
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsDevice.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.nativewindow;
+
+import jogamp.nativewindow.Debug;
+
+/** A interface describing a graphics device in a
+ toolkit-independent manner.
+ */
+public interface AbstractGraphicsDevice extends Cloneable {
+ public static final boolean DEBUG = Debug.debug("GraphicsDevice");
+
+ /** Dummy connection value for a default connection where no native support for multiple devices is available */
+ public static String DEFAULT_CONNECTION = "decon";
+
+ /** Dummy connection value for an external connection where no native support for multiple devices is available */
+ public static String EXTERNAL_CONNECTION = "excon";
+
+ /** Default unit id for the 1st device: 0 */
+ public static int DEFAULT_UNIT = 0;
+
+ public Object clone();
+
+ /**
+ * Returns the type of the underlying subsystem, ie
+ * NativeWindowFactory.TYPE_KD, NativeWindowFactory.TYPE_X11, ..
+ */
+ public String getType();
+
+ /**
+ * Returns the semantic GraphicsDevice connection.<br>
+ * On platforms supporting remote devices, eg via tcp/ip network,
+ * the implementation shall return a unique name for each remote address.<br>
+ * On X11 for example, the connection string should be as the following example.<br>
+ * <ul>
+ * <li><code>:0.0</code> for a local connection</li>
+ * <li><code>remote.host.net:0.0</code> for a remote connection</li>
+ * </ul>
+ *
+ * To support multiple local device, see {@link #getUnitID()}.
+ */
+ public String getConnection();
+
+ /**
+ * Returns the graphics device <code>unit ID</code>.<br>
+ * The <code>unit ID</code> support multiple graphics device configurations
+ * on a local machine.<br>
+ * To support remote device, see {@link #getConnection()}.
+ * @return
+ */
+ public int getUnitID();
+
+ /**
+ * Returns a unique ID object of this device using {@link #getType() type},
+ * {@link #getConnection() connection} and {@link #getUnitID() unitID} as it's key components.
+ * <p>
+ * The unique ID does not reflect the instance of the device, hence the handle is not included.
+ * The unique ID may be used as a key for semantic device mapping.
+ * </p>
+ * <p>
+ * The returned string object reference is unique using {@link String#intern()}
+ * and hence can be used as a key itself.
+ * </p>
+ */
+ public String getUniqueID();
+
+ /**
+ * Returns the native handle of the underlying native device,
+ * if such thing exist.
+ */
+ public long getHandle();
+
+ /**
+ * Optionally locking the device, utilizing eg {@link com.jogamp.nativewindow.ToolkitLock#lock()}.
+ * The lock implementation must be recursive.
+ */
+ public void lock();
+
+ /**
+ * Optionally unlocking the device, utilizing eg {@link com.jogamp.nativewindow.ToolkitLock#unlock()}.
+ * The lock implementation must be recursive.
+ *
+ * @throws RuntimeException in case the lock is not acquired by this thread.
+ */
+ public void unlock();
+
+ /**
+ * @throws RuntimeException if current thread does not hold the lock
+ */
+ public void validateLocked() throws RuntimeException;
+
+ /**
+ * Optionally [re]opening the device if handle is <code>null</code>.
+ * <p>
+ * The default implementation is a <code>NOP</code>.
+ * </p>
+ * <p>
+ * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
+ * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
+ * issue the native open operation in case handle is <code>null</code>.
+ * </p>
+ *
+ * @return true if the handle was <code>null</code> and opening was successful, otherwise false.
+ */
+ public boolean open();
+
+ /**
+ * Optionally closing the device if handle is not <code>null</code>.
+ * <p>
+ * The default implementation {@link ToolkitLock#dispose() dispose} it's {@link ToolkitLock} and sets the handle to <code>null</code>.
+ * </p>
+ * <p>
+ * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
+ * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
+ * issue the native close operation or skip it depending on the {@link #isHandleOwner() handles's ownership}.
+ * </p>
+ *
+ * @return true if the handle was not <code>null</code> and closing was successful, otherwise false.
+ */
+ public boolean close();
+
+ /**
+ * @return <code>true</code> if instance owns the handle to issue {@link #close()}, otherwise <code>false</code>.
+ */
+ public boolean isHandleOwner();
+
+ public void clearHandleOwner();
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsScreen.java b/src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsScreen.java
new file mode 100644
index 000000000..7767cf9e4
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/AbstractGraphicsScreen.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.nativewindow;
+
+/** A interface describing a graphics screen in a
+ toolkit-independent manner.
+ */
+
+public interface AbstractGraphicsScreen extends Cloneable {
+ public Object clone();
+
+ /**
+ * Return the device this graphics configuration is valid for
+ */
+ public AbstractGraphicsDevice getDevice();
+
+ /** Returns the screen index this graphics screen is valid for
+ */
+ public int getIndex();
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/Capabilities.java b/src/nativewindow/classes/com/jogamp/nativewindow/Capabilities.java
new file mode 100644
index 000000000..fa172b201
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/Capabilities.java
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.nativewindow;
+
+/** Specifies a set of capabilities that a window's rendering context
+ must support, such as color depth per channel. It currently
+ contains the minimal number of routines which allow configuration
+ on all supported window systems. */
+public class Capabilities implements CapabilitiesImmutable, Cloneable {
+ protected final static String na_str = "----" ;
+
+ private int redBits = 8;
+ private int greenBits = 8;
+ private int blueBits = 8;
+ private int alphaBits = 0;
+
+ // Support for transparent windows containing OpenGL content
+ private boolean backgroundOpaque = true;
+ private int transparentValueRed = 0;
+ private int transparentValueGreen = 0;
+ private int transparentValueBlue = 0;
+ private int transparentValueAlpha = 0;
+
+ // Switch for on- or offscreen
+ private boolean onscreen = true;
+
+ // offscreen bitmap mode
+ private boolean isBitmap = false;
+
+ /** Creates a Capabilities object. All attributes are in a default
+ state.
+ */
+ public Capabilities() {}
+
+ @Override
+ public Object cloneMutable() {
+ return clone();
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (final CloneNotSupportedException e) {
+ throw new NativeWindowException(e);
+ }
+ }
+
+ /**
+ * Copies all {@link Capabilities} values
+ * from <code>source</code> into this instance.
+ * @return this instance
+ */
+ public Capabilities copyFrom(final CapabilitiesImmutable other) {
+ redBits = other.getRedBits();
+ greenBits = other.getGreenBits();
+ blueBits = other.getBlueBits();
+ alphaBits = other.getAlphaBits();
+ backgroundOpaque = other.isBackgroundOpaque();
+ onscreen = other.isOnscreen();
+ isBitmap = other.isBitmap();
+ transparentValueRed = other.getTransparentRedValue();
+ transparentValueGreen = other.getTransparentGreenValue();
+ transparentValueBlue = other.getTransparentBlueValue();
+ transparentValueAlpha = other.getTransparentAlphaValue();
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + this.redBits;
+ hash = ((hash << 5) - hash) + ( this.onscreen ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( this.isBitmap ? 1 : 0 );
+ hash = ((hash << 5) - hash) + this.greenBits;
+ hash = ((hash << 5) - hash) + this.blueBits;
+ hash = ((hash << 5) - hash) + this.alphaBits;
+ hash = ((hash << 5) - hash) + ( this.backgroundOpaque ? 1 : 0 );
+ hash = ((hash << 5) - hash) + this.transparentValueRed;
+ hash = ((hash << 5) - hash) + this.transparentValueGreen;
+ hash = ((hash << 5) - hash) + this.transparentValueBlue;
+ hash = ((hash << 5) - hash) + this.transparentValueAlpha;
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if(!(obj instanceof CapabilitiesImmutable)) {
+ return false;
+ }
+ final CapabilitiesImmutable other = (CapabilitiesImmutable)obj;
+ boolean res = other.getRedBits()==redBits &&
+ other.getGreenBits()==greenBits &&
+ other.getBlueBits()==blueBits &&
+ other.getAlphaBits()==alphaBits &&
+ other.isBackgroundOpaque()==backgroundOpaque &&
+ other.isOnscreen()==onscreen &&
+ other.isBitmap()==isBitmap;
+ if(res && !backgroundOpaque) {
+ res = other.getTransparentRedValue()==transparentValueRed &&
+ other.getTransparentGreenValue()==transparentValueGreen &&
+ other.getTransparentBlueValue()==transparentValueBlue &&
+ other.getTransparentAlphaValue()==transparentValueAlpha;
+ }
+
+ return res;
+ }
+
+ /**
+ * Comparing RGBA values only
+ **/
+ @Override
+ public int compareTo(final CapabilitiesImmutable caps) {
+ /**
+ if ( ! ( o instanceof CapabilitiesImmutable ) ) {
+ Class<?> c = (null != o) ? o.getClass() : null ;
+ throw new ClassCastException("Not a CapabilitiesImmutable object, but " + c);
+ }
+ final CapabilitiesImmutable caps = (CapabilitiesImmutable) o; */
+
+ final int rgba = redBits * greenBits * blueBits * ( alphaBits + 1 );
+
+ final int xrgba = caps.getRedBits() * caps.getGreenBits() * caps.getBlueBits() * ( caps.getAlphaBits() + 1 );
+
+ if(rgba > xrgba) {
+ return 1;
+ } else if(rgba < xrgba) {
+ return -1;
+ }
+
+ return 0; // they are equal: RGBA
+ }
+
+ @Override
+ public int getVisualID(final VIDType type) throws NativeWindowException {
+ switch(type) {
+ case INTRINSIC:
+ case NATIVE:
+ return VisualIDHolder.VID_UNDEFINED;
+ default:
+ throw new NativeWindowException("Invalid type <"+type+">");
+ }
+ }
+
+ @Override
+ public final int getRedBits() {
+ return redBits;
+ }
+
+ /** Sets the number of bits requested for the color buffer's red
+ component. On some systems only the color depth, which is the
+ sum of the red, green, and blue bits, is considered. */
+ public void setRedBits(final int redBits) {
+ this.redBits = redBits;
+ }
+
+ @Override
+ public final int getGreenBits() {
+ return greenBits;
+ }
+
+ /** Sets the number of bits requested for the color buffer's green
+ component. On some systems only the color depth, which is the
+ sum of the red, green, and blue bits, is considered. */
+ public void setGreenBits(final int greenBits) {
+ this.greenBits = greenBits;
+ }
+
+ @Override
+ public final int getBlueBits() {
+ return blueBits;
+ }
+
+ /** Sets the number of bits requested for the color buffer's blue
+ component. On some systems only the color depth, which is the
+ sum of the red, green, and blue bits, is considered. */
+ public void setBlueBits(final int blueBits) {
+ this.blueBits = blueBits;
+ }
+
+ @Override
+ public final int getAlphaBits() {
+ return alphaBits;
+ }
+
+ /**
+ * Sets the number of bits requested for the color buffer's alpha
+ * component. On some systems only the color depth, which is the
+ * sum of the red, green, and blue bits, is considered.
+ * <p>
+ * <b>Note:</b> If alpha bits are <code>zero</code>, they are set to <code>one</code>
+ * by {@link #setBackgroundOpaque(boolean)} and it's OpenGL specialization <code>GLCapabilities::setSampleBuffers(boolean)</code>.<br/>
+ * Ensure to call this method after the above to ensure a <code>zero</code> value.</br>
+ * The above automated settings takes into account, that the user calls this method to <i>request</i> alpha bits,
+ * not to <i>reflect</i> a current state. Nevertheless if this is the case - call it at last.
+ * </p>
+ */
+ public void setAlphaBits(final int alphaBits) {
+ this.alphaBits = alphaBits;
+ }
+
+ /**
+ * Sets whether the surface shall be opaque or translucent.
+ * <p>
+ * Platform implementations may need an alpha component in the surface (eg. Windows),
+ * or expect pre-multiplied alpha values (eg. X11/XRender).<br>
+ * To unify the experience, this method also invokes {@link #setAlphaBits(int) setAlphaBits(1)}
+ * if {@link #getAlphaBits()} == 0.<br>
+ * Please note that in case alpha is required on the platform the
+ * clear color shall have an alpha lower than 1.0 to allow anything shining through.
+ * </p>
+ * <p>
+ * Mind that translucency may cause a performance penalty
+ * due to the composite work required by the window manager.
+ * </p>
+ */
+ public void setBackgroundOpaque(final boolean opaque) {
+ backgroundOpaque = opaque;
+ if(!opaque && getAlphaBits()==0) {
+ setAlphaBits(1);
+ }
+ }
+
+ @Override
+ public final boolean isBackgroundOpaque() {
+ return backgroundOpaque;
+ }
+
+ /**
+ * Sets whether the surface shall be on- or offscreen.
+ * <p>
+ * Defaults to true.
+ * </p>
+ * <p>
+ * If requesting an offscreen surface without further selection of it's mode,
+ * e.g. FBO, Pbuffer or {@link #setBitmap(boolean) bitmap},
+ * the implementation will choose the best available offscreen mode.
+ * </p>
+ * @param onscreen
+ */
+ public void setOnscreen(final boolean onscreen) {
+ this.onscreen=onscreen;
+ }
+
+ @Override
+ public final boolean isOnscreen() {
+ return onscreen;
+ }
+
+ /**
+ * Requesting offscreen bitmap mode.
+ * <p>
+ * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
+ * </p>
+ * <p>
+ * Defaults to false.
+ * </p>
+ * <p>
+ * Requesting offscreen bitmap mode disables the offscreen auto selection.
+ * </p>
+ */
+ public void setBitmap(final boolean enable) {
+ if(enable) {
+ setOnscreen(false);
+ }
+ isBitmap = enable;
+ }
+
+ @Override
+ public boolean isBitmap() {
+ return isBitmap;
+ }
+
+ @Override
+ public final int getTransparentRedValue() { return transparentValueRed; }
+
+ @Override
+ public final int getTransparentGreenValue() { return transparentValueGreen; }
+
+ @Override
+ public final int getTransparentBlueValue() { return transparentValueBlue; }
+
+ @Override
+ public final int getTransparentAlphaValue() { return transparentValueAlpha; }
+
+ /** Sets the transparent red value for the frame buffer configuration,
+ ranging from 0 to the maximum frame buffer value for red.
+ This value is ignored if {@link #isBackgroundOpaque()} equals true.<br>
+ It defaults to half of the frambuffer value for red. <br>
+ A value of -1 is interpreted as any value. */
+ public void setTransparentRedValue(final int transValueRed) { transparentValueRed=transValueRed; }
+
+ /** Sets the transparent green value for the frame buffer configuration,
+ ranging from 0 to the maximum frame buffer value for green.
+ This value is ignored if {@link #isBackgroundOpaque()} equals true.<br>
+ It defaults to half of the frambuffer value for green.<br>
+ A value of -1 is interpreted as any value. */
+ public void setTransparentGreenValue(final int transValueGreen) { transparentValueGreen=transValueGreen; }
+
+ /** Sets the transparent blue value for the frame buffer configuration,
+ ranging from 0 to the maximum frame buffer value for blue.
+ This value is ignored if {@link #isBackgroundOpaque()} equals true.<br>
+ It defaults to half of the frambuffer value for blue.<br>
+ A value of -1 is interpreted as any value. */
+ public void setTransparentBlueValue(final int transValueBlue) { transparentValueBlue=transValueBlue; }
+
+ /** Sets the transparent alpha value for the frame buffer configuration,
+ ranging from 0 to the maximum frame buffer value for alpha.
+ This value is ignored if {@link #isBackgroundOpaque()} equals true.<br>
+ It defaults to half of the frambuffer value for alpha.<br>
+ A value of -1 is interpreted as any value. */
+ public void setTransparentAlphaValue(final int transValueAlpha) { transparentValueAlpha=transValueAlpha; }
+
+ @Override
+ public StringBuilder toString(final StringBuilder sink) {
+ return toString(sink, true);
+ }
+
+ /** Returns a textual representation of this Capabilities
+ object. */
+ @Override
+ public String toString() {
+ final StringBuilder msg = new StringBuilder();
+ msg.append("Caps[");
+ toString(msg);
+ msg.append("]");
+ return msg.toString();
+ }
+
+ /** Return a textual representation of this object's on/off screen state. Use the given StringBuilder [optional]. */
+ protected StringBuilder onoffScreenToString(StringBuilder sink) {
+ if(null == sink) {
+ sink = new StringBuilder();
+ }
+ if(onscreen) {
+ sink.append("on-scr");
+ } else {
+ sink.append("offscr[");
+ }
+ if(isBitmap) {
+ sink.append("bitmap");
+ } else if(onscreen) {
+ sink.append("."); // no additional off-screen modes besides on-screen
+ } else {
+ sink.append("auto-cfg"); // auto-config off-screen mode
+ }
+ sink.append("]");
+
+ return sink;
+ }
+
+ /** Element separator */
+ protected static final String ESEP = "/";
+ /** Component separator */
+ protected static final String CSEP = ", ";
+
+ protected StringBuilder toString(StringBuilder sink, final boolean withOnOffScreen) {
+ if(null == sink) {
+ sink = new StringBuilder();
+ }
+ sink.append("rgba ").append(redBits).append(ESEP).append(greenBits).append(ESEP).append(blueBits).append(ESEP).append(alphaBits);
+ if(backgroundOpaque) {
+ sink.append(", opaque");
+ } else {
+ sink.append(", trans-rgba 0x").append(toHexString(transparentValueRed)).append(ESEP).append(toHexString(transparentValueGreen)).append(ESEP).append(toHexString(transparentValueBlue)).append(ESEP).append(toHexString(transparentValueAlpha));
+ }
+ if(withOnOffScreen) {
+ sink.append(CSEP);
+ onoffScreenToString(sink);
+ }
+ return sink;
+ }
+
+ protected final String toHexString(final int val) { return Integer.toHexString(val); }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesChooser.java b/src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesChooser.java
new file mode 100644
index 000000000..c33ff5a3f
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesChooser.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.nativewindow;
+
+import java.util.List;
+
+/** Provides a mechanism by which applications can customize the
+ window type selection for a given {@link Capabilities}.
+ Developers can implement this interface and pass an instance into
+ the method {@link GraphicsConfigurationFactory#chooseGraphicsConfiguration}; the chooser
+ will be called at window creation time. */
+
+public interface CapabilitiesChooser {
+ /** Chooses the index (0..available.length - 1) of the {@link
+ Capabilities} most closely matching the desired one from the
+ list of all supported. Some of the entries in the
+ <code>available</code> array may be null; the chooser must
+ ignore these. The <em>windowSystemRecommendedChoice</em>
+ parameter may be provided to the chooser by the underlying
+ window system; if this index is valid, it is recommended, but
+ not necessarily required, that the chooser select that entry.
+
+ <P> <em>Note:</em> this method is called automatically by the
+ {@link GraphicsConfigurationFactory#chooseGraphicsConfiguration} method
+ when an instance of this class is passed in to it.
+ It should generally not be
+ invoked by users directly, unless it is desired to delegate the
+ choice to some other CapabilitiesChooser object.
+ */
+ public int chooseCapabilities(CapabilitiesImmutable desired,
+ List<? extends CapabilitiesImmutable> available,
+ int windowSystemRecommendedChoice);
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesImmutable.java b/src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesImmutable.java
new file mode 100644
index 000000000..780d537b8
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/CapabilitiesImmutable.java
@@ -0,0 +1,139 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow;
+
+import com.jogamp.common.type.WriteCloneable;
+
+/**
+ * Specifies an immutable set of capabilities that a window's rendering context
+ * must support, such as color depth per channel.
+ *
+ * @see com.jogamp.nativewindow.Capabilities
+ */
+public interface CapabilitiesImmutable extends VisualIDHolder, WriteCloneable, Comparable<CapabilitiesImmutable> {
+
+ /**
+ * Returns the number of bits for the color buffer's red
+ * component. On some systems only the color depth, which is the sum of the
+ * red, green, and blue bits, is considered.
+ */
+ int getRedBits();
+
+ /**
+ * Returns the number of bits for the color buffer's green
+ * component. On some systems only the color depth, which is the sum of the
+ * red, green, and blue bits, is considered.
+ */
+ int getGreenBits();
+
+ /**
+ * Returns the number of bits for the color buffer's blue
+ * component. On some systems only the color depth, which is the sum of the
+ * red, green, and blue bits, is considered.
+ */
+ int getBlueBits();
+
+ /**
+ * Returns the number of bits for the color buffer's alpha
+ * component. On some systems only the color depth, which is the sum of the
+ * red, green, and blue bits, is considered.
+ */
+ int getAlphaBits();
+
+ /**
+ * Returns whether an opaque or translucent surface is requested, supported or chosen.
+ * <p>
+ * Default is true, i.e. opaque.
+ * </p>
+ */
+ boolean isBackgroundOpaque();
+
+ /**
+ * Returns whether an on- or offscreen surface is requested, available or chosen.
+ * <p>
+ * Default is true, i.e. onscreen.
+ * </p>
+ * <p>
+ * Mind that an capabilities intance w/ <i>available</i> semantics
+ * may show onscreen, but also the offscreen modes FBO, Pbuffer or {@link #setBitmap(boolean) bitmap}.
+ * This is valid, since one native configuration maybe used for either functionality.
+ * </p>
+ */
+ boolean isOnscreen();
+
+ /**
+ * Returns whether bitmap offscreen mode is requested, available or chosen.
+ * <p>
+ * Default is false.
+ * </p>
+ * <p>
+ * For chosen capabilities, only the selected offscreen surface is set to <code>true</code>.
+ * </p>
+ */
+ boolean isBitmap();
+
+ /**
+ * Gets the transparent red value for the frame buffer configuration. This
+ * value is undefined if; equals true.
+ */
+ int getTransparentRedValue();
+
+ /**
+ * Gets the transparent green value for the frame buffer configuration. This
+ * value is undefined if; equals true.
+ */
+ int getTransparentGreenValue();
+
+ /**
+ * Gets the transparent blue value for the frame buffer configuration. This
+ * value is undefined if; equals true.
+ */
+ int getTransparentBlueValue();
+
+ /**
+ * Gets the transparent alpha value for the frame buffer configuration. This
+ * value is undefined if; equals true.
+ */
+ int getTransparentAlphaValue();
+
+ /** Equality over the immutable attributes of both objects */
+ @Override
+ boolean equals(Object obj);
+
+ /** hash code over the immutable attributes of both objects */
+ @Override
+ int hashCode();
+
+ /** Return a textual representation of this object. Use the given StringBuilder [optional]. */
+ StringBuilder toString(StringBuilder sink);
+
+ /** Returns a textual representation of this object. */
+ @Override
+ String toString();
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DefaultCapabilitiesChooser.java b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultCapabilitiesChooser.java
new file mode 100644
index 000000000..33c3f8458
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultCapabilitiesChooser.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.nativewindow;
+
+import java.util.List;
+
+import com.jogamp.common.util.PropertyAccess;
+
+import jogamp.nativewindow.Debug;
+
+/** <P> The default implementation of the {@link
+ CapabilitiesChooser} interface, which provides consistent visual
+ selection behavior across platforms. The precise algorithm is
+ deliberately left loosely specified. Some properties are: </P>
+
+ <LI> Attempts to match as closely as possible the given
+ Capabilities, but will select one with fewer capabilities (i.e.,
+ lower color depth) if necessary.
+
+ <LI> If there is no exact match, prefers a more-capable visual to
+ a less-capable one.
+
+ <LI> If there is more than one exact match, chooses an arbitrary
+ one.
+
+ <LI> If a valid windowSystemRecommendedChoice parameter is
+ supplied, chooses that instead of using the cross-platform code.
+
+ </UL>
+*/
+
+public class DefaultCapabilitiesChooser implements CapabilitiesChooser {
+ private static final boolean DEBUG;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = PropertyAccess.isPropertyDefined("nativewindow.debug.CapabilitiesChooser", true);
+ }
+
+ private final static int NO_SCORE = -9999999;
+ private final static int COLOR_MISMATCH_PENALTY_SCALE = 36;
+
+ @Override
+ public int chooseCapabilities(final CapabilitiesImmutable desired,
+ final List<? extends CapabilitiesImmutable> available,
+ final int windowSystemRecommendedChoice) {
+ if (DEBUG) {
+ System.err.println("Desired: " + desired);
+ for (int i = 0; i < available.size(); i++) {
+ System.err.println("Available " + i + ": " + available.get(i));
+ }
+ System.err.println("Window system's recommended choice: " + windowSystemRecommendedChoice);
+ }
+ final int availnum = available.size();
+
+ if (windowSystemRecommendedChoice >= 0 &&
+ windowSystemRecommendedChoice < availnum &&
+ null != available.get(windowSystemRecommendedChoice)) {
+ if (DEBUG) {
+ System.err.println("Choosing window system's recommended choice of " + windowSystemRecommendedChoice);
+ System.err.println(available.get(windowSystemRecommendedChoice));
+ }
+ return windowSystemRecommendedChoice;
+ }
+
+ // Create score array
+ final int[] scores = new int[availnum];
+ for (int i = 0; i < availnum; i++) {
+ scores[i] = NO_SCORE;
+ }
+ // Compute score for each
+ for (int i = 0; i < availnum; i++) {
+ final CapabilitiesImmutable cur = available.get(i);
+ if (cur == null) {
+ continue;
+ }
+ if (desired.isOnscreen() && !cur.isOnscreen()) {
+ continue; // requested onscreen, but n/a
+ }
+
+ int score = 0;
+ // Compute difference in color depth
+ score += (COLOR_MISMATCH_PENALTY_SCALE *
+ ((cur.getRedBits() + cur.getGreenBits() + cur.getBlueBits() + cur.getAlphaBits()) -
+ (desired.getRedBits() + desired.getGreenBits() + desired.getBlueBits() + desired.getAlphaBits())));
+ scores[i] = score;
+ }
+
+ if (DEBUG) {
+ System.err.print("Scores: [");
+ for (int i = 0; i < availnum; i++) {
+ if (i > 0) {
+ System.err.print(",");
+ }
+ System.err.print(" " + scores[i]);
+ }
+ System.err.println(" ]");
+ }
+
+ // Ready to select. Choose score closest to 0.
+ int scoreClosestToZero = NO_SCORE;
+ int chosenIndex = -1;
+ for (int i = 0; i < availnum; i++) {
+ final int score = scores[i];
+ if (score == NO_SCORE) {
+ continue;
+ }
+ // Don't substitute a positive score for a smaller negative score
+ if ((scoreClosestToZero == NO_SCORE) ||
+ (Math.abs(score) < Math.abs(scoreClosestToZero) &&
+ ((sign(scoreClosestToZero) < 0) || (sign(score) > 0)))) {
+ scoreClosestToZero = score;
+ chosenIndex = i;
+ }
+ }
+ if (chosenIndex < 0) {
+ throw new NativeWindowException("Unable to select one of the provided Capabilities");
+ }
+ if (DEBUG) {
+ System.err.println("Chosen index: " + chosenIndex);
+ System.err.println("Chosen capabilities:");
+ System.err.println(available.get(chosenIndex));
+ }
+
+ return chosenIndex;
+ }
+
+ private static int sign(final int score) {
+ if (score < 0) {
+ return -1;
+ }
+ return 1;
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsConfiguration.java
new file mode 100644
index 000000000..d20a6824d
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsConfiguration.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+package com.jogamp.nativewindow;
+
+import jogamp.nativewindow.Debug;
+
+public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphicsConfiguration {
+ protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration");
+
+ private AbstractGraphicsScreen screen;
+ protected CapabilitiesImmutable capabilitiesChosen;
+ protected CapabilitiesImmutable capabilitiesRequested;
+
+ public DefaultGraphicsConfiguration(final AbstractGraphicsScreen screen,
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested) {
+ if(null == screen) {
+ throw new IllegalArgumentException("Null screen");
+ }
+ if(null == capsChosen) {
+ throw new IllegalArgumentException("Null chosen caps");
+ }
+ if(null == capsRequested) {
+ throw new IllegalArgumentException("Null requested caps");
+ }
+ this.screen = screen;
+ this.capabilitiesChosen = capsChosen;
+ this.capabilitiesRequested = capsRequested;
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (final CloneNotSupportedException e) {
+ throw new NativeWindowException(e);
+ }
+ }
+
+ @Override
+ final public AbstractGraphicsScreen getScreen() {
+ return screen;
+ }
+
+ @Override
+ final public CapabilitiesImmutable getChosenCapabilities() {
+ return capabilitiesChosen;
+ }
+
+ @Override
+ final public CapabilitiesImmutable getRequestedCapabilities() {
+ return capabilitiesRequested;
+ }
+
+ @Override
+ public AbstractGraphicsConfiguration getNativeGraphicsConfiguration() {
+ return this;
+ }
+
+ @Override
+ final public int getVisualID(final VIDType type) throws NativeWindowException {
+ return capabilitiesChosen.getVisualID(type);
+ }
+
+ /**
+ * Set the capabilities to a new value.
+ *
+ * <p>
+ * The use case for setting the Capabilities at a later time is
+ * a change or re-validation of capabilities.
+ * </p>
+ * @see com.jogamp.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
+ */
+ protected void setChosenCapabilities(final CapabilitiesImmutable capsChosen) {
+ this.capabilitiesChosen = capsChosen;
+ }
+
+ /**
+ * Set a new screen.
+ *
+ * <p>
+ * the use case for setting a new screen at a later time is
+ * a change of the graphics device in a multi-screen environment.
+ * </p>
+ */
+ protected void setScreen(final AbstractGraphicsScreen screen) {
+ this.screen = screen;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()+"[" + screen +
+ ",\n\tchosen " + capabilitiesChosen+
+ ",\n\trequested " + capabilitiesRequested+
+ "]";
+ }
+
+ public static String toHexString(final int val) {
+ return "0x"+Integer.toHexString(val);
+ }
+
+ public static String toHexString(final long val) {
+ return "0x"+Long.toHexString(val);
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsDevice.java
new file mode 100644
index 000000000..070b6bb28
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsDevice.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+package com.jogamp.nativewindow;
+
+import jogamp.nativewindow.NativeWindowFactoryImpl;
+
+public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice {
+ private static final String separator = "_";
+ private final String type;
+ protected final String connection;
+ protected final int unitID;
+ protected final String uniqueID;
+ protected long handle;
+ protected ToolkitLock toolkitLock;
+
+ /**
+ * Create an instance with the system default {@link ToolkitLock},
+ * gathered via {@link NativeWindowFactory#getDefaultToolkitLock(String)}.
+ * @param type
+ */
+ public DefaultGraphicsDevice(final String type, final String connection, final int unitID) {
+ this(type, connection, unitID, 0, NativeWindowFactory.getDefaultToolkitLock(type));
+ }
+
+ /**
+ * Create an instance with the system default {@link ToolkitLock}.
+ * gathered via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}.
+ * @param type
+ * @param handle
+ */
+ public DefaultGraphicsDevice(final String type, final String connection, final int unitID, final long handle) {
+ this(type, connection, unitID, handle, NativeWindowFactory.getDefaultToolkitLock(type, handle));
+ }
+
+ /**
+ * Create an instance with the given {@link ToolkitLock} instance, or <i>null</i> {@link ToolkitLock} if null.
+ * @param type
+ * @param handle
+ * @param locker if null, a non blocking <i>null</i> lock is used.
+ */
+ public DefaultGraphicsDevice(final String type, final String connection, final int unitID, final long handle, final ToolkitLock locker) {
+ this.type = type;
+ this.connection = connection;
+ this.unitID = unitID;
+ this.uniqueID = getUniqueID(type, connection, unitID);
+ this.handle = handle;
+ this.toolkitLock = null != locker ? locker : NativeWindowFactoryImpl.getNullToolkitLock();
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (final CloneNotSupportedException e) {
+ throw new NativeWindowException(e);
+ }
+ }
+
+ @Override
+ public final String getType() {
+ return type;
+ }
+
+ @Override
+ public final String getConnection() {
+ return connection;
+ }
+
+ @Override
+ public final int getUnitID() {
+ return unitID;
+ }
+
+ @Override
+ public final String getUniqueID() {
+ return uniqueID;
+ }
+
+ @Override
+ public final long getHandle() {
+ return handle;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Locking is perfomed via delegation to {@link ToolkitLock#lock()}, {@link ToolkitLock#unlock()}.
+ * </p>
+ *
+ * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
+ * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, com.jogamp.nativewindow.ToolkitLock)
+ */
+ @Override
+ public final void lock() {
+ toolkitLock.lock();
+ }
+
+ @Override
+ public final void validateLocked() throws RuntimeException {
+ toolkitLock.validateLocked();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Locking is perfomed via delegation to {@link ToolkitLock#lock()}, {@link ToolkitLock#unlock()}.
+ * </p>
+ *
+ * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
+ * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, com.jogamp.nativewindow.ToolkitLock)
+ */
+ @Override
+ public final void unlock() {
+ toolkitLock.unlock();
+ }
+
+ @Override
+ public boolean open() {
+ return false;
+ }
+
+ @Override
+ public boolean close() {
+ toolkitLock.dispose();
+ if(0 != handle) {
+ handle = 0;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isHandleOwner() {
+ return false;
+ }
+
+ @Override
+ public void clearHandleOwner() {
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", owner "+isHandleOwner()+", "+toolkitLock+"]";
+ }
+
+ /**
+ * Set the native handle of the underlying native device
+ * and return the previous one.
+ */
+ protected final long setHandle(final long newHandle) {
+ final long oldHandle = handle;
+ handle = newHandle;
+ return oldHandle;
+ }
+
+ protected Object getHandleOwnership() {
+ return null;
+ }
+ protected Object setHandleOwnership(final Object newOwnership) {
+ return null;
+ }
+
+ public static final void swapDeviceHandleAndOwnership(final DefaultGraphicsDevice aDevice1, final DefaultGraphicsDevice aDevice2) {
+ aDevice1.lock();
+ try {
+ aDevice2.lock();
+ try {
+ final long aDevice1Handle = aDevice1.getHandle();
+ final long aDevice2Handle = aDevice2.setHandle(aDevice1Handle);
+ aDevice1.setHandle(aDevice2Handle);
+ final Object aOwnership1 = aDevice1.getHandleOwnership();
+ final Object aOwnership2 = aDevice2.setHandleOwnership(aOwnership1);
+ aDevice1.setHandleOwnership(aOwnership2);
+ } finally {
+ aDevice2.unlock();
+ }
+ } finally {
+ aDevice1.unlock();
+ }
+ }
+
+ /**
+ * Set the internal ToolkitLock, which is used within the
+ * {@link #lock()} and {@link #unlock()} implementation.
+ *
+ * <p>
+ * The current ToolkitLock is being locked/unlocked while swapping the reference,
+ * ensuring no concurrent access can occur during the swap.
+ * </p>
+ *
+ * @param locker the ToolkitLock, if null, {@link jogamp.nativewindow.NullToolkitLock} is being used
+ * @return the previous ToolkitLock instance
+ */
+ protected ToolkitLock setToolkitLock(final ToolkitLock locker) {
+ final ToolkitLock _toolkitLock = toolkitLock;
+ _toolkitLock.lock();
+ try {
+ toolkitLock = ( null == locker ) ? NativeWindowFactoryImpl.getNullToolkitLock() : locker ;
+ } finally {
+ _toolkitLock.unlock();
+ }
+ return _toolkitLock;
+ }
+
+ /**
+ * @return the used ToolkitLock
+ *
+ * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
+ * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, com.jogamp.nativewindow.ToolkitLock)
+ */
+ public final ToolkitLock getToolkitLock() {
+ return toolkitLock;
+ }
+
+ /**
+ * Returns a unique String object using {@link String#intern()} for the given arguments,
+ * which object reference itself can be used as a key.
+ */
+ private static String getUniqueID(final String type, final String connection, final int unitID) {
+ return (type + separator + connection + separator + unitID).intern();
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsScreen.java b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsScreen.java
new file mode 100644
index 000000000..63c79af55
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/DefaultGraphicsScreen.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+package com.jogamp.nativewindow;
+
+public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen {
+ private final AbstractGraphicsDevice device;
+ private final int idx;
+
+ public DefaultGraphicsScreen(final AbstractGraphicsDevice device, final int idx) {
+ this.device = device;
+ this.idx = idx;
+ }
+
+ public static AbstractGraphicsScreen createDefault(final String type) {
+ return new DefaultGraphicsScreen(new DefaultGraphicsDevice(type, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT), 0);
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (final CloneNotSupportedException e) {
+ throw new NativeWindowException(e);
+ }
+ }
+
+ @Override
+ public AbstractGraphicsDevice getDevice() {
+ return device;
+ }
+
+ @Override
+ public int getIndex() {
+ return idx;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()+"["+device+", idx "+idx+"]";
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/GraphicsConfigurationFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/GraphicsConfigurationFactory.java
new file mode 100644
index 000000000..929af054e
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/GraphicsConfigurationFactory.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+package com.jogamp.nativewindow;
+
+import com.jogamp.common.ExceptionUtils;
+import com.jogamp.common.util.ReflectionUtil;
+
+import jogamp.nativewindow.Debug;
+import jogamp.nativewindow.DefaultGraphicsConfigurationFactoryImpl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Provides the mechanism by which the graphics configuration for a
+ * window can be chosen before the window is created. The graphics
+ * configuration decides parameters related to hardware accelerated rendering such
+ * as the OpenGL pixel format. <br>
+ * On some window systems (EGL/OpenKODE and X11 in particular) it is necessary to
+ * choose the graphics configuration early at window creation time. <br>
+ * Note that the selection of the graphics configuration is an algorithm which does not have
+ * strong dependencies on the particular Java window toolkit in use
+ * (e.g., AWT) and therefore it is strongly desirable to factor this
+ * functionality out of the core {@link NativeWindowFactory} so that
+ * new window toolkits can replace just the {@link
+ * NativeWindowFactory} and reuse the graphics configuration selection
+ * algorithm provided by, for example, an OpenGL binding.
+ */
+
+public abstract class GraphicsConfigurationFactory {
+ protected static final boolean DEBUG;
+
+ private static class DeviceCapsType {
+ public final Class<?> deviceType;
+ public final Class<?> capsType;
+ private final int hash32;
+
+ public DeviceCapsType(final Class<?> deviceType, final Class<?> capsType) {
+ this.deviceType = deviceType;
+ this.capsType = capsType;
+
+ // 31 * x == (x << 5) - x
+ int hash32 = 31 + deviceType.hashCode();
+ hash32 = ((hash32 << 5) - hash32) + capsType.hashCode();
+ this.hash32 = hash32;
+ }
+
+ @Override
+ public final int hashCode() {
+ return hash32;
+ }
+
+ @Override
+ public final boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if (obj instanceof DeviceCapsType) {
+ final DeviceCapsType dct = (DeviceCapsType)obj;
+ return deviceType == dct.deviceType && capsType == dct.capsType;
+ }
+ return false;
+ }
+
+ @Override
+ public final String toString() {
+ return "DeviceCapsType["+deviceType.getName()+", "+capsType.getName()+"]";
+ }
+
+ }
+
+ private static final Map<DeviceCapsType, GraphicsConfigurationFactory> registeredFactories;
+ private static final DeviceCapsType defaultDeviceCapsType;
+ static boolean initialized = false;
+
+ static {
+ DEBUG = Debug.debug("GraphicsConfiguration");
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - Info: GraphicsConfigurationFactory.<init>");
+ // Thread.dumpStack();
+ }
+ registeredFactories = Collections.synchronizedMap(new HashMap<DeviceCapsType, GraphicsConfigurationFactory>());
+ defaultDeviceCapsType = new DeviceCapsType(AbstractGraphicsDevice.class, CapabilitiesImmutable.class);
+ }
+
+ public static synchronized void initSingleton() {
+ if(!initialized) {
+ initialized = true;
+
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.initSingleton()");
+ }
+
+ // Register the default no-op factory for arbitrary
+ // AbstractGraphicsDevice implementations, including
+ // AWTGraphicsDevice instances -- the OpenGL binding will take
+ // care of handling AWTGraphicsDevices on X11 platforms (as
+ // well as X11GraphicsDevices in non-AWT situations)
+ registerFactory(defaultDeviceCapsType.deviceType, defaultDeviceCapsType.capsType, new DefaultGraphicsConfigurationFactoryImpl());
+
+ if (NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true)) {
+ try {
+ ReflectionUtil.callStaticMethod("jogamp.nativewindow.x11.X11GraphicsConfigurationFactory",
+ "registerFactory", null, null, GraphicsConfigurationFactory.class.getClassLoader());
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+ if(NativeWindowFactory.isAWTAvailable()) {
+ try {
+ ReflectionUtil.callStaticMethod("jogamp.nativewindow.x11.awt.X11AWTGraphicsConfigurationFactory",
+ "registerFactory", null, null, GraphicsConfigurationFactory.class.getClassLoader());
+ } catch (final Exception e) { /* n/a */ }
+ }
+ }
+ }
+ }
+
+ public static synchronized void shutdown() {
+ if(initialized) {
+ initialized = false;
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.shutdown()");
+ }
+ registeredFactories.clear();
+ }
+ }
+
+ protected static String getThreadName() {
+ return Thread.currentThread().getName();
+ }
+
+ protected static String toHexString(final int val) {
+ return "0x" + Integer.toHexString(val);
+ }
+
+ protected static String toHexString(final long val) {
+ return "0x" + Long.toHexString(val);
+ }
+
+ /** Creates a new NativeWindowFactory instance. End users do not
+ need to call this method. */
+ protected GraphicsConfigurationFactory() {
+ }
+
+ /**
+ * Returns the graphics configuration factory for use with the
+ * given device and capability.
+ *
+ * @see #getFactory(Class, Class)
+ */
+ public static GraphicsConfigurationFactory getFactory(final AbstractGraphicsDevice device, final CapabilitiesImmutable caps) {
+ if (device == null) {
+ throw new IllegalArgumentException("null device");
+ }
+ if (caps == null) {
+ throw new IllegalArgumentException("null caps");
+ }
+ return getFactory(device.getClass(), caps.getClass());
+ }
+
+ /**
+ * Returns the graphics configuration factory for use with the
+ * given device and capability class.
+ * <p>
+ * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only.
+ * </p>
+ *
+ * <p>
+ * Pseudo code for finding a suitable factory is:
+ * <pre>
+ For-All devT := getTopDownDeviceTypes(deviceType)
+ For-All capsT := getTopDownCapabilitiesTypes(capabilitiesType)
+ f = factory.get(devT, capsT);
+ if(f) { return f; }
+ end
+ end
+ * </pre>
+ * </p>
+ *
+ * @param deviceType the minimum capabilities class type accepted, must implement or extend {@link AbstractGraphicsDevice}
+ * @param capabilitiesType the minimum capabilities class type accepted, must implement or extend {@link CapabilitiesImmutable}
+ *
+ * @throws IllegalArgumentException if the deviceType does not implement {@link AbstractGraphicsDevice} or
+ * capabilitiesType does not implement {@link CapabilitiesImmutable}
+ */
+ public static GraphicsConfigurationFactory getFactory(final Class<?> deviceType, final Class<?> capabilitiesType)
+ throws IllegalArgumentException, NativeWindowException
+ {
+ if (!(defaultDeviceCapsType.deviceType.isAssignableFrom(deviceType))) {
+ throw new IllegalArgumentException("Given class must implement AbstractGraphicsDevice");
+ }
+ if (!(defaultDeviceCapsType.capsType.isAssignableFrom(capabilitiesType))) {
+ throw new IllegalArgumentException("Given capabilities class must implement CapabilitiesImmutable");
+ }
+ if(DEBUG) {
+ ExceptionUtils.dumpStack(System.err);
+ System.err.println("GraphicsConfigurationFactory.getFactory: "+deviceType.getName()+", "+capabilitiesType.getName());
+ dumpFactories();
+ }
+
+ final List<Class<?>> deviceTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.deviceType, deviceType, false);
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.getFactory() deviceTypes: " + deviceTypes);
+ }
+ final List<Class<?>> capabilitiesTypes = getAllAssignableClassesFrom(defaultDeviceCapsType.capsType, capabilitiesType, true);
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.getFactory() capabilitiesTypes: " + capabilitiesTypes);
+ }
+ for(int j=0; j<deviceTypes.size(); j++) {
+ final Class<?> interfaceDevice = deviceTypes.get(j);
+ for(int i=0; i<capabilitiesTypes.size(); i++) {
+ final Class<?> interfaceCaps = capabilitiesTypes.get(i);
+ final DeviceCapsType dct = new DeviceCapsType(interfaceDevice, interfaceCaps);
+ final GraphicsConfigurationFactory factory = registeredFactories.get(dct);
+ if (factory != null) {
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.getFactory() found "+dct+" -> "+factory);
+ }
+ return factory;
+ }
+ }
+ }
+ // Return the default
+ final GraphicsConfigurationFactory factory = registeredFactories.get(defaultDeviceCapsType);
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.getFactory() DEFAULT "+defaultDeviceCapsType+" -> "+factory);
+ }
+ return factory;
+ }
+ private static ArrayList<Class<?>> getAllAssignableClassesFrom(final Class<?> superClassOrInterface, final Class<?> fromClass, final boolean interfacesOnly) {
+ // Using a todo list avoiding a recursive loop!
+ final ArrayList<Class<?>> inspectClasses = new ArrayList<Class<?>>();
+ final ArrayList<Class<?>> resolvedInterfaces = new ArrayList<Class<?>>();
+ inspectClasses.add(fromClass);
+ for(int j=0; j<inspectClasses.size(); j++) {
+ final Class<?> clazz = inspectClasses.get(j);
+ getAllAssignableClassesFrom(superClassOrInterface, clazz, interfacesOnly, resolvedInterfaces, inspectClasses);
+ }
+ return resolvedInterfaces;
+ }
+ private static void getAllAssignableClassesFrom(final Class<?> superClassOrInterface, final Class<?> fromClass, final boolean interfacesOnly, final List<Class<?>> resolvedInterfaces, final List<Class<?>> inspectClasses) {
+ final ArrayList<Class<?>> types = new ArrayList<Class<?>>();
+ if( superClassOrInterface.isAssignableFrom(fromClass) && !resolvedInterfaces.contains(fromClass)) {
+ if( !interfacesOnly || fromClass.isInterface() ) {
+ types.add(fromClass);
+ }
+ }
+ types.addAll(Arrays.asList(fromClass.getInterfaces()));
+
+ for(int i=0; i<types.size(); i++) {
+ final Class<?> iface = types.get(i);
+ if( superClassOrInterface.isAssignableFrom(iface) && !resolvedInterfaces.contains(iface) ) {
+ resolvedInterfaces.add(iface);
+ if( !superClassOrInterface.equals(iface) && !inspectClasses.contains(iface) ) {
+ inspectClasses.add(iface); // safe add to todo list, avoiding a recursive nature
+ }
+ }
+ }
+ final Class<?> parentClass = fromClass.getSuperclass();
+ if( null != parentClass && superClassOrInterface.isAssignableFrom(parentClass) && !inspectClasses.contains(parentClass) ) {
+ inspectClasses.add(parentClass); // safe add to todo list, avoiding a recursive nature
+ }
+ }
+ private static void dumpFactories() {
+ final Set<DeviceCapsType> dcts = registeredFactories.keySet();
+ int i=0;
+ for(final Iterator<DeviceCapsType> iter = dcts.iterator(); iter.hasNext(); ) {
+ final DeviceCapsType dct = iter.next();
+ System.err.println("Factory #"+i+": "+dct+" -> "+registeredFactories.get(dct));
+ i++;
+ }
+ }
+
+ /**
+ * Registers a GraphicsConfigurationFactory handling
+ * the given graphics device and capability class.
+ * <p>
+ * This does not need to be called by end users, only implementors of new
+ * GraphicsConfigurationFactory subclasses.
+ * </p>
+ *
+ * <p>
+ * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only.
+ * </p>
+ *
+ * <p>See {@link #getFactory(Class, Class)} for a description of the find algorithm.</p>
+ *
+ * @param deviceType the minimum capabilities class type accepted, must implement or extend interface {@link AbstractGraphicsDevice}
+ * @param capabilitiesType the minimum capabilities class type accepted, must extend interface {@link CapabilitiesImmutable}
+ * @return the previous registered factory, or null if none
+ * @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice
+ */
+ protected static GraphicsConfigurationFactory registerFactory(final Class<?> abstractGraphicsDeviceImplementor, final Class<?> capabilitiesType, final GraphicsConfigurationFactory factory)
+ throws IllegalArgumentException
+ {
+ if (!(defaultDeviceCapsType.deviceType.isAssignableFrom(abstractGraphicsDeviceImplementor))) {
+ throw new IllegalArgumentException("Given device class must implement AbstractGraphicsDevice");
+ }
+ if (!(defaultDeviceCapsType.capsType.isAssignableFrom(capabilitiesType))) {
+ throw new IllegalArgumentException("Given capabilities class must implement CapabilitiesImmutable");
+ }
+ final DeviceCapsType dct = new DeviceCapsType(abstractGraphicsDeviceImplementor, capabilitiesType);
+ final GraphicsConfigurationFactory prevFactory;
+ if(null == factory) {
+ prevFactory = registeredFactories.remove(dct);
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.registerFactory() remove "+dct+
+ ", deleting: "+prevFactory);
+ }
+ } else {
+ prevFactory = registeredFactories.put(dct, factory);
+ if(DEBUG) {
+ System.err.println("GraphicsConfigurationFactory.registerFactory() put "+dct+" -> "+factory+
+ ", overridding: "+prevFactory);
+ }
+ }
+ return prevFactory;
+ }
+
+ /**
+ * <P> Selects a graphics configuration on the specified graphics
+ * device compatible with the supplied {@link Capabilities}. Some
+ * platforms (e.g.: X11, EGL, KD) require the graphics configuration
+ * to be specified when the native window is created.
+ * These architectures have seperated their device, screen, window and drawable
+ * context and hence are capable of quering the capabilities for each screen.
+ * A fully established window is not required.</P>
+ *
+ * <P>Other platforms (e.g. Windows, MacOSX) don't offer the mentioned seperation
+ * and hence need a fully established window and it's drawable.
+ * Here the validation of the capabilities is performed later.
+ * In this case, the AbstractGraphicsConfiguration implementation
+ * must allow an overwrite of the Capabilites, for example
+ * {@link DefaultGraphicsConfiguration#setChosenCapabilities DefaultGraphicsConfiguration.setChosenCapabilities(..)}.
+ * </P>
+ *
+ * <P>
+ * This method is mainly intended to be both used and implemented by the
+ * OpenGL binding.</P>
+ *
+ * <P> The concrete data type of the passed graphics device and
+ * returned graphics configuration must be specified in the
+ * documentation binding this particular API to the underlying
+ * window toolkit. The Reference Implementation accepts {@link
+ * com.jogamp.nativewindow.awt.AWTGraphicsDevice AWTGraphicsDevice} objects and returns {@link
+ * com.jogamp.nativewindow.awt.AWTGraphicsConfiguration AWTGraphicsConfiguration} objects. On
+ * X11 platforms where the AWT is not in use, it also accepts
+ * {@link com.jogamp.nativewindow.x11.X11GraphicsDevice
+ * X11GraphicsDevice} objects and returns {@link
+ * com.jogamp.nativewindow.x11.X11GraphicsConfiguration
+ * X11GraphicsConfiguration} objects.</P>
+ *
+ * @param capsChosen the intermediate chosen capabilities to be refined by this implementation, may be equal to capsRequested
+ * @param capsRequested the original requested capabilities
+ * @param chooser the choosing implementation
+ * @param screen the referring Screen
+ * @param nativeVisualID if not {@link VisualIDHolder#VID_UNDEFINED} it reflects a pre-chosen visualID of the native platform's windowing system.
+ * @return the complete GraphicsConfiguration
+ *
+ * @throws IllegalArgumentException if the data type of the passed
+ * AbstractGraphicsDevice is not supported by this
+ * NativeWindowFactory.
+ * @throws NativeWindowException if any window system-specific errors caused
+ * the selection of the graphics configuration to fail.
+ *
+ * @see com.jogamp.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
+ * @see com.jogamp.nativewindow.DefaultGraphicsConfiguration#setChosenCapabilities(Capabilities caps)
+ */
+ public final AbstractGraphicsConfiguration
+ chooseGraphicsConfiguration(final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser,
+ final AbstractGraphicsScreen screen, final int nativeVisualID)
+ throws IllegalArgumentException, NativeWindowException {
+ if(null==capsChosen) {
+ throw new NativeWindowException("Chosen Capabilities are null");
+ }
+ if(null==capsRequested) {
+ throw new NativeWindowException("Requested Capabilities are null");
+ }
+ if(null==screen) {
+ throw new NativeWindowException("Screen is null");
+ }
+ final AbstractGraphicsDevice device = screen.getDevice();
+ if(null==device) {
+ throw new NativeWindowException("Screen's Device is null");
+ }
+ device.lock();
+ try {
+ return chooseGraphicsConfigurationImpl(capsChosen, capsRequested, chooser, screen, nativeVisualID);
+ } finally {
+ device.unlock();
+ }
+ }
+
+ protected abstract AbstractGraphicsConfiguration
+ chooseGraphicsConfigurationImpl(CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested,
+ CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID)
+ throws IllegalArgumentException, NativeWindowException;
+
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/MutableSurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/MutableSurface.java
new file mode 100644
index 000000000..7686f270b
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/MutableSurface.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2012 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;
+
+/**
+ * Provides a {@link NativeSurface} with a mutable <code>surfaceHandle</code>
+ * via {@link #setSurfaceHandle(long)}.
+ *
+ * @see NativeSurface
+ */
+public interface MutableSurface extends NativeSurface {
+
+ /**
+ * Sets the surface handle which is created outside of this implementation.
+ */
+ public void setSurfaceHandle(long surfaceHandle);
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeSurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeSurface.java
new file mode 100644
index 000000000..ce0699c56
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeSurface.java
@@ -0,0 +1,238 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow;
+
+/**
+ * Provides low-level information required for
+ * hardware-accelerated rendering using a surface in a platform-independent manner.
+ * <p>
+ * All values of this interface are represented in pixel units, if not stated otherwise.
+ * See {@link NativeWindow}.
+ * </p>
+ * <p>
+ * A NativeSurface created for a particular on- or offscreen component is
+ * expected to have the same lifetime as that component. As long as
+ * the component is alive and realized/visible, NativeSurface must be able
+ * provide information such as the surface handle while it is locked.
+ * </p>
+ */
+public interface NativeSurface extends SurfaceUpdatedListener {
+ /** Unlocked state, {@value}. */
+ public static final int LOCK_SURFACE_UNLOCKED = 0;
+
+ /** Returned by {@link #lockSurface()} if the surface is not ready to be locked, {@value}. */
+ public static final int LOCK_SURFACE_NOT_READY = 1;
+
+ /** Returned by {@link #lockSurface()} if the surface is locked, but has changed, {@value}. */
+ public static final int LOCK_SURFACE_CHANGED = 2;
+
+ /** Returned by {@link #lockSurface()} if the surface is locked, and is unchanged, {@value}. */
+ public static final int LOCK_SUCCESS = 3;
+
+ /**
+ * Lock the surface of this native window.
+ * <p>
+ * The surface handle shall be valid after a successfull call,
+ * ie return a value other than {@link #LOCK_SURFACE_UNLOCKED} and {@link #LOCK_SURFACE_NOT_READY},
+ * which is
+ * <pre>
+ * boolean ok = LOCK_SURFACE_NOT_READY < lockSurface();
+ * </pre>
+ * </p>
+ * <p>
+ * The caller may need to take care of the result {@link #LOCK_SURFACE_CHANGED},
+ * where the surface handle is valid but has changed.
+ * </p>
+ * <p>
+ * This call is blocking until the surface has been locked
+ * or a timeout is reached. The latter will throw a runtime exception.
+ * </p>
+ * <p>
+ * This call allows recursion from the same thread.
+ * </p>
+ * <p>
+ * The implementation may want to aquire the
+ * application level {@link com.jogamp.common.util.locks.RecursiveLock}
+ * first before proceeding with a native surface lock.
+ * </p>
+ * <p>
+ * The implementation shall also invoke {@link AbstractGraphicsDevice#lock()}
+ * for the initial lock (recursive count zero).
+ * </p>
+ *
+ * @return {@link #LOCK_SUCCESS}, {@link #LOCK_SURFACE_CHANGED} or {@link #LOCK_SURFACE_NOT_READY}.
+ *
+ * @throws RuntimeException after timeout when waiting for the surface lock
+ * @throws NativeWindowException if native locking failed, maybe platform related
+ *
+ * @see com.jogamp.common.util.locks.RecursiveLock
+ */
+ public int lockSurface() throws NativeWindowException, RuntimeException;
+
+ /**
+ * Unlock the surface of this native window
+ *
+ * Shall not modify the surface handle, see {@link #lockSurface()} <P>
+ *
+ * The implementation shall also invoke {@link AbstractGraphicsDevice#unlock()}
+ * for the final unlock (recursive count zero).<P>
+ *
+ * The implementation shall be fail safe, i.e. tolerant in case the native resources
+ * are already released / unlocked. In this case the implementation shall simply ignore the call.
+ *
+ * @see #lockSurface
+ * @see com.jogamp.common.util.locks.RecursiveLock
+ */
+ public void unlockSurface();
+
+ /**
+ * Query if surface is locked by another thread, i.e. not the current one.
+ * <br>
+ * Convenient shortcut for:
+ * <pre>
+ * final Thread o = getSurfaceLockOwner();
+ * if( null != o && Thread.currentThread() != o ) { .. }
+ * </pre>
+ */
+ public boolean isSurfaceLockedByOtherThread();
+
+ /**
+ * Return the locking owner's Thread, or null if not locked.
+ */
+ public Thread getSurfaceLockOwner();
+
+ /**
+ * Provide a mechanism to utilize custom (pre-) swap surface
+ * code. This method is called before the render toolkit (e.g. JOGL)
+ * swaps the buffer/surface if double buffering is enabled.
+ * <p>
+ * The implementation may itself apply the swapping,
+ * in which case true shall be returned.
+ * </p>
+ *
+ * @return true if this method completed swapping the surface,
+ * otherwise false, in which case eg the GLDrawable
+ * implementation has to swap the code.
+ */
+ public boolean surfaceSwap();
+
+ /** Appends the given {@link SurfaceUpdatedListener} to the end of the list. */
+ public void addSurfaceUpdatedListener(SurfaceUpdatedListener l);
+
+ /**
+ * Inserts the given {@link SurfaceUpdatedListener} at the
+ * specified position in the list.<br>
+ *
+ * @param index Position where the listener will be inserted.
+ * Should be within (0 <= index && index <= size()).
+ * An index value of -1 is interpreted as the end of the list, size().
+ * @param l The listener object to be inserted
+ * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1
+ */
+ public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException;
+
+ /** Remove the specified {@link SurfaceUpdatedListener} from the list. */
+ public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l);
+
+ /**
+ * Returns the handle to the surface for this NativeSurface. <P>
+ *
+ * The surface handle should be set/update by {@link #lockSurface()},
+ * where {@link #unlockSurface()} is not allowed to modify it.
+ * After {@link #unlockSurface()} it is no more guaranteed
+ * that the surface handle is still valid.
+ *
+ * The surface handle shall reflect the platform one
+ * for all drawable surface operations, e.g. opengl, swap-buffer. <P>
+ *
+ * On X11 this returns an entity of type Window,
+ * since there is no differentiation of surface and window there. <BR>
+ * On Microsoft Windows this returns an entity of type HDC.
+ */
+ public long getSurfaceHandle();
+
+ /**
+ * Returns the width of the client area excluding insets (window decorations) in pixel units.
+ * @return width of the client area in pixel units
+ * @see NativeWindow#getWidth()
+ * @see #convertToWindowUnits(int[])
+ */
+ public int getSurfaceWidth();
+
+ /**
+ * Returns the height of the client area excluding insets (window decorations) in pixel units.
+ * @return height of the client area in pixel units
+ * @see NativeWindow#getHeight()
+ * @see #convertToWindowUnits(int[])
+ */
+ public int getSurfaceHeight();
+
+ /**
+ * Converts the given pixel units into window units <i>in place</i>.
+ * @param pixelUnitsAndResult int[2] storage holding the pixel units for the x- and y-coord to convert
+ * and the resulting values.
+ * @return result int[2] storage pixelUnitsAndResult for chaining holding the converted values
+ * @see ScalableSurface
+ */
+ public int[] convertToWindowUnits(final int[] pixelUnitsAndResult);
+
+ /**
+ * Converts the given window units into pixel units <i>in place</i>.
+ * @param windowUnitsAndResult int[2] storage holding the window units for the x- and y-coord to convert
+ * and the resulting values.
+ * @return result int[2] storage windowUnitsAndResult for chaining holding the converted values
+ * @see ScalableSurface
+ */
+ public int[] convertToPixelUnits(final int[] windowUnitsAndResult);
+
+ /**
+ * Returns the graphics configuration corresponding to this window.
+ * <p>
+ * In case the implementation utilizes a delegation pattern to wrap abstract toolkits,
+ * this method shall return the native {@link AbstractGraphicsConfiguration} via {@link AbstractGraphicsConfiguration#getNativeGraphicsConfiguration()}.
+ * </p>
+ * @see AbstractGraphicsConfiguration#getNativeGraphicsConfiguration()
+ * @see com.jogamp.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
+ */
+ public AbstractGraphicsConfiguration getGraphicsConfiguration();
+
+ /**
+ * Convenience: Get display handle from
+ * AbstractGraphicsConfiguration . AbstractGraphicsScreen . AbstractGraphicsDevice
+ */
+ public long getDisplayHandle();
+
+ /**
+ * Convenience: Get display handle from
+ * AbstractGraphicsConfiguration . AbstractGraphicsScreen
+ */
+ public int getScreenIndex();
+
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeSurfaceHolder.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeSurfaceHolder.java
new file mode 100644
index 000000000..667f5d8af
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeSurfaceHolder.java
@@ -0,0 +1,41 @@
+/**
+ * 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;
+
+/**
+ * Accessor interface for implementing classes with ownership of a {@link NativeSurface}
+ * via an <i>is-a</i> or <i>has-a</i> relation.
+ */
+public interface NativeSurfaceHolder {
+ /**
+ * Returns the associated {@link NativeSurface} of this {@link NativeSurfaceHolder}.
+ */
+ public NativeSurface getNativeSurface();
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindow.java
new file mode 100644
index 000000000..1a2d212da
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindow.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.nativewindow;
+
+import com.jogamp.nativewindow.util.InsetsImmutable;
+import com.jogamp.nativewindow.util.Point;
+
+/**
+ * Extend the {@link NativeSurface} interface with windowing
+ * information such as {@link #getWindowHandle() window-handle},
+ * {@link #getWidth() window-size} and {@link #getX() window-position}.
+ * <p>
+ * All values of this interface are represented in window units, if not stated otherwise.
+ * See {@link NativeSurface}.
+ * </p>
+ *
+ * <a name="coordinateSystem"><h5>Coordinate System</h5></a>
+ * <p>
+ * <ul>
+ * <li>Abstract screen space has it's origin in the top-left corner, and may not be at 0/0.</li>
+ * <li>Window origin is in it's top-left corner, see {@link #getX()} and {@link #getY()}. </li>
+ * <li>Window client-area excludes {@link #getInsets() insets}, i.e. window decoration.</li>
+ * <li>Window origin is relative to it's parent window if exist, or the screen position (top-level).</li>
+ * </ul>
+ * </p>
+ * <p>
+ * A window toolkit such as the AWT may either implement this interface
+ * directly with one of its components, or provide and register an
+ * implementation of {@link NativeWindowFactory NativeWindowFactory}
+ * which can create NativeWindow objects for its components.
+ * </p>
+ */
+public interface NativeWindow extends NativeSurface, NativeSurfaceHolder {
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns this instance, which <i>is-a</i> {@link NativeSurface}.
+ * </p>
+ */
+ @Override
+ public NativeSurface getNativeSurface();
+
+ /**
+ * Destroys this window incl. releasing all related resources.
+ */
+ public void destroy();
+
+ /**
+ * @return The parent NativeWindow, or null if this NativeWindow is top level.
+ */
+ public NativeWindow getParent();
+
+ /**
+ * Returns the window handle for this NativeWindow. <P>
+ *
+ * The window handle shall reflect the platform one
+ * for all window related operations, e.g. open, close, resize. <P>
+ *
+ * On X11 this returns an entity of type Window. <BR>
+ * On Microsoft Windows this returns an entity of type HWND.
+ */
+ public long getWindowHandle();
+
+ /**
+ * Returns the insets defined as the width and height of the window decoration
+ * on the left, right, top and bottom in window units.
+ * <p>
+ * Insets are zero if the window is undecorated, including child windows.
+ * </p>
+ *
+ * <p>
+ * Insets are available only after the native window has been created,
+ * ie. the native window has been made visible.<br>
+ *
+ * The top-level window area's top-left corner is located at
+ * <pre>
+ * {@link #getX()} - getInsets().{@link InsetsImmutable#getLeftWidth() getLeftWidth()}
+ * {@link #getY()} - getInsets().{@link InsetsImmutable#getTopHeight() getTopHeight()}
+ * </pre>
+ *
+ * The top-level window size is
+ * <pre>
+ * {@link #getWidth()} + getInsets().{@link InsetsImmutable#getTotalWidth() getTotalWidth()}
+ * {@link #getHeight()} + getInsets().{@link InsetsImmutable#getTotalHeight() getTotalHeight()}
+ * </pre>
+ *
+ * @return insets
+ */
+ public InsetsImmutable getInsets();
+
+ /** Returns the current x position of this window, relative to it's parent. */
+
+ /**
+ * Returns the x position of the top-left corner
+ * of the client area relative to it's parent in window units.
+ * <p>
+ * If no parent exist (top-level window), this coordinate equals the screen coordinate.
+ * </p>
+ * <p>
+ * Since the position reflects the client area, it does not include the insets.
+ * </p>
+ * <p>
+ * See <a href="#coordinateSystem"> Coordinate System</a>.
+ * </p>
+ * @see #getInsets()
+ * @see #getLocationOnScreen(Point)
+ */
+ public int getX();
+
+ /**
+ * Returns the current y position of the top-left corner
+ * of the client area relative to it's parent in window units.
+ * <p>
+ * If no parent exist (top-level window), this coordinate equals the screen coordinate.
+ * </p>
+ * <p>
+ * Since the position reflects the client area, it does not include the insets.
+ * </p>
+ * <p>
+ * See <a href="#coordinateSystem"> Coordinate System</a>.
+ * </p>
+ * @see #getInsets()
+ * @see #getLocationOnScreen(Point)
+ */
+ public int getY();
+
+ /**
+ * Returns the width of the client area excluding insets (window decorations) in window units.
+ * @return width of the client area in window units
+ * @see NativeSurface#getSurfaceWidth()
+ */
+ public int getWidth();
+
+ /**
+ * Returns the height of the client area excluding insets (window decorations) in window units.
+ * @return height of the client area in window units
+ * @see NativeSurface#getSurfaceHeight()
+ */
+ public int getHeight();
+
+ /**
+ * Returns the window's top-left client-area position in the screen.
+ * <p>
+ * If {@link Point} is not <code>null</code>, it is translated about the resulting screen position
+ * and returned.
+ * </p>
+ * <p>
+ * See <a href="#coordinateSystem"> Coordinate System</a>.
+ * </p>
+ * <p>
+ * Since the position reflects the client area, it does not include the insets.
+ * </p>
+ * @param point Optional {@link Point} storage.
+ * If not null, <code>null</code>, it is translated about the resulting screen position
+ * and returned.
+ * @see #getX()
+ * @see #getY()
+ * @see #getInsets()
+ */
+ public Point getLocationOnScreen(Point point);
+
+ /** Returns true if this native window owns the focus, otherwise false. */
+ boolean hasFocus();
+
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowException.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowException.java
new file mode 100644
index 000000000..8f841e7ea
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowException.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package com.jogamp.nativewindow;
+
+/** A generic exception for OpenGL errors used throughout the binding
+ as a substitute for {@link RuntimeException}. */
+
+public class NativeWindowException extends RuntimeException {
+ /** Constructs a NativeWindowException object. */
+ public NativeWindowException() {
+ super();
+ }
+
+ /** Constructs a NativeWindowException object with the specified detail
+ message. */
+ public NativeWindowException(final String message) {
+ super(message);
+ }
+
+ /** Constructs a NativeWindowException object with the specified detail
+ message and root cause. */
+ public NativeWindowException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ /** Constructs a NativeWindowException object with the specified root
+ cause. */
+ public NativeWindowException(final Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java
new file mode 100644
index 000000000..cba3a9214
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java
@@ -0,0 +1,716 @@
+/*
+ * Copyright (c) 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+package com.jogamp.nativewindow;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.jogamp.nativewindow.util.PointImmutable;
+
+import jogamp.common.os.PlatformPropsImpl;
+import jogamp.nativewindow.Debug;
+import jogamp.nativewindow.NativeWindowFactoryImpl;
+import jogamp.nativewindow.ToolkitProperties;
+import jogamp.nativewindow.ResourceToolkitLock;
+import jogamp.nativewindow.WrappedWindow;
+import jogamp.nativewindow.macosx.OSXUtil;
+import jogamp.nativewindow.windows.GDIUtil;
+import jogamp.nativewindow.x11.X11Lib;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos;
+import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
+import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
+import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+
+/** Provides a pluggable mechanism for arbitrary window toolkits to
+ adapt their components to the {@link NativeWindow} interface,
+ which provides a platform-independent mechanism of accessing the
+ information required to perform operations like
+ hardware-accelerated rendering using the OpenGL API. */
+
+public abstract class NativeWindowFactory {
+ protected static final boolean DEBUG;
+
+ /** OpenKODE/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}.*/
+ public static final String TYPE_EGL = ".egl".intern();
+
+ /** Microsoft Windows type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
+ public static final String TYPE_WINDOWS = ".windows".intern();
+
+ /** X11 type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
+ public static final String TYPE_X11 = ".x11".intern();
+
+ /** Broadcom VC IV/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
+ public static final String TYPE_BCM_VC_IV = ".bcm.vc.iv".intern();
+
+ /** Android/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}.*/
+ public static final String TYPE_ANDROID = ".android".intern();
+
+ /** Mac OS X type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
+ public static final String TYPE_MACOSX = ".macosx".intern();
+
+ /** Generic AWT type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
+ public static final String TYPE_AWT = ".awt".intern();
+
+ /** Generic DEFAULT type, where platform implementation don't care, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
+ public static final String TYPE_DEFAULT = ".default".intern();
+
+ private static final String nativeWindowingTypePure; // canonical String via String.intern()
+ private static final String nativeWindowingTypeCustom; // canonical String via String.intern()
+
+ private static NativeWindowFactory defaultFactory;
+ private static Map<Class<?>, NativeWindowFactory> registeredFactories;
+
+ private static Class<?> nativeWindowClass;
+ private static boolean isAWTAvailable;
+
+ private static final String JAWTUtilClassName = "jogamp.nativewindow.jawt.JAWTUtil" ;
+ /** {@link jogamp.nativewindow.x11.X11Util} implements {@link ToolkitProperties}. */
+ private static final String X11UtilClassName = "jogamp.nativewindow.x11.X11Util";
+ /** {@link jogamp.nativewindow.macosx.OSXUtil} implements {@link ToolkitProperties}. */
+ private static final String OSXUtilClassName = "jogamp.nativewindow.macosx.OSXUtil";
+ /** {@link jogamp.nativewindow.windows.GDIUtil} implements {@link ToolkitProperties}. */
+ private static final String GDIClassName = "jogamp.nativewindow.windows.GDIUtil";
+
+ private static ToolkitLock jawtUtilJAWTToolkitLock;
+
+ private static boolean requiresToolkitLock;
+ private static boolean desktopHasThreadingIssues;
+
+ // Shutdown hook mechanism for the factory
+ private static volatile boolean isJVMShuttingDown = false;
+ private static final List<Runnable> customShutdownHooks = new ArrayList<Runnable>();
+
+ /** Creates a new NativeWindowFactory instance. End users do not
+ need to call this method. */
+ protected NativeWindowFactory() {
+ }
+
+ private static final boolean guessBroadcomVCIV() {
+ return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ private final File vcliblocation = new File(
+ "/opt/vc/lib/libbcm_host.so");
+ @Override
+ public Boolean run() {
+ if ( vcliblocation.isFile() ) {
+ return Boolean.TRUE;
+ }
+ return Boolean.FALSE;
+ }
+ } ).booleanValue();
+ }
+
+ private static String _getNativeWindowingType() {
+ switch(PlatformPropsImpl.OS_TYPE) {
+ case ANDROID:
+ return TYPE_ANDROID;
+ case MACOS:
+ return TYPE_MACOSX;
+ case WINDOWS:
+ return TYPE_WINDOWS;
+ case OPENKODE:
+ return TYPE_EGL;
+
+ case LINUX:
+ case FREEBSD:
+ case SUNOS:
+ case HPUX:
+ default:
+ if( guessBroadcomVCIV() ) {
+ return TYPE_BCM_VC_IV;
+ }
+ return TYPE_X11;
+ }
+ }
+
+ static {
+ final boolean[] _DEBUG = new boolean[] { false };
+ final String[] _tmp = new String[] { null };
+
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ Platform.initSingleton(); // last resort ..
+ _DEBUG[0] = Debug.debug("NativeWindow");
+ _tmp[0] = PropertyAccess.getProperty("nativewindow.ws.name", true);
+ Runtime.getRuntime().addShutdownHook(
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ NativeWindowFactory.shutdown(true);
+ } }, "NativeWindowFactory_ShutdownHook" ) ) ;
+ return null;
+ } } ) ;
+
+ DEBUG = _DEBUG[0];
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - Info: NativeWindowFactory.<init>");
+ // Thread.dumpStack();
+ }
+
+ // Gather the windowing TK first
+ nativeWindowingTypePure = _getNativeWindowingType();
+ if(null==_tmp[0] || _tmp[0].length()==0) {
+ nativeWindowingTypeCustom = nativeWindowingTypePure;
+ } else {
+ nativeWindowingTypeCustom = _tmp[0].intern(); // canonical representation
+ }
+ }
+
+ private static boolean initialized = false;
+
+ private static void initSingletonNativeImpl(final ClassLoader cl) {
+ final String clazzName;
+ if( TYPE_X11 == nativeWindowingTypePure ) {
+ clazzName = X11UtilClassName;
+ } else if( TYPE_WINDOWS == nativeWindowingTypePure ) {
+ clazzName = GDIClassName;
+ } else if( TYPE_MACOSX == nativeWindowingTypePure ) {
+ clazzName = OSXUtilClassName;
+ } else {
+ clazzName = null;
+ }
+ if( null != clazzName ) {
+ ReflectionUtil.callStaticMethod(clazzName, "initSingleton", null, null, cl );
+
+ final Boolean res1 = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "requiresToolkitLock", null, null, cl);
+ requiresToolkitLock = res1.booleanValue();
+ final Boolean res2 = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "hasThreadingIssues", null, null, cl);
+ desktopHasThreadingIssues = res2.booleanValue();
+ } else {
+ requiresToolkitLock = false;
+ desktopHasThreadingIssues = false;
+ }
+ }
+
+ /** Returns true if the JVM is shutting down, otherwise false. */
+ public static final boolean isJVMShuttingDown() { return isJVMShuttingDown; }
+
+ /**
+ * Add a custom shutdown hook to be performed at JVM shutdown before shutting down NativeWindowFactory instance.
+ *
+ * @param head if true add runnable at the start, otherwise at the end
+ * @param runnable runnable to be added.
+ */
+ public static void addCustomShutdownHook(final boolean head, final Runnable runnable) {
+ synchronized( customShutdownHooks ) {
+ if( !customShutdownHooks.contains( runnable ) ) {
+ if( head ) {
+ customShutdownHooks.add(0, runnable);
+ } else {
+ customShutdownHooks.add( runnable );
+ }
+ }
+ }
+ }
+
+ /**
+ * Cleanup resources at JVM shutdown
+ */
+ public static synchronized void shutdown(final boolean _isJVMShuttingDown) {
+ isJVMShuttingDown = _isJVMShuttingDown;
+ if(DEBUG) {
+ System.err.println("NativeWindowFactory.shutdown() START: JVM Shutdown "+isJVMShuttingDown+", on thread "+Thread.currentThread().getName());
+ }
+ synchronized(customShutdownHooks) {
+ final int cshCount = customShutdownHooks.size();
+ for(int i=0; i < cshCount; i++) {
+ try {
+ if( DEBUG ) {
+ System.err.println("NativeWindowFactory.shutdown - customShutdownHook #"+(i+1)+"/"+cshCount);
+ }
+ customShutdownHooks.get(i).run();
+ } catch(final Throwable t) {
+ System.err.println("NativeWindowFactory.shutdown: Caught "+t.getClass().getName()+" during customShutdownHook #"+(i+1)+"/"+cshCount);
+ if( DEBUG ) {
+ t.printStackTrace();
+ }
+ }
+ }
+ customShutdownHooks.clear();
+ }
+ if(DEBUG) {
+ System.err.println("NativeWindowFactory.shutdown(): Post customShutdownHook");
+ }
+
+ if(initialized) {
+ initialized = false;
+ if(null != registeredFactories) {
+ registeredFactories.clear();
+ registeredFactories = null;
+ }
+ GraphicsConfigurationFactory.shutdown();
+ }
+
+ shutdownNativeImpl(NativeWindowFactory.class.getClassLoader()); // always re-shutdown
+ // SharedResourceToolkitLock.shutdown(DEBUG); // not used yet
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END JVM Shutdown "+isJVMShuttingDown);
+ }
+ }
+
+ private static void shutdownNativeImpl(final ClassLoader cl) {
+ final String clazzName;
+ if( TYPE_X11 == nativeWindowingTypePure ) {
+ clazzName = X11UtilClassName;
+ } else if( TYPE_WINDOWS == nativeWindowingTypePure ) {
+ clazzName = GDIClassName;
+ } else if( TYPE_MACOSX == nativeWindowingTypePure ) {
+ clazzName = OSXUtilClassName;
+ } else {
+ clazzName = null;
+ }
+ if( null != clazzName ) {
+ ReflectionUtil.callStaticMethod(clazzName, "shutdown", null, null, cl );
+ }
+ }
+
+ /** Returns true if {@link #initSingleton()} has been called w/o subsequent {@link #shutdown(boolean)}. */
+ public static synchronized boolean isInitialized() { return initialized; }
+
+ /**
+ * Static one time initialization of this factory.<br>
+ * This initialization method <b>must be called</b> once by the program or utilizing modules!
+ */
+ public static synchronized void initSingleton() {
+ if(!initialized) {
+ initialized = true;
+
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.initSingleton()");
+ }
+
+ final ClassLoader cl = NativeWindowFactory.class.getClassLoader();
+
+ isAWTAvailable = false; // may be set to true below
+
+ if( Platform.AWT_AVAILABLE &&
+ ReflectionUtil.isClassAvailable("com.jogamp.nativewindow.awt.AWTGraphicsDevice", cl) ) {
+
+ final Method[] jawtUtilMethods = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
+ @Override
+ public Method[] run() {
+ try {
+ final Class<?> _jawtUtilClass = Class.forName(JAWTUtilClassName, true, NativeWindowFactory.class.getClassLoader());
+ final Method jawtUtilIsHeadlessMethod = _jawtUtilClass.getDeclaredMethod("isHeadlessMode", (Class[])null);
+ jawtUtilIsHeadlessMethod.setAccessible(true);
+ final Method jawtUtilInitMethod = _jawtUtilClass.getDeclaredMethod("initSingleton", (Class[])null);
+ jawtUtilInitMethod.setAccessible(true);
+ final Method jawtUtilGetJAWTToolkitLockMethod = _jawtUtilClass.getDeclaredMethod("getJAWTToolkitLock", new Class[]{});
+ jawtUtilGetJAWTToolkitLockMethod.setAccessible(true);
+ return new Method[] { jawtUtilInitMethod, jawtUtilIsHeadlessMethod, jawtUtilGetJAWTToolkitLockMethod };
+ } catch (final Exception e) {
+ if(DEBUG) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+ });
+ if(null != jawtUtilMethods) {
+ final Method jawtUtilInitMethod = jawtUtilMethods[0];
+ final Method jawtUtilIsHeadlessMethod = jawtUtilMethods[1];
+ final Method jawtUtilGetJAWTToolkitLockMethod = jawtUtilMethods[2];
+
+ ReflectionUtil.callMethod(null, jawtUtilInitMethod);
+
+ Object resO = ReflectionUtil.callMethod(null, jawtUtilIsHeadlessMethod);
+ if(resO instanceof Boolean) {
+ // AWT is only available in case all above classes are available
+ // and AWT is not int headless mode
+ isAWTAvailable = ((Boolean)resO).equals(Boolean.FALSE);
+ } else {
+ throw new RuntimeException("JAWTUtil.isHeadlessMode() didn't return a Boolean");
+ }
+ resO = ReflectionUtil.callMethod(null, jawtUtilGetJAWTToolkitLockMethod);
+ if(resO instanceof ToolkitLock) {
+ jawtUtilJAWTToolkitLock = (ToolkitLock) resO;
+ } else {
+ throw new RuntimeException("JAWTUtil.getJAWTToolkitLock() didn't return a ToolkitLock");
+ }
+ }
+ }
+
+ // X11 initialization after possible AWT initialization
+ // This is performed post AWT initialization, allowing AWT to complete the same,
+ // which may have been triggered before NativeWindow initialization.
+ // This way behavior is more uniforms across configurations (Applet/RCP, applications, ..).
+ initSingletonNativeImpl(cl);
+
+ registeredFactories = Collections.synchronizedMap(new HashMap<Class<?>, NativeWindowFactory>());
+
+ // register our default factory -> NativeWindow
+ final NativeWindowFactory factory = new NativeWindowFactoryImpl();
+ nativeWindowClass = com.jogamp.nativewindow.NativeWindow.class;
+ registerFactory(nativeWindowClass, factory);
+ defaultFactory = factory;
+
+ if ( isAWTAvailable ) {
+ // register either our default factory or (if exist) the X11/AWT one -> AWT Component
+ registerFactory(ReflectionUtil.getClass(ReflectionUtil.AWTNames.ComponentClass, false, cl), factory);
+ }
+
+ if(DEBUG) {
+ System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock+", desktopHasThreadingIssues "+desktopHasThreadingIssues);
+ System.err.println("NativeWindowFactory isAWTAvailable "+isAWTAvailable+", defaultFactory "+factory);
+ }
+
+ GraphicsConfigurationFactory.initSingleton();
+ }
+ }
+
+ /** @return true if the underlying toolkit requires locking, otherwise false. */
+ public static boolean requiresToolkitLock() {
+ return requiresToolkitLock;
+ }
+
+ /** @return true if not headless, AWT Component and NativeWindow's AWT part available */
+ public static boolean isAWTAvailable() { return isAWTAvailable; }
+
+ /**
+ * @param useCustom if false return the native value, if true return a custom value if set, otherwise fallback to the native value.
+ * @return the native window type, e.g. {@link #TYPE_X11}, which is canonical via {@link String#intern()}.
+ * Hence {@link String#equals(Object)} and <code>==</code> produce the same result.
+ */
+ public static String getNativeWindowType(final boolean useCustom) {
+ return useCustom?nativeWindowingTypeCustom:nativeWindowingTypePure;
+ }
+
+ /** Don't know if we shall add this factory here ..
+ public static AbstractGraphicsDevice createGraphicsDevice(String type, String connection, int unitID, long handle, ToolkitLock locker) {
+ if(TYPE_EGL == type) {
+ return new
+ } else if(TYPE_X11 == type) {
+ } else if(TYPE_WINDOWS == type) {
+ } else if(TYPE_MACOSX == type)) {
+ } else if(TYPE_AWT == type) {
+ } else if(TYPE_DEFAULT == type) {
+ }
+ } */
+
+ /** Sets the default NativeWindowFactory. */
+ public static void setDefaultFactory(final NativeWindowFactory factory) {
+ defaultFactory = factory;
+ }
+
+ /** Gets the default NativeWindowFactory. */
+ public static NativeWindowFactory getDefaultFactory() {
+ return defaultFactory;
+ }
+
+ /**
+ * Returns the AWT {@link ToolkitLock} (JAWT based) if {@link #isAWTAvailable}, otherwise null.
+ * <p>
+ * The JAWT based {@link ToolkitLock} also locks the global lock,
+ * which matters if the latter is required.
+ * </p>
+ */
+ public static ToolkitLock getAWTToolkitLock() {
+ return jawtUtilJAWTToolkitLock;
+ }
+
+ public static ToolkitLock getNullToolkitLock() {
+ return NativeWindowFactoryImpl.getNullToolkitLock();
+ }
+
+ /**
+ * Provides the system default {@link ToolkitLock} for the default system windowing type.
+ * @see #getNativeWindowType(boolean)
+ * @see #getDefaultToolkitLock(java.lang.String)
+ */
+ public static ToolkitLock getDefaultToolkitLock() {
+ return getDefaultToolkitLock(nativeWindowingTypePure);
+ }
+
+ /**
+ * Provides the default {@link ToolkitLock} for <code>type</code>.
+ * <ul>
+ * <li> JAWT {@link ToolkitLock} if required and <code>type</code> is of {@link #TYPE_AWT} and AWT available,</li>
+ * <li> {@link jogamp.nativewindow.ResourceToolkitLock} if required, otherwise</li>
+ * <li> {@link jogamp.nativewindow.NullToolkitLock} </li>
+ * </ul>
+ */
+ public static ToolkitLock getDefaultToolkitLock(final String type) {
+ if( requiresToolkitLock ) {
+ if( TYPE_AWT == type && isAWTAvailable() ) { // uses .intern()!
+ return getAWTToolkitLock();
+ }
+ return ResourceToolkitLock.create();
+ }
+ return NativeWindowFactoryImpl.getNullToolkitLock();
+ }
+
+ /**
+ * Provides the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>.
+ * <ul>
+ * <li> JAWT {@link ToolkitLock} if required and <code>type</code> is of {@link #TYPE_AWT} and AWT available,</li>
+ * <li> {@link jogamp.nativewindow.ResourceToolkitLock} if required, otherwise</li>
+ * <li> {@link jogamp.nativewindow.NullToolkitLock} </li>
+ * </ul>
+ */
+ public static ToolkitLock getDefaultToolkitLock(final String type, final long deviceHandle) {
+ if( requiresToolkitLock ) {
+ if( TYPE_AWT == type && isAWTAvailable() ) { // uses .intern()!
+ return getAWTToolkitLock();
+ }
+ return ResourceToolkitLock.create();
+ }
+ return NativeWindowFactoryImpl.getNullToolkitLock();
+ }
+
+ /**
+ * @param device
+ * @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen
+ * @return newly created AbstractGraphicsScreen matching device's native type
+ */
+ public static AbstractGraphicsScreen createScreen(final AbstractGraphicsDevice device, int screen) {
+ final String type = device.getType();
+ if( TYPE_X11 == type ) {
+ final X11GraphicsDevice x11Device = (X11GraphicsDevice)device;
+ if(0 > screen) {
+ screen = x11Device.getDefaultScreen();
+ }
+ return new X11GraphicsScreen(x11Device, screen);
+ }
+ if(0 > screen) {
+ screen = 0; // FIXME: Needs native API utilization
+ }
+ if( TYPE_AWT == type ) {
+ final AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) device;
+ return new AWTGraphicsScreen(awtDevice);
+ }
+ return new DefaultGraphicsScreen(device, screen);
+ }
+
+ /** Returns the appropriate NativeWindowFactory to handle window
+ objects of the given type. The windowClass might be {@link
+ NativeWindow NativeWindow}, in which case the client has
+ already assumed the responsibility of creating a compatible
+ NativeWindow implementation, or it might be that of a toolkit
+ class like {@link java.awt.Component Component}. */
+ public static NativeWindowFactory getFactory(final Class<?> windowClass) throws IllegalArgumentException {
+ if (nativeWindowClass.isAssignableFrom(windowClass)) {
+ return registeredFactories.get(nativeWindowClass);
+ }
+ Class<?> clazz = windowClass;
+ while (clazz != null) {
+ final NativeWindowFactory factory = registeredFactories.get(clazz);
+ if (factory != null) {
+ return factory;
+ }
+ clazz = clazz.getSuperclass();
+ }
+ throw new IllegalArgumentException("No registered NativeWindowFactory for class " + windowClass.getName());
+ }
+
+ /** Registers a NativeWindowFactory handling window objects of the
+ given class. This does not need to be called by end users,
+ only implementors of new NativeWindowFactory subclasses. */
+ protected static void registerFactory(final Class<?> windowClass, final NativeWindowFactory factory) {
+ if(DEBUG) {
+ System.err.println("NativeWindowFactory.registerFactory() "+windowClass+" -> "+factory);
+ }
+ registeredFactories.put(windowClass, factory);
+ }
+
+ /** Converts the given window object and it's
+ {@link AbstractGraphicsConfiguration AbstractGraphicsConfiguration} into a
+ {@link NativeWindow NativeWindow} which can be operated upon by a custom
+ toolkit, e.g. {@link com.jogamp.opengl.GLDrawableFactory com.jogamp.opengl.GLDrawableFactory}.<br>
+ The object may be a component for a particular window toolkit, such as an AWT
+ Canvas. It may also be a NativeWindow object itself.<br>
+ You shall utilize {@link com.jogamp.nativewindow.GraphicsConfigurationFactory GraphicsConfigurationFactory}
+ to construct a proper {@link AbstractGraphicsConfiguration AbstractGraphicsConfiguration}.<br>
+ The particular implementation of the
+ NativeWindowFactory is responsible for handling objects from a
+ particular window toolkit. The built-in NativeWindowFactory
+ handles NativeWindow instances as well as AWT Components.<br>
+
+ @throws IllegalArgumentException if the given window object
+ could not be handled by any of the registered
+ NativeWindowFactory instances
+
+ @see com.jogamp.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
+ */
+ public static NativeWindow getNativeWindow(final Object winObj, final AbstractGraphicsConfiguration config) throws IllegalArgumentException, NativeWindowException {
+ if (winObj == null) {
+ throw new IllegalArgumentException("Null window object");
+ }
+
+ return getFactory(winObj.getClass()).getNativeWindowImpl(winObj, config);
+ }
+
+ /** Performs the conversion from a toolkit's window object to a
+ NativeWindow. Implementors of concrete NativeWindowFactory
+ subclasses should override this method. */
+ protected abstract NativeWindow getNativeWindowImpl(Object winObj, AbstractGraphicsConfiguration config) throws IllegalArgumentException;
+
+ /**
+ * Returns the {@link OffscreenLayerSurface} instance of this {@link NativeSurface}.
+ * <p>
+ * In case this surface is a {@link NativeWindow}, we traverse from the given surface
+ * up to root until an implementation of {@link OffscreenLayerSurface} is found.
+ * In case <code>ifEnabled</code> is true, the surface must also implement {@link OffscreenLayerOption}
+ * where {@link OffscreenLayerOption#isOffscreenLayerSurfaceEnabled()} is <code>true</code>.
+ * </p>
+ *
+ * @param surface The surface to query.
+ * @param ifEnabled If true, only return the enabled {@link OffscreenLayerSurface}, see {@link OffscreenLayerOption#isOffscreenLayerSurfaceEnabled()}.
+ * @return
+ */
+ public static OffscreenLayerSurface getOffscreenLayerSurface(final NativeSurface surface, final boolean ifEnabled) {
+ if(surface instanceof OffscreenLayerSurface &&
+ ( !ifEnabled || surface instanceof OffscreenLayerOption ) ) {
+ final OffscreenLayerSurface ols = (OffscreenLayerSurface) surface;
+ return ( !ifEnabled || ((OffscreenLayerOption)ols).isOffscreenLayerSurfaceEnabled() ) ? ols : null;
+ }
+ if(surface instanceof NativeWindow) {
+ NativeWindow nw = ((NativeWindow) surface).getParent();
+ while(null != nw) {
+ if(nw instanceof OffscreenLayerSurface &&
+ ( !ifEnabled || nw instanceof OffscreenLayerOption ) ) {
+ final OffscreenLayerSurface ols = (OffscreenLayerSurface) nw;
+ return ( !ifEnabled || ((OffscreenLayerOption)ols).isOffscreenLayerSurfaceEnabled() ) ? ols : null;
+ }
+ nw = nw.getParent();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if the given visualID is valid for further processing, i.e. OpenGL usage,
+ * otherwise return false.
+ * <p>
+ * On certain platforms, i.e. X11, a valid visualID is required at window creation.
+ * Other platforms may determine it later on, e.g. OSX and Windows. </p>
+ * <p>
+ * If the visualID is {@link VisualIDHolder#VID_UNDEFINED} and the platform requires it
+ * at creation time (see above), it is not valid for further processing.
+ * </p>
+ */
+ public static boolean isNativeVisualIDValidForProcessing(final int visualID) {
+ return NativeWindowFactory.TYPE_X11 != NativeWindowFactory.getNativeWindowType(false) ||
+ VisualIDHolder.VID_UNDEFINED != visualID ;
+ }
+
+ /**
+ * Creates a native device type, following {@link #getNativeWindowType(boolean) getNativeWindowType(true)}.
+ * <p>
+ * The device will be opened if <code>own</code> is true, otherwise no native handle will ever be acquired.
+ * </p>
+ */
+ public static AbstractGraphicsDevice createDevice(final String displayConnection, final boolean own) {
+ final String nwt = NativeWindowFactory.getNativeWindowType(true);
+ if( NativeWindowFactory.TYPE_X11 == nwt ) {
+ if( own ) {
+ return new X11GraphicsDevice(displayConnection, AbstractGraphicsDevice.DEFAULT_UNIT, null /* ToolkitLock */);
+ } else {
+ return new X11GraphicsDevice(displayConnection, AbstractGraphicsDevice.DEFAULT_UNIT);
+ }
+ } else if( NativeWindowFactory.TYPE_WINDOWS == nwt ) {
+ return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ } else if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
+ return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+ /**
+ * FIXME: Needs service provider interface (SPI) for TK dependent implementation
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_ANDROID== nwt ) {
+ } else if( NativeWindowFactory.TYPE_EGL == nwt ) {
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_AWT == nwt ) {
+ */
+ }
+ throw new UnsupportedOperationException("n/a for windowing system: "+nwt);
+ }
+
+ /**
+ * Creates a wrapped {@link NativeWindow} with given native handles and {@link AbstractGraphicsScreen}.
+ * <p>
+ * The given {@link UpstreamWindowHookMutableSizePos} maybe used to reflect resizes and repositioning of the native window.
+ * </p>
+ * <p>
+ * The {@link AbstractGraphicsScreen} may be created via {@link #createScreen(AbstractGraphicsDevice, int)}.
+ * </p>
+ * <p>
+ * The {@link AbstractGraphicsScreen} may have an underlying open {@link AbstractGraphicsDevice}
+ * or a simple <i>dummy</i> instance, see {@link #createDevice(String, boolean)}.
+ * </p>
+ */
+ public static NativeWindow createWrappedWindow(final AbstractGraphicsScreen aScreen, final long surfaceHandle, final long windowHandle,
+ final UpstreamWindowHookMutableSizePos hook) {
+ final CapabilitiesImmutable caps = new Capabilities();
+ final AbstractGraphicsConfiguration config = new DefaultGraphicsConfiguration(aScreen, caps, caps);
+ return new WrappedWindow(config, surfaceHandle, hook, true, windowHandle);
+ }
+
+ /**
+ * @param nw
+ * @return top-left client-area position in window units
+ */
+ public static PointImmutable getLocationOnScreen(final NativeWindow nw) {
+ final String nwt = NativeWindowFactory.getNativeWindowType(true);
+ if( NativeWindowFactory.TYPE_X11 == nwt ) {
+ return X11Lib.GetRelativeLocation(nw.getDisplayHandle(), nw.getScreenIndex(), nw.getWindowHandle(), 0, 0, 0);
+ } else if( NativeWindowFactory.TYPE_WINDOWS == nwt ) {
+ return GDIUtil.GetRelativeLocation(nw.getWindowHandle(), 0, 0, 0);
+ } else if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
+ return OSXUtil.GetLocationOnScreen(nw.getWindowHandle(), 0, 0);
+ /**
+ * FIXME: Needs service provider interface (SPI) for TK dependent implementation
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_ANDROID== nwt ) {
+ } else if( NativeWindowFactory.TYPE_EGL == nwt ) {
+ } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
+ } else if( NativeWindowFactory.TYPE_AWT == nwt ) {
+ */
+ }
+ throw new UnsupportedOperationException("n/a for windowing system: "+nwt);
+ }
+
+
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/OffscreenLayerOption.java b/src/nativewindow/classes/com/jogamp/nativewindow/OffscreenLayerOption.java
new file mode 100644
index 000000000..2e9f2c172
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/OffscreenLayerOption.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright 2011 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;
+
+/**
+ * Handling requests for using an {@link OffscreenLayerSurface}
+ * within the implementation.
+ */
+public interface OffscreenLayerOption {
+ /**
+ * Request an offscreen layer, if supported.
+ * <p>
+ * Shall be called before the first {@link NativeWindow#lockSurface()},
+ * and hence before realization.
+ * </p>
+ *
+ * @see #getShallUseOffscreenLayer()
+ * @see #isOffscreenLayerSurfaceEnabled()
+ */
+ public void setShallUseOffscreenLayer(boolean v);
+
+ /** Returns the property set by {@link #setShallUseOffscreenLayer(boolean)}. */
+ public boolean getShallUseOffscreenLayer();
+
+ /**
+ * Returns true if this instance uses an offscreen layer, otherwise false.
+ * <p>
+ * This instance is an offscreen layer, if {@link #setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
+ * has been called before it's realization and first lock and the underlying implementation supports it.
+ * </p>
+ * The return value is undefined before issuing the first {@link NativeWindow#lockSurface()}.
+ *
+ * @see #setShallUseOffscreenLayer(boolean)
+ */
+ public boolean isOffscreenLayerSurfaceEnabled();
+} \ No newline at end of file
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/OffscreenLayerSurface.java
new file mode 100644
index 000000000..abba2c126
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/OffscreenLayerSurface.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright 2011 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 com.jogamp.nativewindow.util.PixelRectangle;
+import com.jogamp.nativewindow.util.PointImmutable;
+
+import com.jogamp.common.util.locks.RecursiveLock;
+
+/**
+ * Interface specifying the offscreen layer surface protocol.
+ */
+public interface OffscreenLayerSurface {
+ /**
+ * Attach the offscreen layer to this offscreen layer surface.
+ * <p>
+ * Implementation may realize all required resources at this point.
+ * </p>
+ *
+ * @see #isOffscreenLayerSurfaceEnabled()
+ * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
+ */
+ public void attachSurfaceLayer(final long layerHandle) throws NativeWindowException;
+
+ /**
+ * Detaches a previously attached offscreen layer from this offscreen layer surface.
+ * @see #attachSurfaceLayer(long)
+ * @see #isOffscreenLayerSurfaceEnabled()
+ * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
+ * or no surface layer is attached.
+ */
+ public void detachSurfaceLayer() throws NativeWindowException;
+
+ /** Returns the attached surface layer or null if none is attached. */
+ public long getAttachedSurfaceLayer();
+
+ /** Returns true if a surface layer is attached, otherwise false. */
+ public boolean isSurfaceLayerAttached();
+
+ /** Sets the capabilities of this instance, allowing upstream API's to refine it, i.e. OpenGL related settings. */
+ public void setChosenCapabilities(CapabilitiesImmutable caps);
+
+ /** Returns the recursive lock object of this surface, which synchronizes multithreaded access. */
+ public RecursiveLock getLock();
+
+ /**
+ * Optional method setting cursor in the corresponding on-screen surface/window, if exists.
+ *
+ * @param pixelrect cursor pixels, maybe null for default cursor
+ * @param hotSpot maybe null for default cursor
+ * @return true if successful, i.e. on-screen surface/window w/ cursor capabilities exists. Otherwise false.
+ */
+ public boolean setCursor(PixelRectangle pixelrect, PointImmutable hotSpot);
+
+ /**
+ * Optional method hiding the cursor in the corresponding on-screen surface/window, if exists.
+ *
+ * @return true if successful, i.e. on-screen surface/window w/ cursor capabilities exists. Otherwise false.
+ */
+ public boolean hideCursor();
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/ProxySurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/ProxySurface.java
new file mode 100644
index 000000000..7b36531dc
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/ProxySurface.java
@@ -0,0 +1,135 @@
+/**
+ * Copyright 2012 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 jogamp.nativewindow.Debug;
+
+/**
+ * Provides a mutable {@link NativeSurface}, i.e. {@link MutableSurface}, while allowing an
+ * {@link UpstreamSurfaceHook} to influence the lifecycle and information.
+ *
+ * @see UpstreamSurfaceHook
+ * @see MutableSurface
+ * @see NativeSurface
+ */
+public interface ProxySurface extends MutableSurface {
+ public static final boolean DEBUG = Debug.debug("ProxySurface");
+
+ /**
+ * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's surface handle
+ * @see #addUpstreamOptionBits(int)
+ * @see #clearUpstreamOptionBits(int)
+ * @see #getUpstreamOptionBits()
+ */
+ public static final int OPT_PROXY_OWNS_UPSTREAM_SURFACE = 1 << 6;
+
+ /**
+ * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's {@link AbstractGraphicsDevice}.
+ * @see #addUpstreamOptionBits(int)
+ * @see #clearUpstreamOptionBits(int)
+ * @see #getUpstreamOptionBits()
+ */
+ public static final int OPT_PROXY_OWNS_UPSTREAM_DEVICE = 1 << 7;
+
+ /**
+ * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete.
+ * @see #addUpstreamOptionBits(int)
+ * @see #clearUpstreamOptionBits(int)
+ * @see #getUpstreamOptionBits()
+ */
+ 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);
+
+ /**
+ * Returns the optional upstream {@link NativeSurface} if used by implementation, otherwise <code>null</code>.
+ * <p>
+ * The upstream {@link NativeSurface} is retrieved via {@link #getUpstreamSurfaceHook() the UpstreamSurfaceHook},
+ * i.e. {@link UpstreamSurfaceHook#getUpstreamSurface()}.
+ * </p>
+ * <p>
+ * One example is the JOGL EGLWrappedSurface, which might be backed up by a
+ * native platform NativeSurface (X11, WGL, CGL, ..).
+ * </p>
+ */
+ public NativeSurface getUpstreamSurface();
+
+ /** Returns the {@link UpstreamSurfaceHook} if {@link #setUpstreamSurfaceHook(UpstreamSurfaceHook) set}, otherwise <code>null</code>. */
+ public UpstreamSurfaceHook getUpstreamSurfaceHook();
+
+ /**
+ * Overrides the {@link UpstreamSurfaceHook}.
+ */
+ public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook);
+
+ /**
+ * Enables or disables the {@link UpstreamSurfaceHook} lifecycle functions
+ * {@link UpstreamSurfaceHook#create(ProxySurface)} and {@link UpstreamSurfaceHook#destroy(ProxySurface)}.
+ * <p>
+ * Use this for small code blocks where the native resources shall not change,
+ * i.e. resizing a derived (OpenGL) drawable.
+ * </p>
+ */
+ public void enableUpstreamSurfaceHookLifecycle(boolean enable);
+
+ /**
+ * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set.
+ */
+ public void createNotify();
+
+ /**
+ * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all proxy surface/window handles shall be cleared.
+ */
+ public void destroyNotify();
+
+ public StringBuilder getUpstreamOptionBits(StringBuilder sink);
+ public int getUpstreamOptionBits();
+
+ /** Returns <code>true</code> if the give bit-mask <code>v</code> is set in this instance upstream-option-bits, otherwise <code>false</code>.*/
+ public boolean containsUpstreamOptionBits(int v);
+
+ /** Add the given bit-mask to this instance upstream-option-bits using bit-or w/ <code>v</code>.*/
+ public void addUpstreamOptionBits(int v);
+
+ /** Clear the given bit-mask from this instance upstream-option-bits using bit-and w/ <code>~v</code>*/
+ public void clearUpstreamOptionBits(int v);
+
+ public StringBuilder toString(StringBuilder sink);
+ @Override
+ public String toString();
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/ScalableSurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/ScalableSurface.java
new file mode 100644
index 000000000..eea9e4bed
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/ScalableSurface.java
@@ -0,0 +1,107 @@
+/**
+ * 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;
+
+/**
+ * Adding mutable surface pixel scale property to implementing class, usually to a {@link NativeSurface} implementation,
+ * see {@link #setSurfaceScale(float[])}.
+ */
+public interface ScalableSurface {
+ /** Setting surface-pixel-scale of {@value}, results in same pixel- and window-units. */
+ public static final float IDENTITY_PIXELSCALE = 1f;
+ /** Setting surface-pixel-scale of {@value}, results in maximum platform dependent pixel-scale, i.e. pixel-units >> window-units where available. */
+ public static final float AUTOMAX_PIXELSCALE = 0f;
+
+ /**
+ * Request a pixel scale in x- and y-direction for the associated {@link NativeSurface},
+ * where {@code size_in_pixel_units = pixel_scale * size_in_window_units}.
+ * <p>
+ * Default pixel scale request for both directions is {@link #AUTOMAX_PIXELSCALE}.
+ * </p>
+ * <p>
+ * In case platform only supports uniform pixel scale, i.e. one scale for both directions,
+ * either {@link #AUTOMAX_PIXELSCALE} or the maximum requested pixel scale component is used.
+ * </p>
+ * <p>
+ * The <i>requested</i> pixel scale will be validated against platform limits before native scale-setup,
+ * i.e. clipped to {@link #IDENTITY_PIXELSCALE} if not supported or clipped to the platform maximum.
+ * It can be queried via {@link #getRequestedSurfaceScale(float[])}.
+ * </p>
+ * <p>
+ * The actual <i>realized</i> pixel scale values of the {@link NativeSurface}
+ * can be queried via {@link #getCurrentSurfaceScale(float[])} or
+ * computed via <code>surface.{@link NativeSurface#convertToPixelUnits(int[]) convertToPixelUnits}(new int[] { 1, 1 })</code>
+ * </p>
+ * @param pixelScale <i>requested</i> surface pixel scale float[2] values for x- and y-direction.
+ * @return {@code true} if the {@link #getCurrentSurfaceScale(float[]) current pixel scale} has changed, otherwise {@code false}.
+ * @see #getRequestedSurfaceScale(float[])
+ */
+ public boolean setSurfaceScale(final float[] pixelScale);
+
+ /**
+ * Returns the {@link #setSurfaceScale(float[]) requested} pixel scale of the associated {@link NativeSurface}.
+ *
+ * @param result float[2] storage for the result
+ * @return the passed storage containing the current pixelScale for chaining
+ * @see #setSurfaceScale(float[])
+ */
+ public float[] getRequestedSurfaceScale(final float[] result);
+
+ /**
+ * Returns the current pixel scale of the associated {@link NativeSurface}.
+ *
+ * @param result float[2] storage for the result
+ * @return the passed storage containing the current pixelScale for chaining
+ */
+ public float[] getCurrentSurfaceScale(final float[] result);
+
+ /**
+ * Returns the minimum pixel scale of the associated {@link NativeSurface}.
+ * @param result float[2] storage for the result
+ * @return the passed storage containing the minimum pixelScale for chaining
+ */
+ public float[] getMinimumSurfaceScale(final float[] result);
+
+ /**
+ * Returns the maximum pixel scale of the associated {@link NativeSurface}.
+ * <p>
+ * The maximum pixel scale maybe used to determine the proper <i>dpi</i>
+ * value of the monitor displaying this {@link NativeSurface}.
+ * <pre>
+ * surfacePpMM = monitorPpMM * currentSurfaceScale / nativeSurfaceScale,
+ * with PpMM == pixel per millimeter
+ * </pre>
+ * </p>
+ *
+ * @param result float[2] storage for the result
+ * @return the passed storage containing the maximum pixelScale for chaining
+ */
+ public float[] getMaximumSurfaceScale(final float[] result);
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/SurfaceUpdatedListener.java b/src/nativewindow/classes/com/jogamp/nativewindow/SurfaceUpdatedListener.java
new file mode 100644
index 000000000..37e4bd0c9
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/SurfaceUpdatedListener.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+package com.jogamp.nativewindow;
+
+/**
+ * Clients may add their SurfaceUpdateListener implementation to a {@link com.jogamp.nativewindow.NativeSurface}
+ * allowing to get notified after the surface has been updated, eg. after a swap buffer operation.
+ */
+public interface SurfaceUpdatedListener {
+ /** Notification of a surface update event, eg. after a swap buffer operation.
+ *
+ * @param updater is the caller object who updated the surface,
+ * e.g. a JOGL GLDrawable.
+ * @param ns the updated NativeSurface
+ * @param when the time in ms, when the surface was updated
+ */
+ public void surfaceUpdated(Object updater, NativeSurface ns, long when) ;
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/ToolkitLock.java b/src/nativewindow/classes/com/jogamp/nativewindow/ToolkitLock.java
new file mode 100644
index 000000000..eef11adb7
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/ToolkitLock.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow;
+
+import jogamp.nativewindow.Debug;
+
+/**
+ * Marker for a singleton global recursive blocking lock implementation,
+ * optionally locking a native windowing toolkit as well.
+ * <p>
+ * Toolkit locks are created solely via {@link NativeWindowFactory}.
+ * </p>
+ * <p>
+ * One use case is the AWT locking on X11, see {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}.
+ * </p>
+ */
+public interface ToolkitLock {
+ public static final boolean DEBUG = Debug.debug("ToolkitLock");
+ public static final boolean TRACE_LOCK = Debug.isPropertyDefined("nativewindow.debug.ToolkitLock.TraceLock", true);
+
+ /**
+ * Blocking until the lock is acquired by this Thread or a timeout is reached.
+ * <p>
+ * Timeout is implementation specific, if used at all.
+ * </p>
+ *
+ * @throws RuntimeException in case of a timeout
+ */
+ public void lock();
+
+ /**
+ * Release the lock.
+ *
+ * @throws RuntimeException in case the lock is not acquired by this thread.
+ */
+ public void unlock();
+
+ /**
+ * @throws RuntimeException if current thread does not hold the lock
+ */
+ public void validateLocked() throws RuntimeException;
+
+ /**
+ * Dispose this instance.
+ * <p>
+ * Shall be called when instance is no more required.
+ * </p>
+ * This allows implementations sharing a lock via resources
+ * to decrease the reference counter.
+ */
+ public void dispose();
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHook.java b/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHook.java
new file mode 100644
index 000000000..5e9b8d293
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHook.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright 2012 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;
+
+/**
+ * Interface allowing upstream caller to pass lifecycle actions and size info
+ * to a {@link ProxySurface} instance.
+ */
+public interface UpstreamSurfaceHook {
+ /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */
+ public void create(ProxySurface s);
+ /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */
+ public void destroy(ProxySurface s);
+
+ /**
+ * Returns the optional upstream {@link NativeSurface} if used by implementation, otherwise <code>null</code>.
+ * <p>
+ * One example is the JOGL EGLWrappedSurface, which might be backed up by a
+ * native platform NativeSurface (X11, WGL, CGL, ..).
+ * </p>
+ */
+ public NativeSurface getUpstreamSurface();
+
+ /** Returns the width of the upstream surface in pixels, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */
+ public int getSurfaceWidth(ProxySurface s);
+ /** Returns the height of the upstream surface in pixels, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */
+ public int getSurfaceHeight(ProxySurface s);
+
+ /**
+ * {@link UpstreamSurfaceHook} w/ mutable size, allowing it's {@link ProxySurface} user to resize.
+ */
+ public interface MutableSize extends UpstreamSurfaceHook {
+ /**
+ * Resizes the upstream surface.
+ * @param width new width in pixel units
+ * @param height new height in pixel units
+ */
+ public void setSurfaceSize(int width, int height);
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/VisualIDHolder.java b/src/nativewindow/classes/com/jogamp/nativewindow/VisualIDHolder.java
new file mode 100644
index 000000000..69bfe50f8
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/VisualIDHolder.java
@@ -0,0 +1,136 @@
+/**
+ * Copyright 2012 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 java.util.Comparator;
+
+/**
+ * Visual ID holder interface.
+ * <p>
+ * Allows queries of different types of native visual IDs,
+ * see {@link #getVisualID(int)}.
+ * </p>
+ */
+public interface VisualIDHolder {
+
+ public enum VIDType {
+ // Generic Values
+ INTRINSIC(0), NATIVE(1),
+ // EGL Values
+ EGL_CONFIG(10),
+ // X11 Values
+ X11_XVISUAL(20), X11_FBCONFIG(21),
+ // Windows Values
+ WIN32_PFD(30);
+
+ public final int id;
+
+ VIDType(final int id){
+ this.id = id;
+ }
+ }
+
+ /**
+ * Returns the native visual ID of the given <code>type</code>
+ * if supported, or {@link #VID_UNDEFINED} if not supported.
+ * <p>
+ * Depending on the native windowing system, <code>type</code> is handled as follows:
+ * <ul>
+ * <li>X11 throws NativeWindowException on <code>EGL_CONFIG</code>, <code>WIN32_PFD</code>
+ * <ul>
+ * <li><code>INTRINSIC</code>: <i>X11 XVisual ID</i></li>
+ * <li><code>NATIVE</code>: <i>X11 XVisual ID</i></li>
+ * <li><code>X11_XVISUAL</code>: <i>X11 XVisual ID</i></li>
+ * <li><code>X11_FBCONFIG</code>: <code>VID_UNDEFINED</code></li>
+ * </ul></li>
+ * <li>X11/GL throws NativeWindowException on <code>EGL_CONFIG</code>, <code>WIN32_PFD</code>
+ * <ul>
+ * <li><code>INTRINSIC</code>: <i>X11 XVisual ID</i></li>
+ * <li><code>NATIVE</code>: <i>X11 XVisual ID</i></li>
+ * <li><code>X11_XVISUAL</code>: <i>X11 XVisual ID</i></li>
+ * <li><code>X11_FBCONFIG</code>: <i>X11 FBConfig ID</i> or <code>VID_UNDEFINED</code></li>
+ * </ul></li>
+ * <li>Windows/GL throws NativeWindowException on <code>EGL_CONFIG</code>, <code>X11_XVISUAL</code>, <code>X11_FBCONFIG</code>
+ * <ul>
+ * <li><code>INTRINSIC</code>: <i>Win32 PIXELFORMATDESCRIPTOR ID</i></li>
+ * <li><code>NATIVE</code>: <i>Win32 PIXELFORMATDESCRIPTOR ID</i></li>
+ * <li><code>WIN32_PFD</code>: <i>Win32 PIXELFORMATDESCRIPTOR ID</i></li>
+ * </ul></li>
+ * <li>EGL/GL throws NativeWindowException on <code>X11_XVISUAL</code>, <code>X11_FBCONFIG</code>, <code>WIN32_PFD</code>
+ * <ul>
+ * <li><code>INTRINSIC</code>: <i>EGL Config ID</i></li>
+ * <li><code>NATIVE</code>: <i>EGL NativeVisual ID</i> (<i>X11 XVisual ID</i>, <i>Win32 PIXELFORMATDESCRIPTOR ID</i>, ...)</li>
+ * <li><code>EGL_CONFIG</code>: <i>EGL Config ID</i></li>
+ * </ul></li>
+ * </ul>
+ * </p>
+ * Note: <code>INTRINSIC</code> and <code>NATIVE</code> are always handled,
+ * but may result in {@link #VID_UNDEFINED}. The latter is true if
+ * the native value are actually undefined or the corresponding object is not
+ * mapped to a native visual object.
+ *
+ * @throws NativeWindowException if <code>type</code> is neither
+ * <code>INTRINSIC</code> nor <code>NATIVE</code>
+ * and does not match the native implementation.
+ */
+ int getVisualID(VIDType type) throws NativeWindowException ;
+
+ /**
+ * {@link #getVisualID(VIDType)} result indicating an undefined value,
+ * which could be cause by an unsupported query.
+ * <p>
+ * We assume the const value <code>0</code> doesn't reflect a valid native visual ID
+ * and is interpreted as <i>no value</i> on all platforms.
+ * This is currently true for Android, X11 and Windows.
+ * </p>
+ */
+ static final int VID_UNDEFINED = 0;
+
+ /** Comparing {@link VIDType#NATIVE} */
+ public static class VIDComparator implements Comparator<VisualIDHolder> {
+ private final VIDType type;
+
+ public VIDComparator(final VIDType type) {
+ this.type = type;
+ }
+
+ @Override
+ public int compare(final VisualIDHolder vid1, final VisualIDHolder vid2) {
+ final int id1 = vid1.getVisualID(type);
+ final int id2 = vid2.getVisualID(type);
+
+ if(id1 > id2) {
+ return 1;
+ } else if(id1 < id2) {
+ return -1;
+ }
+ return 0;
+ }
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/WindowClosingProtocol.java b/src/nativewindow/classes/com/jogamp/nativewindow/WindowClosingProtocol.java
new file mode 100644
index 000000000..f4f8a02e1
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/WindowClosingProtocol.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow;
+
+/**
+ * Protocol for handling window closing events.
+ * <p>
+ * The implementation shall obey either the user value set by this interface,<br>
+ * an underlying toolkit set user value or it's default, eg. {@link WindowClosingMode#DO_NOTHING_ON_CLOSE DO_NOTHING_ON_CLOSE} within an AWT environment.<br>
+ * If none of the above determines the operation,
+ * this protocol default behavior {@link WindowClosingMode#DISPOSE_ON_CLOSE DISPOSE_ON_CLOSE} shall be used.</p>
+ */
+public interface WindowClosingProtocol {
+
+ /**
+ * Window closing mode if triggered by toolkit close operation.
+ */
+ public enum WindowClosingMode {
+ /**
+ * Do nothing on native window close operation.<br>
+ * This is the default behavior within an AWT environment.
+ */
+ DO_NOTHING_ON_CLOSE,
+
+ /**
+ * Dispose resources on native window close operation.<br>
+ * This is the default behavior in case no underlying toolkit defines otherwise.
+ */
+ DISPOSE_ON_CLOSE;
+ }
+
+
+ /**
+ * @return the current close operation value
+ * @see WindowClosingMode#DISPOSE_ON_CLOSE
+ * @see WindowClosingMode#DO_NOTHING_ON_CLOSE
+ */
+ WindowClosingMode getDefaultCloseOperation();
+
+ /**
+ * @param op the new close operation value
+ * @return the previous close operation value
+ * @see WindowClosingMode#DISPOSE_ON_CLOSE
+ * @see WindowClosingMode#DO_NOTHING_ON_CLOSE
+ */
+ WindowClosingMode setDefaultCloseOperation(WindowClosingMode op);
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/package.html b/src/nativewindow/classes/com/jogamp/nativewindow/package.html
new file mode 100644
index 000000000..1fe52eea4
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/package.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+ <title>NativeWindow Specification Overview</title>
+</head>
+ <body>
+
+<h2><i>NativeWindow Protocol</i> Specification Overview</h2>
+
+<h3>Preface</h3>
+ This specification, an optional set of packages, describing a <i>protocol</i> for a
+ <i>native windowing interface</i> binding to Java(TM).<br>
+ Currently specified <i>native windowing systems</i> are:
+ <ul>
+ <li> EGL/OpenKODE Windowing System</li>
+ <li> X11 Windowing System</li>
+ <li> Microsoft Windows</li>
+ <li> Apple MacOSX</li>
+ <li> Java's AWT</li>
+ </ul>
+ <br>
+ However, any other native windowing system may be added to the implementation,
+ using a generic string identifier and an optional specialisation of:
+ <ul>
+ <li>{@link com.jogamp.nativewindow.AbstractGraphicsDevice AbstractGraphicsDevice},
+ <p>Shall return the new string identifier with {@link com.jogamp.nativewindow.AbstractGraphicsDevice#getType() getType()}</p></li>
+ <li>{@link com.jogamp.nativewindow.AbstractGraphicsScreen AbstractGraphicsScreen}</li>
+ <li>{@link com.jogamp.nativewindow.AbstractGraphicsConfiguration AbstractGraphicsConfiguration}</li>
+ </ul>
+ <p>The implementor has to provide the following:</p>
+ <ul>
+ <li> The specialisation of the abstract class {@link com.jogamp.nativewindow.NativeWindowFactory NativeWindowFactory}
+ <p>shall be registered with {@link com.jogamp.nativewindow.NativeWindowFactory#registerFactory NativeWindowFactory.registerFactory(..)}.</p></li>
+
+ <li> The specialisation of the abstract class {@link com.jogamp.nativewindow.GraphicsConfigurationFactory GraphicsConfigurationFactory}
+ <p>shall be registered with {@link com.jogamp.nativewindow.GraphicsConfigurationFactory#registerFactory GraphicsConfigurationFactory.registerFactory(..)}.</p></li>
+ </ul>
+ <p>This protocol <i>does not</i> describe how to <i>create</i> native windows, but how to <i>bind</i> a native surface to an implementation of
+ and window to an implementation of {@link com.jogamp.nativewindow.NativeSurface NativeSurface}.</p>
+ <p>{@link com.jogamp.nativewindow.NativeWindow NativeWindow} specializes the NativeSurface.</p>
+ <p>However, an implementation of this protocol (e.g. {@link com.jogamp.newt}) may support the creation.</p>
+
+<h3>Dependencies</h3>
+ This binding has dependencies to the following:
+ <ul>
+ <li> Either of the following Java implementations:
+ <ul>
+ <li> <a href="http://docs.oracle.com/javase/6/docs/api/">Java SE 1.6 or later</a> </li>
+ <li> A mobile JavaVM with language 1.6 support, ie:
+ <ul>
+ <li> <a href="http://developer.android.com/reference/packages.html">Android API Level 9 (Version 2.3)</a> </li>
+ <li> <a href="http://jamvm.sourceforge.net/">JamVM</a> </li>
+ </ul>
+ with
+ <ul>
+ <li> <a href="http://docs.oracle.com/javase/1.4.2/docs/api/java/nio/package-summary.html"> Java 1.4 <i>java.nio</i> implementation</a> </li>
+ </ul></li>
+ </ul></li>
+ </ul>
+ <br>
+
+<h3>Package Structure</h3>
+ The packages defined by this specification include:
+<ul>
+ <li>The <b>com.jogamp.nativewindow</b> package
+ <p>This package contains Java bindings for a native windowing system.</p>
+ <p>Subsequent packages contain marker type classes, containing native characteristics of the windowing system.</p>
+ <ul>
+ <li>The <b>com.jogamp.nativewindow.awt</b> package
+ <p>This sub package contains classes to cover the native characteristics of the AWT windowing system.</p></li>
+
+ <li>The <b>com.jogamp.nativewindow.x11</b> package
+ <p>This sub package contains classes to cover the native characteristics of the X11 windowing system.</p></li>
+
+ <li>The <b>com.jogamp.nativewindow.windows</b> package
+ <p>This sub package contains classes to cover the native characteristics of the Windows windowing system.</p></li>
+
+ <li>The <b>com.jogamp.nativewindow.macosx</b> package
+ <p>This sub package contains classes to cover the native characteristics of the MacOSX windowing system.</p></li>
+
+ <li>The <b>com.jogamp.nativewindow.egl</b> package
+ <p>This sub package contains classes to cover the native characteristics of the EGL/OpenKODE windowing system.</p></li>
+ </ul></li>
+</ul>
+
+<h3>Factory Model</h3>
+<p>Running on a platform with a supported windowing system, the factory model shall be used
+to instantiate a native window, see {@link com.jogamp.nativewindow.NativeWindowFactory NativeWindowFactory}.</p>
+
+<h3>Revision History</h3>
+
+<ul>
+<li> Early Draft Review, June 2009</li>
+<li> 2.0.0 Maintenance Release, February 2011</li>
+<li> 2.0.2 Major Release, July 18th 2013</li>
+</ul>
+ <br>
+ <br>
+ <br>
+</body>
+</html>
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/Dimension.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/Dimension.java
new file mode 100644
index 000000000..28c5dd90e
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/Dimension.java
@@ -0,0 +1,128 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow.util;
+
+public class Dimension implements Cloneable, DimensionImmutable {
+ int width;
+ int height;
+
+ public Dimension() {
+ this(0, 0);
+ }
+
+ public Dimension(final int[] size) {
+ this(size[0], size[1]);
+ }
+
+ public Dimension(final int width, final int height) {
+ if(width<0 || height<0) {
+ throw new IllegalArgumentException("width and height must be within: ["+0+".."+Integer.MAX_VALUE+"]");
+ }
+ this.width=width;
+ this.height=height;
+ }
+
+ @Override
+ public Object cloneMutable() {
+ return clone();
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (final CloneNotSupportedException ex) {
+ throw new InternalError();
+ }
+ }
+
+ @Override
+ public final int getWidth() { return width; }
+ @Override
+ public final int getHeight() { return height; }
+
+ public final void set(final int width, final int height) {
+ this.width = width;
+ this.height = height;
+ }
+ public final void setWidth(final int width) {
+ this.width = width;
+ }
+ public final void setHeight(final int height) {
+ this.height = height;
+ }
+ public final Dimension scale(final int s) {
+ width *= s;
+ height *= s;
+ return this;
+ }
+ public final Dimension add(final Dimension pd) {
+ width += pd.width ;
+ height += pd.height ;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return width + " x " + height;
+ }
+
+ @Override
+ public int compareTo(final DimensionImmutable d) {
+ final int tsq = width*height;
+ final int xsq = d.getWidth()*d.getHeight();
+
+ if(tsq > xsq) {
+ return 1;
+ } else if(tsq < xsq) {
+ return -1;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if (obj instanceof Dimension) {
+ final Dimension p = (Dimension)obj;
+ return height == p.height &&
+ width == p.width ;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ final int hash = 31 + width;
+ return ((hash << 5) - hash) + height;
+ }
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/DimensionImmutable.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/DimensionImmutable.java
new file mode 100644
index 000000000..6de77a716
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/DimensionImmutable.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow.util;
+
+import com.jogamp.common.type.WriteCloneable;
+
+/** Immutable Dimension Interface, consisting of it's read only components:<br>
+ * <ul>
+ * <li><code>width</code></li>
+ * <li><code>height</code></li>
+ * </ul>
+ */
+public interface DimensionImmutable extends WriteCloneable, Comparable<DimensionImmutable> {
+
+ int getHeight();
+
+ int getWidth();
+
+ /**
+ * <p>
+ * Compares square of size.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final DimensionImmutable d);
+
+ /**
+ * Checks whether two dimensions objects are equal. Two instances
+ * of <code>DimensionReadOnly</code> are equal if two components
+ * <code>height</code> and <code>width</code> are equal.
+ * @return <code>true</code> if the two dimensions are equal;
+ * otherwise <code>false</code>.
+ */
+ @Override
+ boolean equals(Object obj);
+
+ @Override
+ int hashCode();
+
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/Insets.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/Insets.java
new file mode 100644
index 000000000..205e18346
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/Insets.java
@@ -0,0 +1,136 @@
+/**
+ * Copyright 2011 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.util;
+
+/**
+ * Mutable insets representing rectangular window decoration insets on all four edges
+ * in window units.
+ */
+public class Insets implements Cloneable, InsetsImmutable {
+ static final InsetsImmutable zeroInsets = new Insets();
+ public static final InsetsImmutable getZero() { return zeroInsets; }
+
+ private int l, r, t, b;
+
+ public Insets() {
+ this(0, 0, 0, 0);
+ }
+
+ public Insets(final int left, final int right, final int top, final int bottom) {
+ this.l=left;
+ this.r=right;
+ this.t=top;
+ this.b=bottom;
+ }
+
+ @Override
+ public Object cloneMutable() {
+ return clone();
+ }
+
+ @Override
+ protected Object clone() {
+ try {
+ return super.clone();
+ } catch (final CloneNotSupportedException ex) {
+ throw new InternalError();
+ }
+ }
+
+ @Override
+ public final int getLeftWidth() { return l; }
+ @Override
+ public final int getRightWidth() { return r; }
+ @Override
+ public final int getTotalWidth() { return l + r; }
+ @Override
+ public final int getTopHeight() { return t; }
+ @Override
+ public final int getBottomHeight() { return b; }
+ @Override
+ public final int getTotalHeight() { return t + b; }
+
+ /**
+ * Set the inset values of this instance in window units.
+ * @param left left inset width in window units.
+ * @param right right inset width in window units.
+ * @param top top inset width in window units.
+ * @param bottom bottom inset width in window units.
+ */
+ public final void set(final int left, final int right, final int top, final int bottom) {
+ l = left; r = right; t = top; b = bottom;
+ }
+ /**
+ * Set the left inset value of this instance in window units.
+ * @param left left inset width in window units.
+ */
+ public final void setLeftWidth(final int left) { l = left; }
+ /**
+ * Set the right inset value of this instance in window units.
+ * @param right right inset width in window units.
+ */
+ public final void setRightWidth(final int right) { r = right; }
+ /**
+ * Set the top inset value of this instance in window units.
+ * @param top top inset width in window units.
+ */
+ public final void setTopHeight(final int top) { t = top; }
+ /**
+ * Set the bottom inset value of this instance in window units.
+ * @param bottom bottom inset width in window units.
+ */
+ public final void setBottomHeight(final int bottom) { b = bottom; }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if (obj instanceof Insets) {
+ final Insets insets = (Insets)obj;
+ return (r == insets.r) && (l == insets.l) &&
+ (b == insets.b) && (t == insets.t);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ final int sum1 = l + b;
+ final int sum2 = t + r;
+ final int val1 = sum1 * (sum1 + 1)/2 + l;
+ final int val2 = sum2 * (sum2 + 1)/2 + r;
+ final int sum3 = val1 + val2;
+ return sum3 * (sum3 + 1)/2 + val2;
+ }
+
+ @Override
+ public String toString() {
+ return "[ l "+l+", r "+r+" - t "+t+", b "+b+" - "+getTotalWidth()+"x"+getTotalHeight()+"]";
+ }
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/InsetsImmutable.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/InsetsImmutable.java
new file mode 100644
index 000000000..e626a507e
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/InsetsImmutable.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright 2011 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.util;
+
+import com.jogamp.common.type.WriteCloneable;
+
+/**
+ * Immutable insets representing rectangular window decoration insets on all four edges
+ * in window units.
+ */
+public interface InsetsImmutable extends WriteCloneable {
+
+ /** @return left inset width in window units. */
+ int getLeftWidth();
+
+ /** @return right inset width in window units. */
+ int getRightWidth();
+
+ /** @return total width in window units, ie. <code>left_width + right_width</code> */
+ int getTotalWidth();
+
+ /** @return top inset height in window units. */
+ int getTopHeight();
+
+ /** @return bottom inset height in window units. */
+ int getBottomHeight();
+
+ /** @return total height in window units, ie. <code>top_height + bottom_height</code> */
+ int getTotalHeight();
+
+ /**
+ * Checks whether two rect objects are equal. Two instances
+ * of <code>Insets</code> are equal if the four integer values
+ * of the fields <code>left</code>, <code>right</code>,
+ * <code>top</code>, and <code>bottom</code> are all equal.
+ * @return <code>true</code> if the two Insets are equal;
+ * otherwise <code>false</code>.
+ */
+ @Override
+ boolean equals(Object obj);
+
+ @Override
+ int hashCode();
+
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/PixelFormat.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/PixelFormat.java
new file mode 100644
index 000000000..8b1e91564
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/PixelFormat.java
@@ -0,0 +1,739 @@
+/**
+ * Copyright (c) 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.util;
+
+import java.util.Arrays;
+
+import com.jogamp.common.util.IntBitfield;
+
+/**
+ * Basic pixel formats
+ * <p>
+ * Notation follows OpenGL notation, i.e.
+ * name consist of all it's component names
+ * followed by their bit size.
+ * </p>
+ * <p>
+ * Order of component names is from lowest-bit to highest-bit.
+ * </p>
+ * <p>
+ * In case component-size is 1 byte (e.g. OpenGL data-type GL_UNSIGNED_BYTE),
+ * component names are ordered from lowest-byte to highest-byte.
+ * Note that OpenGL applies special interpretation if
+ * data-type is e.g. GL_UNSIGNED_8_8_8_8_REV or GL_UNSIGNED_8_8_8_8_REV.
+ * </p>
+ * <p>
+ * PixelFormat can be converted to OpenGL GLPixelAttributes
+ * via
+ * <pre>
+ * GLPixelAttributes glpa = GLPixelAttributes.convert(PixelFormat pixFmt, GLProfile glp);
+ * </pre>
+ * </p>
+ * <p>
+ * See OpenGL Specification 4.3 - February 14, 2013, Core Profile,
+ * Section 8.4.4 Transfer of Pixel Rectangles, p. 161-174.
+ * </ul>
+ *
+ * </p>
+ */
+public enum PixelFormat {
+ /**
+ * 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>
+ * <li>AWT: <i>none</i></li>
+ * </ul>
+ * </p>
+ */
+ LUMINANCE(new CType[]{ CType.Y }, 1, 8, 8),
+
+ /**
+ * 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>
+ * Compatible with:
+ * <ul>
+ * <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_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>
+ */
+ 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 ),
+
+ /**
+ * 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>
+ * Compatible with:
+ * <ul>
+ * <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>
+ * <li>OpenGL: data-format GL_BGR (>= GL2), data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_3BYTE_BGR TYPE_3BYTE_BGR}</li>
+ * </ul>
+ * </p>
+ */
+ 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),
+
+ /**
+ * 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>
+ * Compatible with:
+ * <ul>
+ * <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>
+ * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: <i>None</i></li>
+ * <li>PointerIcon: OSX (NSBitmapImageRep)</li>
+ * <li>Window Icon: OSX (NSBitmapImageRep)</li>
+ * <li>PNGJ: Scanlines</li>
+ * </ul>
+ * </p>
+ */
+ RGBA8888(new CType[]{ CType.R, CType.G, CType.B, CType.A }, 4, 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>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_INT_8_8_8_8</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_4BYTE_ABGR TYPE_4BYTE_ABGR}</li>
+ * </ul>
+ * </p>
+ */
+ ABGR8888(new CType[]{ CType.A, CType.B, CType.G, CType.R }, 4, 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>A: 0xFF << 0</li>
+ * <li>R: 0xFF << 8</li>
+ * <li>G: 0xFF << 16</li>
+ * <li>B: 0xFF << 24</li>
+ * </ol>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_BGRA, data-type GL_UNSIGNED_INT_8_8_8_8</li>
+ * <li>AWT: <i>None</i></li>
+ * </ul>
+ * </p>
+ */
+ ARGB8888(new CType[]{ CType.A, CType.R, CType.G, CType.B }, 4, 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>B: 0xFF << 0</li>
+ * <li>G: 0xFF << 8</li>
+ * <li>R: 0xFF << 16</li>
+ * <li>A: 0xFF << 24</li>
+ * </ol>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_BGRA, data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_INT_ARGB TYPE_INT_ARGB}</li>
+ * <li>PointerIcon: X11 (XCURSOR), Win32, AWT</li>
+ * <li>Window Icon: X11, Win32</li>
+ * </ul>
+ * </p>
+ */
+ 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();
+ }
+
+ /**
+ * @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 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/com/jogamp/nativewindow/util/PixelFormatUtil.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/PixelFormatUtil.java
new file mode 100644
index 000000000..180f02d72
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/PixelFormatUtil.java
@@ -0,0 +1,600 @@
+/**
+ * Copyright (c) 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.util;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.Bitstream;
+
+/**
+ * Pixel Rectangle Utilities.
+ * <p>
+ * All conversion methods are endian independent.
+ * </p>
+ */
+public class PixelFormatUtil {
+ private static boolean DEBUG = false;
+
+ public static class ComponentMap {
+ /**
+ * Contains the source index for each destination index,
+ * length is {@link Composition#componenCount()} of destination.
+ */
+ final int[] dst2src;
+ /**
+ * Contains the destination index for each source index,
+ * length is {@link Composition#componenCount()} of source.
+ */
+ final int[] src2dst;
+
+ /**
+ * Contains the source index of RGBA components.
+ */
+ 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;
+ }
+ }
+
+ /**
+ * 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 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");
+ }
+ }
+
+ /**
+ * Returns the {@link PixelFormat} with reversed components of <code>fmt</code>.
+ * If no reversed {@link PixelFormat} is available, returns <code>fmt</code>.
+ */
+ public static PixelFormat getReversed(final PixelFormat fmt) {
+ switch(fmt) {
+ 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:
+ return PixelFormat.RGB888;
+ case RGBA8888:
+ return PixelFormat.ABGR8888;
+ case ABGR8888:
+ return PixelFormat.RGBA8888;
+ case ARGB8888:
+ return PixelFormat.BGRA8888;
+ case BGRA8888:
+ return PixelFormat.ABGR8888;
+ default:
+ return 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 l = ( byte) ( ( ( ( 0xff & r ) + ( 0xff & g ) + ( 0xff & b ) ) / 3 ) * a );
+ return ( 0xff ) << 24 | ( 0xff & l ) << 16 | ( 0xff & l ) << 8 | ( 0xff & l );
+ }
+ case RGB888:
+ return ( 0xff ) << 24 | ( 0xff & b ) << 16 | ( 0xff & g ) << 8 | ( 0xff & r );
+ case BGR888:
+ return ( 0xff ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b );
+ case RGBA8888:
+ return ( 0xff & a ) << 24 | ( 0xff & b ) << 16 | ( 0xff & g ) << 8 | ( 0xff & r );
+ case ABGR8888:
+ return ( 0xff & r ) << 24 | ( 0xff & g ) << 16 | ( 0xff & b ) << 8 | ( 0xff & a );
+ case ARGB8888:
+ return ( 0xff & b ) << 24 | ( 0xff & g ) << 16 | ( 0xff & r ) << 8 | ( 0xff & a );
+ case BGRA8888:
+ return ( 0xff & a ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b );
+ default:
+ throw new InternalError("Unhandled format "+dst_fmt);
+ }
+ }
+
+ 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:
+ r = src.get(srcOff++); // R
+ g = r; // G
+ b = r; // B
+ a = (byte) 0xff; // A
+ break;
+ case RGB888:
+ r = src.get(srcOff++); // R
+ g = src.get(srcOff++); // G
+ b = src.get(srcOff++); // B
+ a = (byte) 0xff; // A
+ break;
+ case BGR888:
+ b = src.get(srcOff++); // B
+ g = src.get(srcOff++); // G
+ r = src.get(srcOff++); // R
+ a = (byte) 0xff; // A
+ break;
+ case RGBA8888:
+ r = src.get(srcOff++); // R
+ g = src.get(srcOff++); // G
+ b = src.get(srcOff++); // B
+ a = src.get(srcOff++); // A
+ break;
+ case ABGR8888:
+ a = src.get(srcOff++); // A
+ b = src.get(srcOff++); // B
+ g = src.get(srcOff++); // G
+ r = src.get(srcOff++); // R
+ break;
+ case ARGB8888:
+ a = src.get(srcOff++); // A
+ r = src.get(srcOff++); // R
+ g = src.get(srcOff++); // G
+ b = src.get(srcOff++); // B
+ break;
+ case BGRA8888:
+ b = src.get(srcOff++); // B
+ g = src.get(srcOff++); // G
+ r = src.get(srcOff++); // R
+ a = src.get(srcOff++); // A
+ break;
+ default:
+ throw new InternalError("Unhandled format "+src_fmt);
+ }
+ return convertToInt32(dst_fmt, r, g, b, a);
+ }
+
+ public static int convertToInt32(final PixelFormat dest_fmt, final PixelFormat src_fmt, final int src_pixel) {
+ final byte r, g, b, a;
+ switch(src_fmt) {
+ case LUMINANCE:
+ r = (byte) ( src_pixel ); // R
+ g = r; // G
+ b = r; // B
+ a = (byte) 0xff; // A
+ break;
+ case RGB888:
+ r = (byte) ( src_pixel ); // R
+ g = (byte) ( src_pixel >>> 8 ); // G
+ b = (byte) ( src_pixel >>> 16 ); // B
+ a = (byte) 0xff; // A
+ break;
+ case BGR888:
+ b = (byte) ( src_pixel ); // B
+ g = (byte) ( src_pixel >>> 8 ); // G
+ r = (byte) ( src_pixel >>> 16 ); // R
+ a = (byte) 0xff; // A
+ break;
+ case RGBA8888:
+ r = (byte) ( src_pixel ); // R
+ g = (byte) ( src_pixel >>> 8 ); // G
+ b = (byte) ( src_pixel >>> 16 ); // B
+ a = (byte) ( src_pixel >>> 24 ); // A
+ break;
+ case ABGR8888:
+ a = (byte) ( src_pixel ); // A
+ b = (byte) ( src_pixel >>> 8 ); // B
+ g = (byte) ( src_pixel >>> 16 ); // G
+ r = (byte) ( src_pixel >>> 24 ); // R
+ break;
+ case ARGB8888:
+ a = (byte) ( src_pixel ); // A
+ r = (byte) ( src_pixel >>> 8 ); // R
+ g = (byte) ( src_pixel >>> 16 ); // G
+ b = (byte) ( src_pixel >>> 24 ); // B
+ break;
+ case BGRA8888:
+ b = (byte) ( src_pixel ); // B
+ g = (byte) ( src_pixel >>> 8 ); // G
+ r = (byte) ( src_pixel >>> 16 ); // R
+ a = (byte) ( src_pixel >>> 24 ); // A
+ break;
+ default:
+ throw new InternalError("Unhandled format "+src_fmt);
+ }
+ return convertToInt32(dest_fmt, r, g, b, a);
+ }
+
+ 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.comp.bytesPerPixel();
+ final int destStride;
+ if( 0 != ddestStride ) {
+ destStride = ddestStride;
+ } else {
+ destStride = bpp * width;
+ }
+ final int capacity = destStride*height;
+ 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);
+ }
+
+ /**
+ * @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 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 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 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 {
+ 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);
+ }
+
+ if( fast_copy ) {
+ // Fast copy
+ for(int y=0; y<height; y++) {
+ 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++) {
+ 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
+ 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/com/jogamp/nativewindow/util/PixelRectangle.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/PixelRectangle.java
new file mode 100644
index 000000000..f58ba0ce2
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/PixelRectangle.java
@@ -0,0 +1,194 @@
+/**
+ * Copyright (c) 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.util;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Pixel Rectangle identified by it's {@link #hashCode()}.
+ * <p>
+ * The {@link #getPixels()} are assumed to be immutable.
+ * </p>
+ */
+public interface PixelRectangle {
+ /**
+ * <p>
+ * Computes a hash code over:
+ * <ul>
+ * <li>pixelformat</li>
+ * <li>size</li>
+ * <li>stride</li>
+ * <li>isGLOriented</li>
+ * <li>pixels</li>
+ * </ul>
+ * </p>
+ * <p>
+ * The hashCode shall be computed only once with first call
+ * and stored for later retrieval to enhance performance.
+ * </p>
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ @Override
+ int hashCode();
+
+ /** Returns the {@link PixelFormat}. */
+ PixelFormat getPixelformat();
+
+ /** Returns the size, i.e. width and height. */
+ DimensionImmutable getSize();
+
+ /**
+ * 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>
+ */
+ int getStride();
+
+ /**
+ * Returns <code>true</code> if the 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>.
+ */
+ public boolean isGLOriented();
+
+ /** Returns the pixels. */
+ ByteBuffer getPixels();
+
+ @Override
+ String toString();
+
+ /**
+ * Generic PixelRectangle implementation
+ */
+ public static class GenericPixelRect implements PixelRectangle {
+ protected final PixelFormat pixelformat;
+ protected final DimensionImmutable size;
+ protected final int strideInBytes;
+ protected final boolean isGLOriented;
+ protected final ByteBuffer pixels;
+ private int hashCode = 0;
+ private volatile boolean hashCodeComputed = false;
+
+ /**
+ *
+ * @param pixelformat
+ * @param size
+ * @param strideInBytes stride in byte-size, i.e. byte count from one line to the next.
+ * If not zero, value must be >= <code>width * bytes-per-pixel</code>.
+ * If zero, stride is set to <code>width * bytes-per-pixel</code>.
+ * @param isGLOriented
+ * @param pixels
+ * @throws IllegalArgumentException if <code>strideInBytes</code> is invalid.
+ * @throws IndexOutOfBoundsException if <code>pixels</code> has insufficient bytes left
+ */
+ public GenericPixelRect(final PixelFormat pixelformat, final DimensionImmutable size, int strideInBytes, final boolean isGLOriented, final ByteBuffer pixels)
+ throws IllegalArgumentException, IndexOutOfBoundsException
+ {
+ if( 0 != strideInBytes ) {
+ 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.comp.bytesPerPixel() * size.getWidth();
+ }
+ final int reqBytes = strideInBytes * size.getHeight();
+ if( pixels.limit() < reqBytes ) {
+ throw new IndexOutOfBoundsException("Dest buffer has insufficient bytes left, needs "+reqBytes+": "+pixels);
+ }
+ this.pixelformat = pixelformat;
+ this.size = size;
+ this.strideInBytes = strideInBytes;
+ this.isGLOriented = isGLOriented;
+ this.pixels = pixels;
+ }
+
+ /**
+ * Copy ctor validating src.
+ * @param src
+ * @throws IllegalArgumentException if <code>strideInBytes</code> is invalid.
+ * @throws IndexOutOfBoundsException if <code>pixels</code> has insufficient bytes left
+ */
+ public GenericPixelRect(final PixelRectangle src)
+ throws IllegalArgumentException, IndexOutOfBoundsException
+ {
+ this(src.getPixelformat(), src.getSize(), src.getStride(), src.isGLOriented(), src.getPixels());
+ }
+
+ @Override
+ public int hashCode() {
+ if( !hashCodeComputed ) { // DBL CHECKED OK VOLATILE
+ synchronized (this) {
+ if( !hashCodeComputed ) {
+ // 31 * x == (x << 5) - x
+ int hash = pixelformat.comp.hashCode();
+ hash = ((hash << 5) - hash) + size.hashCode();
+ hash = ((hash << 5) - hash) + strideInBytes;
+ hash = ((hash << 5) - hash) + ( isGLOriented ? 1 : 0);
+ hashCode = ((hash << 5) - hash) + pixels.hashCode();
+ hashCodeComputed = true;
+ }
+ }
+ }
+ return hashCode;
+ }
+
+ @Override
+ public PixelFormat getPixelformat() {
+ return pixelformat;
+ }
+
+ @Override
+ public DimensionImmutable getSize() {
+ return size;
+ }
+
+ @Override
+ public int getStride() {
+ return strideInBytes;
+ }
+
+ @Override
+ public boolean isGLOriented() {
+ return isGLOriented;
+ }
+
+ @Override
+ public ByteBuffer getPixels() {
+ return pixels;
+ }
+
+ @Override
+ public final String toString() {
+ return "PixelRect[obj 0x"+Integer.toHexString(super.hashCode())+", "+pixelformat+", "+size+", stride "+strideInBytes+", isGLOrient "+isGLOriented+", pixels "+pixels+"]";
+ }
+ }
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/Point.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/Point.java
new file mode 100644
index 000000000..fc5465bbf
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/Point.java
@@ -0,0 +1,190 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow.util;
+
+public class Point implements Cloneable, PointImmutable {
+ int x;
+ int y;
+
+ public Point(final int x, final int y) {
+ this.x=x;
+ this.y=y;
+ }
+
+ public Point() {
+ this(0, 0);
+ }
+
+ @Override
+ public Object cloneMutable() {
+ return clone();
+ }
+
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (final CloneNotSupportedException ex) {
+ throw new InternalError();
+ }
+ }
+
+ @Override
+ public int compareTo(final PointImmutable d) {
+ final int sq = x*y;
+ final int xsq = d.getX()*d.getY();
+
+ if(sq > xsq) {
+ return 1;
+ } else if(sq < xsq) {
+ return -1;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if (obj instanceof Point) {
+ final Point p = (Point)obj;
+ return y == p.y && x == p.x;
+ }
+ return false;
+ }
+
+ @Override
+ public final int getX() {
+ return x;
+ }
+
+ @Override
+ public final int getY() {
+ return y;
+ }
+
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + x;
+ hash = ((hash << 5) - hash) + y;
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return x + " / " + y;
+ }
+
+ public final void set(final int x, final int y) { this.x = x; this.y = y; }
+ public final void setX(final int x) { this.x = x; }
+ public final void setY(final int y) { this.y = y; }
+
+ /**
+ * Translate this instance's x- and y-components,
+ * i.e. add the values of the given delta point to them.
+ * @param pd delta point
+ * @return this instance for scaling
+ */
+ public final Point translate(final Point pd) {
+ x += pd.x ;
+ y += pd.y ;
+ return this;
+ }
+
+ /**
+ * Translate this instance's x- and y-components,
+ * i.e. add the given deltas to them.
+ * @param dx delta for x
+ * @param dy delta for y
+ * @return this instance for scaling
+ */
+ public final Point translate(final int dx, final int dy) {
+ x += dx ;
+ y += dy ;
+ return this;
+ }
+
+ /**
+ * Scale this instance's x- and y-components,
+ * i.e. multiply them by the given scale factors.
+ * @param sx scale factor for x
+ * @param sy scale factor for y
+ * @return this instance for scaling
+ */
+ public final Point scale(final int sx, final int sy) {
+ x *= sx ;
+ y *= sy ;
+ return this;
+ }
+
+ /**
+ * Scale this instance's x- and y-components,
+ * i.e. multiply them by the given scale factors.
+ * <p>
+ * The product is rounded back to integer.
+ * </p>
+ * @param sx scale factor for x
+ * @param sy scale factor for y
+ * @return this instance for scaling
+ */
+ public final Point scale(final float sx, final float sy) {
+ x = (int)(x * sx + 0.5f);
+ y = (int)(y * sy + 0.5f);
+ return this;
+ }
+
+ /**
+ * Inverse scale this instance's x- and y-components,
+ * i.e. divide them by the given scale factors.
+ * @param sx inverse scale factor for x
+ * @param sy inverse scale factor for y
+ * @return this instance for scaling
+ */
+ public final Point scaleInv(final int sx, final int sy) {
+ x /= sx ;
+ y /= sy ;
+ return this;
+ }
+ /**
+ * Inverse scale this instance's x- and y-components,
+ * i.e. divide them by the given scale factors.
+ * <p>
+ * The product is rounded back to integer.
+ * </p>
+ * @param sx inverse scale factor for x
+ * @param sy inverse scale factor for y
+ * @return this instance for scaling
+ */
+ public final Point scaleInv(final float sx, final float sy) {
+ x = (int)(x / sx + 0.5f);
+ y = (int)(y / sy + 0.5f);
+ return this;
+ }
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/PointImmutable.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/PointImmutable.java
new file mode 100644
index 000000000..59372f67d
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/PointImmutable.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow.util;
+
+import com.jogamp.common.type.WriteCloneable;
+
+/** Immutable Point interface */
+public interface PointImmutable extends WriteCloneable, Comparable<PointImmutable> {
+
+ int getX();
+
+ int getY();
+
+ /**
+ * <p>
+ * Compares the square of the position.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final PointImmutable d);
+
+ /**
+ * Checks whether two points objects are equal. Two instances
+ * of <code>PointReadOnly</code> are equal if the two components
+ * <code>y</code> and <code>x</code> are equal.
+ * @return <code>true</code> if the two points are equal;
+ * otherwise <code>false</code>.
+ */
+ @Override
+ public boolean equals(Object obj);
+
+ @Override
+ public int hashCode();
+
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/Rectangle.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/Rectangle.java
new file mode 100644
index 000000000..33a1955e8
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/Rectangle.java
@@ -0,0 +1,237 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow.util;
+
+import java.util.List;
+
+public class Rectangle implements Cloneable, RectangleImmutable {
+ int x;
+ int y;
+ int width;
+ int height;
+
+ public Rectangle() {
+ this(0, 0, 0, 0);
+ }
+
+ public Rectangle(final int x, final int y, final int width, final int height) {
+ this.x=x;
+ this.y=y;
+ this.width=width;
+ this.height=height;
+ }
+
+ @Override
+ public Object cloneMutable() {
+ return clone();
+ }
+
+ @Override
+ protected Object clone() {
+ try {
+ return super.clone();
+ } catch (final CloneNotSupportedException ex) {
+ throw new InternalError();
+ }
+ }
+
+ @Override
+ public final int getX() { return x; }
+ @Override
+ public final int getY() { return y; }
+ @Override
+ public final int getWidth() { return width; }
+ @Override
+ public final int getHeight() { return height; }
+
+ public final void set(final int x, final int y, final int width, final int height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+ public final void set(final Rectangle s) {
+ this.x = s.x;
+ this.y = s.y;
+ this.width = s.width;
+ this.height = s.height;
+ }
+ public final void setX(final int x) { this.x = x; }
+ public final void setY(final int y) { this.y = y; }
+ public final void setWidth(final int width) { this.width = width; }
+ public final void setHeight(final int height) { this.height = height; }
+
+ @Override
+ public final RectangleImmutable union(final RectangleImmutable r) {
+ return union(r.getX(), r.getY(), r.getX() + r.getWidth(), r.getY() + r.getHeight());
+ }
+ @Override
+ public final RectangleImmutable union(final int rx1, final int ry1, final int rx2, final int ry2) {
+ final int x1 = Math.min(x, rx1);
+ final int y1 = Math.min(y, ry1);
+ final int x2 = Math.max(x + width, rx2);
+ final int y2 = Math.max(y + height, ry2);
+ return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+ }
+ /**
+ * Calculates the union of the given rectangles, stores it in this instance and returns this instance.
+ * @param rectangles given list of rectangles
+ * @return this instance holding the union of given rectangles.
+ */
+ public final Rectangle union(final List<RectangleImmutable> rectangles) {
+ int x1=Integer.MAX_VALUE, y1=Integer.MAX_VALUE;
+ int x2=Integer.MIN_VALUE, y2=Integer.MIN_VALUE;
+ for(int i=rectangles.size()-1; i>=0; i--) {
+ final RectangleImmutable vp = rectangles.get(i);
+ x1 = Math.min(x1, vp.getX());
+ x2 = Math.max(x2, vp.getX() + vp.getWidth());
+ y1 = Math.min(y1, vp.getY());
+ y2 = Math.max(y2, vp.getY() + vp.getHeight());
+ }
+ set(x1, y1, x2 - x1, y2 - y1);
+ return this;
+ }
+
+ @Override
+ public final RectangleImmutable intersection(final RectangleImmutable r) {
+ return intersection(r.getX(), r.getY(), r.getX() + r.getWidth(), r.getY() + r.getHeight());
+ }
+ @Override
+ public final RectangleImmutable intersection(final int rx1, final int ry1, final int rx2, final int ry2) {
+ final int x1 = Math.max(x, rx1);
+ final int y1 = Math.max(y, ry1);
+ final int x2 = Math.min(x + width, rx2);
+ final int y2 = Math.min(y + height, ry2);
+ final int ix, iy, iwidth, iheight;
+ if( x2 < x1 ) {
+ ix = 0;
+ iwidth = 0;
+ } else {
+ ix = x1;
+ iwidth = x2 - x1;
+ }
+ if( y2 < y1 ) {
+ iy = 0;
+ iheight = 0;
+ } else {
+ iy = y1;
+ iheight = y2 - y1;
+ }
+ return new Rectangle (ix, iy, iwidth, iheight);
+ }
+ @Override
+ public final float coverage(final RectangleImmutable r) {
+ final RectangleImmutable isect = intersection(r);
+ final float sqI = isect.getWidth()*isect.getHeight();
+ final float sqT = width*height;
+ return sqI / sqT;
+ }
+
+ /**
+ * Scale this instance's components,
+ * i.e. multiply them by the given scale factors.
+ * @param sx scale factor for x
+ * @param sy scale factor for y
+ * @return this instance for scaling
+ */
+ public final Rectangle scale(final int sx, final int sy) {
+ x *= sx ;
+ y *= sy ;
+ width *= sx ;
+ height *= sy ;
+ return this;
+ }
+
+ /**
+ * Inverse scale this instance's components,
+ * i.e. divide them by the given scale factors.
+ * @param sx inverse scale factor for x
+ * @param sy inverse scale factor for y
+ * @return this instance for scaling
+ */
+ public final Rectangle scaleInv(final int sx, final int sy) {
+ x /= sx ;
+ y /= sy ;
+ width /= sx ;
+ height /= sy ;
+ return this;
+ }
+
+ @Override
+ public int compareTo(final RectangleImmutable d) {
+ {
+ final int sq = width*height;
+ final int xsq = d.getWidth()*d.getHeight();
+
+ if(sq > xsq) {
+ return 1;
+ } else if(sq < xsq) {
+ return -1;
+ }
+ }
+ {
+ final int sq = x*y;
+ final int xsq = d.getX()*d.getY();
+
+ if(sq > xsq) {
+ return 1;
+ } else if(sq < xsq) {
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if (obj instanceof Rectangle) {
+ final Rectangle rect = (Rectangle)obj;
+ return (y == rect.y) && (x == rect.x) &&
+ (height == rect.height) && (width == rect.width);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ final int sum1 = x + height;
+ final int sum2 = width + y;
+ final int val1 = sum1 * (sum1 + 1)/2 + x;
+ final int val2 = sum2 * (sum2 + 1)/2 + y;
+ final int sum3 = val1 + val2;
+ return sum3 * (sum3 + 1)/2 + val2;
+ }
+
+ @Override
+ public String toString() {
+ return "[ "+x+" / "+y+" "+width+" x "+height+" ]";
+ }
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/RectangleImmutable.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/RectangleImmutable.java
new file mode 100644
index 000000000..ff2209598
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/RectangleImmutable.java
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow.util;
+
+import com.jogamp.common.type.WriteCloneable;
+
+/** Immutable Rectangle interface */
+public interface RectangleImmutable extends WriteCloneable, Comparable<RectangleImmutable> {
+
+ int getHeight();
+
+ int getWidth();
+
+ int getX();
+
+ int getY();
+
+ /** Returns the union of this rectangle and the given rectangle. */
+ RectangleImmutable union(final RectangleImmutable r);
+ /** Returns the union of this rectangleand the given coordinates. */
+ RectangleImmutable union(final int rx1, final int ry1, final int rx2, final int ry2);
+ /** Returns the intersection of this rectangleand the given rectangle. */
+ RectangleImmutable intersection(RectangleImmutable r);
+ /** Returns the intersection of this rectangleand the given coordinates. */
+ RectangleImmutable intersection(final int rx1, final int ry1, final int rx2, final int ry2);
+ /**
+ * Returns the coverage of given rectangle w/ this this one, i.e. between <code>0.0</code> and <code>1.0</code>.
+ * <p>
+ * Coverage is computed by:
+ * <pre>
+ * isect = this.intersection(r);
+ * coverage = area( isect ) / area( this ) ;
+ * </pre>
+ * </p>
+ */
+ float coverage(RectangleImmutable r);
+
+ /**
+ * <p>
+ * Compares square of size 1st, if equal the square of position.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final RectangleImmutable d);
+
+ /**
+ * Checks whether two rect objects are equal. Two instances
+ * of <code>Rectangle</code> are equal if the four integer values
+ * of the fields <code>y</code>, <code>x</code>,
+ * <code>height</code>, and <code>width</code> are all equal.
+ * @return <code>true</code> if the two rectangles are equal;
+ * otherwise <code>false</code>.
+ */
+ @Override
+ boolean equals(Object obj);
+
+ @Override
+ int hashCode();
+
+}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/util/SurfaceSize.java b/src/nativewindow/classes/com/jogamp/nativewindow/util/SurfaceSize.java
new file mode 100644
index 000000000..b9e6ded95
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/util/SurfaceSize.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.nativewindow.util;
+
+/**
+ * Immutable SurfaceSize Class, consisting of it's read only components:<br>
+ * <ul>
+ * <li>{@link com.jogamp.nativewindow.util.DimensionImmutable size in pixels}</li>
+ * <li><code>bits per pixel</code></li>
+ * </ul>
+ */
+public class SurfaceSize implements Comparable<SurfaceSize> {
+ final DimensionImmutable resolution;
+ final int bitsPerPixel;
+
+ public SurfaceSize(final DimensionImmutable resolution, final int bitsPerPixel) {
+ if(null==resolution || bitsPerPixel<=0) {
+ throw new IllegalArgumentException("resolution must be set and bitsPerPixel greater 0");
+ }
+ this.resolution=resolution;
+ this.bitsPerPixel=bitsPerPixel;
+ }
+
+ /** Returns the resolution in pixel units */
+ public final DimensionImmutable getResolution() {
+ return resolution;
+ }
+
+ public final int getBitsPerPixel() {
+ return bitsPerPixel;
+ }
+
+ @Override
+ public final String toString() {
+ return "[ "+resolution+" pixels x "+bitsPerPixel+" bpp ]";
+ }
+
+ /**
+ * <p>
+ * Compares {@link DimensionImmutable#compareTo(DimensionImmutable) resolution} 1st, if equal the bitsPerPixel.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final SurfaceSize ssz) {
+ final int rres = resolution.compareTo(ssz.getResolution());
+ if( 0 != rres ) {
+ return rres;
+ }
+ final int xbpp = ssz.getBitsPerPixel();
+ if(bitsPerPixel > xbpp) {
+ return 1;
+ } else if(bitsPerPixel < xbpp) {
+ return -1;
+ }
+ return 0;
+ }
+
+ /**
+ * Checks whether two size objects are equal. Two instances
+ * of <code>SurfaceSize</code> are equal if the two components
+ * <code>resolution</code> and <code>bitsPerPixel</code>
+ * are equal.
+ * @return <code>true</code> if the two dimensions are equal;
+ * otherwise <code>false</code>.
+ */
+ @Override
+ public final boolean equals(final Object obj) {
+ if(this == obj) { return true; }
+ if (obj instanceof SurfaceSize) {
+ final SurfaceSize p = (SurfaceSize)obj;
+ return getResolution().equals(p.getResolution()) &&
+ getBitsPerPixel() == p.getBitsPerPixel();
+ }
+ return false;
+ }
+
+ @Override
+ public final int hashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = getResolution().hashCode();
+ hash = ((hash << 5) - hash) + getBitsPerPixel();
+ return hash;
+ }
+}
+