diff options
author | Sven Gothel <[email protected]> | 2014-02-23 14:51:06 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-02-23 14:51:06 +0100 |
commit | 3352601e0860584509adf2b76f993d03893ded4b (patch) | |
tree | 974fccc8c0eb2f5ad9d4ffd741dfc35869ed67b5 /src/nativewindow/classes/javax | |
parent | f51933f0ebe9ae030c26c066e59a728ce08b8559 (diff) | |
parent | c67de337a8aaf52e36104c3f13e273aa19d21f1f (diff) |
Merge branch 'master' into stash_glyphcache
Conflicts:
make/scripts/tests.sh
src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
src/jogl/classes/com/jogamp/graph/curve/Region.java
src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java
src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java
src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java
src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java
src/jogl/classes/com/jogamp/graph/font/Font.java
src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java
src/jogl/classes/jogamp/graph/curve/text/GlyphString.java
src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java
src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java
src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
Diffstat (limited to 'src/nativewindow/classes/javax')
38 files changed, 2537 insertions, 965 deletions
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java index ebdaf2fbb..48f72e574 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java @@ -1,22 +1,22 @@ /* * 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 @@ -29,11 +29,11 @@ * 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. */ @@ -42,8 +42,9 @@ package javax.media.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 */ diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java index 1dd01a274..31b64269f 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java @@ -1,22 +1,22 @@ /* * 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 @@ -29,22 +29,25 @@ * 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 javax.media.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"; @@ -54,6 +57,8 @@ public interface AbstractGraphicsDevice extends Cloneable { /** 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, .. @@ -84,10 +89,16 @@ public interface AbstractGraphicsDevice extends Cloneable { public int getUnitID(); /** - * Returns a unique ID String of this device using {@link #getType() type}, - * {@link #getConnection() connection} and {@link #getUnitID() unitID}.<br> - * The unique ID does not reflect the instance of the device, hence the handle is not included.<br> + * 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(); @@ -98,27 +109,58 @@ public interface AbstractGraphicsDevice extends Cloneable { public long getHandle(); /** - * Optionally locking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock}. + * Optionally locking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock#lock()}. * The lock implementation must be recursive. */ public void lock(); - /** - * Optionally unlocking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock}. + /** + * Optionally unlocking the device, utilizing eg {@link javax.media.nativewindow.ToolkitLock#unlock()}. * The lock implementation must be recursive. + * + * @throws RuntimeException in case the lock is not acquired by this thread. */ public void unlock(); /** - * Optionally closing the device. + * @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>, just setting the handle to <code>null</code>. + * 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> - * The specific implementing, ie {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}, - * shall have a enable/disable like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice#setCloseDisplay(boolean, boolean)},<br> - * which shall be invoked at creation time to determine ownership/role of freeing the resource.<br> * - * @return true if the handle was not <code>null</code>, otherwise false. + * @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/javax/media/nativewindow/AbstractGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java index eb2cc9120..da8f12f3e 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java @@ -1,21 +1,21 @@ /* * 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 @@ -28,11 +28,11 @@ * 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. */ @@ -44,6 +44,8 @@ package javax.media.nativewindow; */ public interface AbstractGraphicsScreen extends Cloneable { + public Object clone(); + /** * Return the device this graphics configuration is valid for */ diff --git a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java index b422f50e6..9eed887b5 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java +++ b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java @@ -1,22 +1,22 @@ /* * 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 @@ -29,11 +29,11 @@ * 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. */ @@ -44,7 +44,7 @@ package javax.media.nativewindow; 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, Comparable { +public class Capabilities implements CapabilitiesImmutable, Cloneable { protected final static String na_str = "----" ; private int redBits = 8; @@ -62,15 +62,20 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable, Comparabl // 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(); @@ -79,9 +84,32 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable, Comparabl } } + /** + * Copies all {@link Capabilities} values + * from <code>source</code> into this instance. + * @return this instance + */ + public Capabilities copyFrom(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; @@ -90,10 +118,10 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable, Comparabl hash = ((hash << 5) - hash) + this.transparentValueGreen; hash = ((hash << 5) - hash) + this.transparentValueBlue; hash = ((hash << 5) - hash) + this.transparentValueAlpha; - hash = ((hash << 5) - hash) + ( this.onscreen ? 1 : 0 ); return hash; } + @Override public boolean equals(Object obj) { if(this == obj) { return true; } if(!(obj instanceof CapabilitiesImmutable)) { @@ -105,31 +133,33 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable, Comparabl other.getBlueBits()==blueBits && other.getAlphaBits()==alphaBits && other.isBackgroundOpaque()==backgroundOpaque && - other.isOnscreen()==onscreen; - if(!backgroundOpaque) { - res = res && other.getTransparentRedValue()==transparentValueRed && - other.getTransparentGreenValue()==transparentValueGreen && - other.getTransparentBlueValue()==transparentValueBlue && - other.getTransparentAlphaValue()==transparentValueAlpha; + 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 */ - public int compareTo(Object o) { - if ( ! ( o instanceof Capabilities ) ) { + /** + * 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 Capabilities object: " + c); + throw new ClassCastException("Not a CapabilitiesImmutable object, but " + c); } + final CapabilitiesImmutable caps = (CapabilitiesImmutable) o; */ - final Capabilities caps = (Capabilities) o; - - final int a = ( alphaBits > 0 ) ? alphaBits : 1; - final int rgba = redBits * greenBits * blueBits * a; + final int rgba = redBits * greenBits * blueBits * ( alphaBits + 1 ); - final int xa = ( caps.alphaBits ) > 0 ? caps.alphaBits : 1; - final int xrgba = caps.redBits * caps.greenBits * caps.blueBits * xa; + final int xrgba = caps.getRedBits() * caps.getGreenBits() * caps.getBlueBits() * ( caps.getAlphaBits() + 1 ); if(rgba > xrgba) { return 1; @@ -148,13 +178,11 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable, Comparabl return VisualIDHolder.VID_UNDEFINED; default: throw new NativeWindowException("Invalid type <"+type+">"); - } + } } - - /** Returns 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 int getRedBits() { + + @Override + public final int getRedBits() { return redBits; } @@ -165,10 +193,8 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable, Comparabl this.redBits = redBits; } - /** Returns 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 int getGreenBits() { + @Override + public final int getGreenBits() { return greenBits; } @@ -179,10 +205,8 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable, Comparabl this.greenBits = greenBits; } - /** Returns 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 int getBlueBits() { + @Override + public final int getBlueBits() { return blueBits; } @@ -192,99 +216,111 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable, Comparabl public void setBlueBits(int blueBits) { this.blueBits = blueBits; } - - /** Returns 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. */ - public int getAlphaBits() { + + @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. */ + /** + * 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(int alphaBits) { this.alphaBits = alphaBits; } - /** - * Defaults to true, ie. opaque surface. - * <p> - * On supported platforms, setting opaque to false may result in a translucent surface. </p> - * - * <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> - * - * <p> - * The platform implementation may utilize the transparency RGBA values.<br> - * This is true for the original GLX transparency specification, which is no more used today.<br> - * Actually these values are currently not used by any implementation, - * so we may mark them deprecated soon, if this doesn't change.<br> - * </p> - */ + /** + * 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(boolean opaque) { - backgroundOpaque = opaque; - if(!opaque && getAlphaBits()==0) { - setAlphaBits(1); - } + backgroundOpaque = opaque; + if(!opaque && getAlphaBits()==0) { + setAlphaBits(1); + } } - /** Indicates whether the background of this OpenGL context should - be considered opaque. Defaults to true. - - @see #setBackgroundOpaque - */ - public boolean isBackgroundOpaque() { + @Override + public final boolean isBackgroundOpaque() { return backgroundOpaque; } - /** Sets whether the drawable surface supports onscreen. - Defaults to true. - */ + /** + * 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(boolean onscreen) { this.onscreen=onscreen; } - /** Indicates whether the drawable surface is onscreen. - Defaults to true. - */ - public boolean isOnscreen() { + @Override + public final boolean isOnscreen() { return onscreen; } - /** Gets the transparent red value for the frame buffer configuration. - * This value is undefined if {@link #isBackgroundOpaque()} equals true. - * @see #setTransparentRedValue - */ - public int getTransparentRedValue() { return transparentValueRed; } + /** + * 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(boolean enable) { + if(enable) { + setOnscreen(false); + } + isBitmap = enable; + } - /** Gets the transparent green value for the frame buffer configuration. - * This value is undefined if {@link #isBackgroundOpaque()} equals true. - * @see #setTransparentGreenValue - */ - public int getTransparentGreenValue() { return transparentValueGreen; } + @Override + public boolean isBitmap() { + return isBitmap; + } - /** Gets the transparent blue value for the frame buffer configuration. - * This value is undefined if {@link #isBackgroundOpaque()} equals true. - * @see #setTransparentBlueValue - */ - public int getTransparentBlueValue() { return transparentValueBlue; } + @Override + public final int getTransparentRedValue() { return transparentValueRed; } - /** Gets the transparent alpha value for the frame buffer configuration. - * This value is undefined if {@link #isBackgroundOpaque()} equals true. - * @see #setTransparentAlphaValue - */ - public int getTransparentAlphaValue() { return transparentValueAlpha; } + @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. @@ -314,33 +350,65 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable, Comparabl A value of -1 is interpreted as any value. */ public void setTransparentAlphaValue(int transValueAlpha) { transparentValueAlpha=transValueAlpha; } + @Override public StringBuilder toString(StringBuilder sink) { + return toString(sink, true); + } + + /** Returns a textual representation of this Capabilities + object. */ + @Override + public String toString() { + 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"); + sink.append("offscr["); } - sink.append(", rgba 0x").append(toHexString(redBits)).append("/").append(toHexString(greenBits)).append("/").append(toHexString(blueBits)).append("/").append(toHexString(alphaBits)); - if(backgroundOpaque) { - sink.append(", opaque"); + if(isBitmap) { + sink.append("bitmap"); + } else if(onscreen) { + sink.append("."); // no additional off-screen modes besides on-screen } else { - sink.append(", trans-rgba 0x").append(toHexString(transparentValueRed)).append("/").append(toHexString(transparentValueGreen)).append("/").append(toHexString(transparentValueBlue)).append("/").append(toHexString(transparentValueAlpha)); + sink.append("auto-cfg"); // auto-config off-screen mode } + sink.append("]"); + return sink; } - protected final String toHexString(int val) { return Integer.toHexString(val); } - /** Returns a textual representation of this Capabilities - object. */ - public String toString() { - StringBuilder msg = new StringBuilder(); - msg.append("Caps["); - toString(msg); - msg.append("]"); - return msg.toString(); + /** Element separator */ + protected static final String ESEP = "/"; + /** Component separator */ + protected static final String CSEP = ", "; + + protected StringBuilder toString(StringBuilder sink, 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(int val) { return Integer.toHexString(val); } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesChooser.java b/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesChooser.java index a306363dc..1f4db7997 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesChooser.java +++ b/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesChooser.java @@ -1,21 +1,21 @@ /* * 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 @@ -28,11 +28,11 @@ * 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. */ @@ -58,13 +58,13 @@ public interface CapabilitiesChooser { not necessarily required, that the chooser select that entry. <P> <em>Note:</em> this method is called automatically by the - {@link GraphicsConfigurationFactory#chooseGraphicsConfiguration} method + {@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 /*<CapabilitiesImmutable>*/ available, + List<? extends CapabilitiesImmutable> available, int windowSystemRecommendedChoice); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesImmutable.java index 3d7362c40..c496a1535 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesImmutable.java +++ b/src/nativewindow/classes/javax/media/nativewindow/CapabilitiesImmutable.java @@ -33,51 +33,72 @@ 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 javax.media.nativewindow.Capabilities */ -public interface CapabilitiesImmutable extends VisualIDHolder, WriteCloneable { +public interface CapabilitiesImmutable extends VisualIDHolder, WriteCloneable, Comparable<CapabilitiesImmutable> { /** - * Returns the number of bits requested for the color buffer's red + * 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 requested for the color buffer's green + * 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 requested for the color buffer's blue + * 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 requested for the color buffer's alpha + * 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(); /** - * Indicates whether the background of this OpenGL context should be - * considered opaque. Defaults to true. + * Returns whether an opaque or translucent surface is requested, supported or chosen. + * <p> + * Default is true, i.e. opaque. + * </p> */ boolean isBackgroundOpaque(); /** - * Indicates whether the drawable surface is onscreen. Defaults to true. + * 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. */ @@ -109,7 +130,7 @@ public interface CapabilitiesImmutable extends VisualIDHolder, WriteCloneable { @Override int hashCode(); - /** Return a textual representation of this object. Use the given StringBuffer [optional]. */ + /** Return a textual representation of this object. Use the given StringBuilder [optional]. */ StringBuilder toString(StringBuilder sink); /** Returns a textual representation of this object. */ diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultCapabilitiesChooser.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultCapabilitiesChooser.java index 48c4d31ce..77cbe2995 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultCapabilitiesChooser.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultCapabilitiesChooser.java @@ -1,22 +1,22 @@ /* * 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 @@ -29,11 +29,11 @@ * 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. */ @@ -66,10 +66,19 @@ import jogamp.nativewindow.Debug; */ public class DefaultCapabilitiesChooser implements CapabilitiesChooser { - private static final boolean DEBUG = Debug.isPropertyDefined("nativewindow.debug.CapabilitiesChooser", true); + private static final boolean DEBUG; + static { + Debug.initSingleton(); + DEBUG = Debug.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 /*<CapabilitiesImmutable>*/ available, + final List<? extends CapabilitiesImmutable> available, final int windowSystemRecommendedChoice) { if (DEBUG) { System.err.println("Desired: " + desired); @@ -92,17 +101,19 @@ public class DefaultCapabilitiesChooser implements CapabilitiesChooser { // Create score array int[] scores = new int[availnum]; - int NO_SCORE = -9999999; - int COLOR_MISMATCH_PENALTY_SCALE = 36; for (int i = 0; i < availnum; i++) { scores[i] = NO_SCORE; } // Compute score for each for (int i = 0; i < availnum; i++) { - CapabilitiesImmutable cur = (CapabilitiesImmutable) available.get(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 * @@ -122,7 +133,7 @@ public class DefaultCapabilitiesChooser implements CapabilitiesChooser { System.err.println(" ]"); } - // Ready to select. Choose score closest to 0. + // Ready to select. Choose score closest to 0. int scoreClosestToZero = NO_SCORE; int chosenIndex = -1; for (int i = 0; i < availnum; i++) { diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java index a33c3792a..42d7f3a23 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java @@ -1,21 +1,21 @@ /* * 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 @@ -36,12 +36,12 @@ 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(AbstractGraphicsScreen screen, + public DefaultGraphicsConfiguration(AbstractGraphicsScreen screen, CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested) { if(null == screen) { throw new IllegalArgumentException("Null screen"); @@ -69,18 +69,22 @@ public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphics } } + @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; } @@ -89,36 +93,37 @@ public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphics final public int getVisualID(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 of the graphics device in a multi-screen environment.<br> - * + * a change or re-validation of capabilities. + * </p> * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen) */ protected void setChosenCapabilities(CapabilitiesImmutable capsChosen) { - capabilitiesChosen = 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.<br> - * - * A copy of the passed object is being used. + * a change of the graphics device in a multi-screen environment. + * </p> */ - final protected void setScreen(DefaultGraphicsScreen screen) { - this.screen = (AbstractGraphicsScreen) screen.clone(); + protected void setScreen(AbstractGraphicsScreen screen) { + this.screen = screen; } @Override public String toString() { return getClass().getSimpleName()+"[" + screen + ",\n\tchosen " + capabilitiesChosen+ - ",\n\trequested " + capabilitiesRequested+ + ",\n\trequested " + capabilitiesRequested+ "]"; } diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index 187959a67..15ff2b1ac 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -1,22 +1,22 @@ /* * 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 @@ -37,10 +37,10 @@ import jogamp.nativewindow.NativeWindowFactoryImpl; public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice { private static final String separator = "_"; - private String type; - protected String connection; - protected int unitID; - protected String uniqueID; + private final String type; + protected final String connection; + protected final int unitID; + protected final String uniqueID; protected long handle; protected ToolkitLock toolkitLock; @@ -50,34 +50,24 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice * @param type */ public DefaultGraphicsDevice(String type, String connection, int unitID) { - this.type = type; - this.connection = connection; - this.unitID = unitID; - this.uniqueID = getUniqueID(type, connection, unitID); - this.handle = 0; - this.toolkitLock = NativeWindowFactory.getDefaultToolkitLock(type); + this(type, connection, unitID, 0, NativeWindowFactory.getDefaultToolkitLock(type)); } /** * Create an instance with the system default {@link ToolkitLock}. - * gathered via {@link NativeWindowFactory#createDefaultToolkitLock(String, long)}. + * gathered via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}. * @param type * @param handle */ public DefaultGraphicsDevice(String type, String connection, int unitID, long handle) { - this.type = type; - this.connection = connection; - this.unitID = unitID; - this.uniqueID = getUniqueID(type, connection, unitID); - this.handle = handle; - this.toolkitLock = NativeWindowFactory.createDefaultToolkitLock(type, handle); + this(type, connection, unitID, handle, NativeWindowFactory.getDefaultToolkitLock(type, handle)); } /** - * Create an instance with the given {@link ToolkitLock} instance. + * Create an instance with the given {@link ToolkitLock} instance, or <i>null</i> {@link ToolkitLock} if null. * @param type * @param handle - * @param locker + * @param locker if null, a non blocking <i>null</i> lock is used. */ public DefaultGraphicsDevice(String type, String connection, int unitID, long handle, ToolkitLock locker) { this.type = type; @@ -97,49 +87,72 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } } + @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; } /** - * No lock is performed on the graphics device per default, - * instead the aggregated recursive {@link ToolkitLock#lock()} is invoked. + * {@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, javax.media.nativewindow.ToolkitLock) */ + @Override public final void lock() { toolkitLock.lock(); } - /** - * No lock is performed on the graphics device per default, - * instead the aggregated recursive {@link ToolkitLock#unlock()} is invoked. + @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, javax.media.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; @@ -148,8 +161,53 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } @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())+"]"; + 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(long newHandle) { + final long oldHandle = handle; + handle = newHandle; + return oldHandle; + } + + protected Object getHandleOwnership() { + return null; + } + protected Object setHandleOwnership(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(); + } } /** @@ -160,10 +218,11 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice * 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 void setToolkitLock(ToolkitLock locker) { + protected ToolkitLock setToolkitLock(ToolkitLock locker) { final ToolkitLock _toolkitLock = toolkitLock; _toolkitLock.lock(); try { @@ -171,6 +230,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } finally { _toolkitLock.unlock(); } + return _toolkitLock; } /** @@ -183,7 +243,12 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice return toolkitLock; } - protected static String getUniqueID(String type, String connection, int unitID) { - return (type + separator + connection + separator + unitID).intern(); + /** + * 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(String type, String connection, int unitID) { + final String r = (type + separator + connection + separator + unitID).intern(); + return r.intern(); } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java index f50bd0e14..4bd548916 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java @@ -1,21 +1,21 @@ /* * 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 @@ -33,8 +33,8 @@ package javax.media.nativewindow; public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen { - AbstractGraphicsDevice device; - private int idx; + private final AbstractGraphicsDevice device; + private final int idx; public DefaultGraphicsScreen(AbstractGraphicsDevice device, int idx) { this.device = device; @@ -54,10 +54,12 @@ public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen } } + @Override public AbstractGraphicsDevice getDevice() { return device; } + @Override public int getIndex() { return idx; } diff --git a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java index 2610f2cfa..c09e6eaa4 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java @@ -1,22 +1,22 @@ /* * 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 @@ -36,13 +36,19 @@ package javax.media.nativewindow; 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 + * 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 @@ -59,19 +65,57 @@ import java.util.Map; public abstract class GraphicsConfigurationFactory { protected static final boolean DEBUG; - private static Map<Class<?>, GraphicsConfigurationFactory> registeredFactories; - private static Class<?> abstractGraphicsDeviceClass; + private static class DeviceCapsType { + public final Class<?> deviceType; + public final Class<?> capsType; + private final int hash32; + + public DeviceCapsType(Class<?> deviceType, 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(Object obj) { + if(this == obj) { return true; } + if (obj instanceof DeviceCapsType) { + 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(); } - abstractGraphicsDeviceClass = javax.media.nativewindow.AbstractGraphicsDevice.class; + registeredFactories = Collections.synchronizedMap(new HashMap<DeviceCapsType, GraphicsConfigurationFactory>()); + defaultDeviceCapsType = new DeviceCapsType(AbstractGraphicsDevice.class, CapabilitiesImmutable.class); } - + public static synchronized void initSingleton() { if(!initialized) { initialized = true; @@ -79,32 +123,31 @@ public abstract class GraphicsConfigurationFactory { if(DEBUG) { System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.initSingleton()"); } - registeredFactories = Collections.synchronizedMap(new HashMap<Class<?>, GraphicsConfigurationFactory>()); - + // 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(abstractGraphicsDeviceClass, new DefaultGraphicsConfigurationFactoryImpl()); - - if (NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) { + 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()); + ReflectionUtil.callStaticMethod("jogamp.nativewindow.x11.X11GraphicsConfigurationFactory", + "registerFactory", null, null, GraphicsConfigurationFactory.class.getClassLoader()); } catch (Exception e) { throw new RuntimeException(e); } if(NativeWindowFactory.isAWTAvailable()) { try { - ReflectionUtil.callStaticMethod("jogamp.nativewindow.x11.awt.X11AWTGraphicsConfigurationFactory", - "registerFactory", null, null, GraphicsConfigurationFactory.class.getClassLoader()); + ReflectionUtil.callStaticMethod("jogamp.nativewindow.x11.awt.X11AWTGraphicsConfigurationFactory", + "registerFactory", null, null, GraphicsConfigurationFactory.class.getClassLoader()); } catch (Exception e) { /* n/a */ } } } } } - + public static synchronized void shutdown() { if(initialized) { initialized = false; @@ -112,10 +155,9 @@ public abstract class GraphicsConfigurationFactory { System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.shutdown()"); } registeredFactories.clear(); - registeredFactories = null; } } - + protected static String getThreadName() { return Thread.currentThread().getName(); } @@ -133,74 +175,175 @@ public abstract class GraphicsConfigurationFactory { protected GraphicsConfigurationFactory() { } - /** Returns the factory for use with the given type of - AbstractGraphicsDevice. */ - public static GraphicsConfigurationFactory getFactory(AbstractGraphicsDevice device) { + /** + * Returns the graphics configuration factory for use with the + * given device and capability. + * + * @see #getFactory(Class, Class) + */ + public static GraphicsConfigurationFactory getFactory(AbstractGraphicsDevice device, CapabilitiesImmutable caps) { if (device == null) { - return getFactory(AbstractGraphicsDevice.class); + throw new IllegalArgumentException("null device"); + } + if (caps == null) { + throw new IllegalArgumentException("null caps"); } - return getFactory(device.getClass()); + return getFactory(device.getClass(), caps.getClass()); } /** * Returns the graphics configuration factory for use with the - * given class, which must implement the {@link - * AbstractGraphicsDevice} interface. + * given device and capability class. + * <p> + * Note: Registered device types maybe classes or interfaces, where capabilities types are interfaces only. + * </p> * - * @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice + * <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(Class<?> abstractGraphicsDeviceImplementor) + public static GraphicsConfigurationFactory getFactory(Class<?> deviceType, Class<?> capabilitiesType) throws IllegalArgumentException, NativeWindowException { - if (!(abstractGraphicsDeviceClass.isAssignableFrom(abstractGraphicsDeviceImplementor))) { + 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) { + Thread.dumpStack(); + System.err.println("GraphicsConfigurationFactory.getFactory: "+deviceType.getName()+", "+capabilitiesType.getName()); + dumpFactories(); + } - GraphicsConfigurationFactory factory = null; - Class<?> clazz = abstractGraphicsDeviceImplementor; - while (clazz != null) { - factory = registeredFactories.get(clazz); - if (factory != null) { - if(DEBUG) { - System.err.println("GraphicsConfigurationFactory.getFactory() "+abstractGraphicsDeviceImplementor+" -> "+factory); + 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++) { + 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 factory; } - clazz = clazz.getSuperclass(); } // Return the default - factory = registeredFactories.get(abstractGraphicsDeviceClass); + final GraphicsConfigurationFactory factory = registeredFactories.get(defaultDeviceCapsType); if(DEBUG) { - System.err.println("GraphicsConfigurationFactory.getFactory() DEFAULT "+abstractGraphicsDeviceClass+" -> "+factory); + System.err.println("GraphicsConfigurationFactory.getFactory() DEFAULT "+defaultDeviceCapsType+" -> "+factory); } return factory; } + private static ArrayList<Class<?>> getAllAssignableClassesFrom(Class<?> superClassOrInterface, Class<?> fromClass, 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(Class<?> superClassOrInterface, Class<?> fromClass, boolean interfacesOnly, List<Class<?>> resolvedInterfaces, 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() { + Set<DeviceCapsType> dcts = registeredFactories.keySet(); + int i=0; + for(Iterator<DeviceCapsType> iter = dcts.iterator(); iter.hasNext(); ) { + DeviceCapsType dct = iter.next(); + System.err.println("Factory #"+i+": "+dct+" -> "+registeredFactories.get(dct)); + i++; + } + } - /** Registers a GraphicsConfigurationFactory handling graphics - * device objects of the given class. This does not need to be - * called by end users, only implementors of new + /** + * 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(Class<?> abstractGraphicsDeviceImplementor, GraphicsConfigurationFactory factory) + protected static GraphicsConfigurationFactory registerFactory(Class<?> abstractGraphicsDeviceImplementor, Class<?> capabilitiesType, GraphicsConfigurationFactory factory) throws IllegalArgumentException { - if (!(abstractGraphicsDeviceClass.isAssignableFrom(abstractGraphicsDeviceImplementor))) { - throw new IllegalArgumentException("Given class must implement AbstractGraphicsDevice"); + 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(abstractGraphicsDeviceImplementor); + prevFactory = registeredFactories.remove(dct); if(DEBUG) { - System.err.println("GraphicsConfigurationFactory.registerFactory() remove "+abstractGraphicsDeviceImplementor+ + System.err.println("GraphicsConfigurationFactory.registerFactory() remove "+dct+ ", deleting: "+prevFactory); } } else { - prevFactory = registeredFactories.put(abstractGraphicsDeviceImplementor, factory); + prevFactory = registeredFactories.put(dct, factory); if(DEBUG) { - System.err.println("GraphicsConfigurationFactory.registerFactory() put "+abstractGraphicsDeviceImplementor+" -> "+factory+ + System.err.println("GraphicsConfigurationFactory.registerFactory() put "+dct+" -> "+factory+ ", overridding: "+prevFactory); } } @@ -211,7 +354,7 @@ public abstract class GraphicsConfigurationFactory { * <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. + * 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> @@ -219,7 +362,7 @@ public abstract class GraphicsConfigurationFactory { * <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 + * In this case, the AbstractGraphicsConfiguration implementation * must allow an overwrite of the Capabilites, for example * {@link DefaultGraphicsConfiguration#setChosenCapabilities DefaultGraphicsConfiguration.setChosenCapabilities(..)}. * </P> @@ -244,6 +387,7 @@ public abstract class GraphicsConfigurationFactory { * @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 @@ -258,7 +402,7 @@ public abstract class GraphicsConfigurationFactory { public final AbstractGraphicsConfiguration chooseGraphicsConfiguration(CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, - AbstractGraphicsScreen screen) + AbstractGraphicsScreen screen, int nativeVisualID) throws IllegalArgumentException, NativeWindowException { if(null==capsChosen) { throw new NativeWindowException("Chosen Capabilities are null"); @@ -275,7 +419,7 @@ public abstract class GraphicsConfigurationFactory { } device.lock(); try { - return chooseGraphicsConfigurationImpl(capsChosen, capsRequested, chooser, screen); + return chooseGraphicsConfigurationImpl(capsChosen, capsRequested, chooser, screen, nativeVisualID); } finally { device.unlock(); } @@ -283,7 +427,7 @@ public abstract class GraphicsConfigurationFactory { protected abstract AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AbstractGraphicsScreen screen) + CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID) throws IllegalArgumentException, NativeWindowException; } diff --git a/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java new file mode 100644 index 000000000..a0db11ad9 --- /dev/null +++ b/src/nativewindow/classes/javax/media/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 javax.media.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/javax/media/nativewindow/NativeSurface.java b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java index b7829cb6d..a755b1812 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java @@ -3,14 +3,14 @@ * * 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 @@ -20,12 +20,12 @@ * 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 javax.media.nativewindow; /** Provides low-level information required for @@ -54,10 +54,10 @@ public interface NativeSurface extends SurfaceUpdatedListener { * <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 = lockSurface() > LOCK_SURFACE_NOT_READY; - * </pre> + * 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}, @@ -71,7 +71,7 @@ public interface NativeSurface extends SurfaceUpdatedListener { * This call allows recursion from the same thread. * </p> * <p> - * The implementation may want to aquire the + * 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> @@ -83,10 +83,11 @@ public interface NativeSurface extends SurfaceUpdatedListener { * @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(); + public int lockSurface() throws NativeWindowException, RuntimeException; /** * Unlock the surface of this native window @@ -96,36 +97,41 @@ public interface NativeSurface extends SurfaceUpdatedListener { * The implementation shall also invoke {@link AbstractGraphicsDevice#unlock()} * for the final unlock (recursive count zero).<P> * - * @throws RuntimeException if surface is not locked + * 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() throws NativeWindowException ; + public void unlockSurface(); /** - * Return if surface is locked by another thread, ie not the current one + * 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 if surface is locked - */ - public boolean isSurfaceLocked(); - - /** * 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. The implementation may itself apply the swapping, + * 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 + * otherwise false, in which case eg the GLDrawable * implementation has to swap the code. */ public boolean surfaceSwap(); @@ -147,13 +153,13 @@ public interface NativeSurface extends SurfaceUpdatedListener { /** 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 + * After {@link #unlockSurface()} it is no more guaranteed * that the surface handle is still valid. * * The surface handle shall reflect the platform one @@ -189,16 +195,16 @@ public interface NativeSurface extends SurfaceUpdatedListener { public AbstractGraphicsConfiguration getGraphicsConfiguration(); /** - * Convenience: Get display handle from + * Convenience: Get display handle from * AbstractGraphicsConfiguration . AbstractGraphicsScreen . AbstractGraphicsDevice */ public long getDisplayHandle(); /** - * Convenience: Get display handle from + * Convenience: Get display handle from * AbstractGraphicsConfiguration . AbstractGraphicsScreen */ public int getScreenIndex(); - + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java index 2bc352116..a740ebbe0 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindow.java @@ -1,22 +1,22 @@ /* * 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 @@ -29,11 +29,11 @@ * 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. */ @@ -52,10 +52,9 @@ import javax.media.nativewindow.util.Point; which can create NativeWindow objects for its components. <P> */ public interface NativeWindow extends NativeSurface { - - /** - * destroys the window and releases - * windowing related resources. + + /** + * Destroys this window incl. releasing all related resources. */ public void destroy(); @@ -67,63 +66,63 @@ public interface NativeWindow extends NativeSurface { /** * Returns the window handle for this NativeWindow. <P> * - * The window handle shall reflect the platform one + * 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. + * 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.<br> * Insets are zero if the window is undecorated, including child windows. - * + * * <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> * getX() - getInsets().{@link InsetsImmutable#getLeftWidth() getLeftWidth()} * getY() - getInsets().{@link InsetsImmutable#getTopHeight() getTopHeight()} - * </pre> - * + * </pre> + * * The top-level window size is * <pre> - * getWidth() + getInsets().{@link InsetsImmutable#getTotalWidth() getTotalWidth()} + * getWidth() + getInsets().{@link InsetsImmutable#getTotalWidth() getTotalWidth()} * getHeight() + getInsets().{@link InsetsImmutable#getTotalHeight() getTotalHeight()} - * </pre> - * + * </pre> + * * @return insets */ public InsetsImmutable getInsets(); - + /** Returns the current x position of this window, relative to it's parent. */ - - /** + + /** * @return the current x position of the top-left corner - * of the client area relative to it's parent. + * of the client area relative to it's parent. * Since the position reflects the client area, it does not include the insets. * @see #getInsets() */ public int getX(); - /** + /** * @return the current y position of the top-left corner - * of the client area relative to it's parent. + * of the client area relative to it's parent. * Since the position reflects the client area, it does not include the insets. * @see #getInsets() */ public int getY(); - /** - * Returns the current position of the top-left corner + /** + * Returns the current position of the top-left corner * of the client area in screen coordinates. * <p> * Since the position reflects the client area, it does not include the insets. - * </p> + * </p> * @param point if not null, * {@link javax.media.nativewindow.util.Point#translate(javax.media.nativewindow.util.Point)} * the passed {@link javax.media.nativewindow.util.Point} by this location on the screen and return it. @@ -131,8 +130,8 @@ public interface NativeWindow extends NativeSurface { * or a new instance with the screen location of this NativeWindow. */ public Point getLocationOnScreen(Point point); - + /** Returns true if this native window owns the focus, otherwise false. */ boolean hasFocus(); - + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowException.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowException.java index 593c1e7d6..0943c8c09 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowException.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowException.java @@ -1,21 +1,21 @@ /* * 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 @@ -28,11 +28,11 @@ * 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. */ diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index b85ad47f2..034bf2456 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -1,22 +1,22 @@ /* * 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 @@ -33,19 +33,36 @@ package javax.media.nativewindow; -import java.lang.reflect.Constructor; +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 javax.media.nativewindow.util.PointImmutable; + 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.ReflectionUtil; +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSizePos; +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, @@ -56,57 +73,75 @@ import com.jogamp.common.util.ReflectionUtil; public abstract class NativeWindowFactory { protected static final boolean DEBUG; - /** OpenKODE/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}*/ - public static final String TYPE_EGL = "EGL"; + /** 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(); - /** Microsoft Windows type, as retrieved with {@link #getNativeWindowType(boolean)} */ - public static final String TYPE_WINDOWS = "Windows"; + /** 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(); - /** X11 type, as retrieved with {@link #getNativeWindowType(boolean)} */ - public static final String TYPE_X11 = "X11"; + /** Android/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}.*/ + public static final String TYPE_ANDROID = ".android".intern(); - /** Android/EGL type, as retrieved with {@link #getNativeWindowType(boolean)}*/ - public static final String TYPE_ANDROID = "ANDROID"; + /** 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(); - /** Mac OS X type, as retrieved with {@link #getNativeWindowType(boolean)} */ - public static final String TYPE_MACOSX = "MacOSX"; + /** 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 AWT type, as retrieved with {@link #getNativeWindowType(boolean)} */ - public static final String TYPE_AWT = "AWT"; + /** 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(); - /** Generic DEFAULT type, where platform implementation don't care, as retrieved with {@link #getNativeWindowType(boolean)} */ - public static final String TYPE_DEFAULT = "default"; + 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 String nativeWindowingTypePure; - private static String nativeWindowingTypeCustom; 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; - - public static final String X11JAWTToolkitLockClassName = "jogamp.nativewindow.jawt.x11.X11JAWTToolkitLock" ; - public static final String X11ToolkitLockClassName = "jogamp.nativewindow.x11.X11ToolkitLock" ; - - private static Class<?> x11JAWTToolkitLockClass; - private static Constructor<?> x11JAWTToolkitLockConstructor; - private static Class<?> x11ToolkitLockClass; - private static Constructor<?> x11ToolkitLockConstructor; - private static boolean isFirstUIActionOnProcess; + 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(Platform.OS_TYPE) { case ANDROID: @@ -114,99 +149,188 @@ public abstract class NativeWindowFactory { case MACOS: return TYPE_MACOSX; case WINDOWS: - return TYPE_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 { - Platform.initSingleton(); - DEBUG = Debug.debug("NativeWindow"); + 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] = Debug.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 + } } - static boolean initialized = false; + private static boolean initialized = false; - private static void initSingletonNativeImpl(final boolean firstUIActionOnProcess, final ClassLoader cl) { - isFirstUIActionOnProcess = firstUIActionOnProcess; - + private static void initSingletonNativeImpl(final ClassLoader cl) { final String clazzName; - if( TYPE_X11.equals(nativeWindowingTypePure) ) { + if( TYPE_X11 == nativeWindowingTypePure ) { clazzName = X11UtilClassName; - } else if( TYPE_WINDOWS.equals(nativeWindowingTypePure) ) { + } else if( TYPE_WINDOWS == nativeWindowingTypePure ) { clazzName = GDIClassName; - } else if( TYPE_MACOSX.equals(nativeWindowingTypePure) ) { + } else if( TYPE_MACOSX == nativeWindowingTypePure ) { clazzName = OSXUtilClassName; } else { clazzName = null; } if( null != clazzName ) { - ReflectionUtil.callStaticMethod(clazzName, "initSingleton", - new Class[] { boolean.class }, - new Object[] { new Boolean(firstUIActionOnProcess) }, cl ); - - final Boolean res = (Boolean) ReflectionUtil.callStaticMethod(clazzName, "requiresToolkitLock", null, null, cl); - requiresToolkitLock = res.booleanValue(); - } else { + 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(boolean head, 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(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(Throwable t) { + System.err.println("NativeWindowFactory.shutdown: Catched "+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! - * <p> - * The parameter <code>firstUIActionOnProcess</code> has an impact on concurrent locking: - * <ul> - * <li> {@link #getDefaultToolkitLock() getDefaultToolkitLock() }</li> - * <li> {@link #getDefaultToolkitLock(java.lang.String) getDefaultToolkitLock(type) }</li> - * <li> {@link #createDefaultToolkitLock(java.lang.String, long) createDefaultToolkitLock(type, dpyHandle) }</li> - * <li> {@link #createDefaultToolkitLockNoAWT(java.lang.String, long) createDefaultToolkitLockNoAWT(type, dpyHandle) }</li> - * </ul> - * </p> - * @param firstUIActionOnProcess Should be <code>true</code> if called before the first UI action of the running program, - * otherwise <code>false</code>. */ - public static synchronized void initSingleton(final boolean firstUIActionOnProcess) { + public static synchronized void initSingleton() { if(!initialized) { initialized = true; if(DEBUG) { - System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.initSingleton("+firstUIActionOnProcess+")"); + System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.initSingleton()"); } final ClassLoader cl = NativeWindowFactory.class.getClassLoader(); - // Gather the windowing OS first - nativeWindowingTypePure = _getNativeWindowingType(); - String tmp = Debug.getProperty("nativewindow.ws.name", true); - if(null==tmp || tmp.length()==0) { - nativeWindowingTypeCustom = nativeWindowingTypePure; - } else { - nativeWindowingTypeCustom = tmp; - } - - if(firstUIActionOnProcess) { - // X11 initialization before possible AWT initialization - initSingletonNativeImpl(true, cl); - } isAWTAvailable = false; // may be set to true below if( Platform.AWT_AVAILABLE && ReflectionUtil.isClassAvailable("com.jogamp.nativewindow.awt.AWTGraphicsDevice", cl) ) { - + Method[] jawtUtilMethods = AccessController.doPrivileged(new PrivilegedAction<Method[]>() { + @Override public Method[] run() { try { Class<?> _jawtUtilClass = Class.forName(JAWTUtilClassName, true, NativeWindowFactory.class.getClassLoader()); @@ -216,7 +340,7 @@ public abstract class NativeWindowFactory { jawtUtilInitMethod.setAccessible(true); Method jawtUtilGetJAWTToolkitLockMethod = _jawtUtilClass.getDeclaredMethod("getJAWTToolkitLock", new Class[]{}); jawtUtilGetJAWTToolkitLockMethod.setAccessible(true); - return new Method[] { jawtUtilInitMethod, jawtUtilIsHeadlessMethod, jawtUtilGetJAWTToolkitLockMethod }; + return new Method[] { jawtUtilInitMethod, jawtUtilIsHeadlessMethod, jawtUtilGetJAWTToolkitLockMethod }; } catch (Exception e) { if(DEBUG) { e.printStackTrace(); @@ -229,7 +353,7 @@ public abstract class NativeWindowFactory { 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); @@ -240,18 +364,21 @@ public abstract class NativeWindowFactory { } else { throw new RuntimeException("JAWTUtil.isHeadlessMode() didn't return a Boolean"); } - resO = ReflectionUtil.callMethod(null, jawtUtilGetJAWTToolkitLockMethod); + resO = ReflectionUtil.callMethod(null, jawtUtilGetJAWTToolkitLockMethod); if(resO instanceof ToolkitLock) { jawtUtilJAWTToolkitLock = (ToolkitLock) resO; } else { throw new RuntimeException("JAWTUtil.getJAWTToolkitLock() didn't return a ToolkitLock"); - } + } } } - if(!firstUIActionOnProcess) { - // X11 initialization after possible AWT initialization - initSingletonNativeImpl(false, cl); - } + + // 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 @@ -259,79 +386,47 @@ public abstract class NativeWindowFactory { nativeWindowClass = javax.media.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( TYPE_X11 == nativeWindowingTypePure ) { - // passing through RuntimeException if not exists intended - x11ToolkitLockClass = ReflectionUtil.getClass(X11ToolkitLockClassName, false, cl); - x11ToolkitLockConstructor = ReflectionUtil.getConstructor(x11ToolkitLockClass, new Class[] { long.class } ); - if( isAWTAvailable() ) { - x11JAWTToolkitLockClass = ReflectionUtil.getClass(X11JAWTToolkitLockClassName, false, cl); - x11JAWTToolkitLockConstructor = ReflectionUtil.getConstructor(x11JAWTToolkitLockClass, new Class[] { long.class } ); - } - } - if(DEBUG) { - System.err.println("NativeWindowFactory firstUIActionOnProcess "+firstUIActionOnProcess); - System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock); + System.err.println("NativeWindowFactory requiresToolkitLock "+requiresToolkitLock+", desktopHasThreadingIssues "+desktopHasThreadingIssues); System.err.println("NativeWindowFactory isAWTAvailable "+isAWTAvailable+", defaultFactory "+factory); } - - GraphicsConfigurationFactory.initSingleton(); - } - } - public static synchronized void shutdown() { - if(initialized) { - initialized = false; - if(DEBUG) { - System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() START"); - } - registeredFactories.clear(); - registeredFactories = null; - GraphicsConfigurationFactory.shutdown(); - // X11Util.shutdown(..) already called via GLDrawableFactory.shutdown() .. - if(DEBUG) { - System.err.println(Thread.currentThread().getName()+" - NativeWindowFactory.shutdown() END"); - } + GraphicsConfigurationFactory.initSingleton(); } } - - /** @return true if initialized with <b>{@link #initSingleton(boolean) initSingleton(firstUIActionOnProcess==true)}</b>, - otherwise false. */ - public static boolean isFirstUIActionOnProcess() { - return isFirstUIActionOnProcess; - } /** @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 a define native window type, like {@link #TYPE_X11}, .. + * @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(boolean useCustom) { return useCustom?nativeWindowingTypeCustom:nativeWindowingTypePure; } - /** Don't know if we shall add this factory here .. + /** 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.equals(TYPE_EGL)) { + if(TYPE_EGL == type) { return new - } else if(type.equals(TYPE_X11)) { - } else if(type.equals(TYPE_WINDOWS)) { - } else if(type.equals(TYPE_MACOSX)) { - } else if(type.equals(TYPE_AWT)) { - } else if(type.equals(TYPE_DEFAULT)) { + } 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) { } } */ @@ -346,126 +441,89 @@ public abstract class NativeWindowFactory { } /** - * Provides the system default {@link ToolkitLock}, a singleton instance. - * <br> + * 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(getNativeWindowType(false)); + return getDefaultToolkitLock(nativeWindowingTypePure); } /** - * Provides the default {@link ToolkitLock} for <code>type</code>, a singleton instance. - * <br> + * Provides the default {@link ToolkitLock} for <code>type</code>. * <ul> - * <li> If {@link #initSingleton(boolean) initSingleton( <b>firstUIActionOnProcess := false</b> )} </li> - * <ul> - * <li>If <b>AWT-type</b> and <b>native-X11-type</b> and <b>AWT-available</b></li> - * <ul> - * <li> return {@link #getAWTToolkitLock()} </li> - * </ul> - * </ul> - * <li> Otherwise return {@link #getNullToolkitLock()} </li> + * <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(String type) { - if( requiresToolkitLock() ) { - if( TYPE_AWT == type && TYPE_X11 == getNativeWindowType(false) && isAWTAvailable() ) { + if( requiresToolkitLock ) { + if( TYPE_AWT == type && isAWTAvailable() ) { return getAWTToolkitLock(); } + return ResourceToolkitLock.create(); } return NativeWindowFactoryImpl.getNullToolkitLock(); } - /** Returns the AWT Toolkit (JAWT based) if {@link #isAWTAvailable}, otherwise null. */ - public static ToolkitLock getAWTToolkitLock() { - return jawtUtilJAWTToolkitLock; - } - - public static ToolkitLock getNullToolkitLock() { - return NativeWindowFactoryImpl.getNullToolkitLock(); - } - /** - * Creates the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>. - * <br> + * Provides the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>. * <ul> - * <li> If {@link #initSingleton(boolean) initSingleton( <b>firstUIActionOnProcess := false</b> )} </li> - * <ul> - * <li>If <b>X11 type</b> </li> - * <ul> - * <li> return {@link jogamp.nativewindow.x11.X11ToolkitLock} </li> - * </ul> - * </ul> - * <li> Otherwise return {@link jogamp.nativewindow.NullToolkitLock} </li> + * <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 createDefaultToolkitLock(String type, long deviceHandle) { - if( requiresToolkitLock() ) { - if( TYPE_X11 == type ) { - if( 0== deviceHandle ) { - throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11"); - } - return createX11ToolkitLock(deviceHandle); + public static ToolkitLock getDefaultToolkitLock(String type, long deviceHandle) { + if( requiresToolkitLock ) { + if( TYPE_AWT == type && isAWTAvailable() ) { + return getAWTToolkitLock(); } + return ResourceToolkitLock.create(); } return NativeWindowFactoryImpl.getNullToolkitLock(); } - + /** - * Creates the default {@link ToolkitLock} for <code>type</code> and <code>deviceHandle</code>. - * <br> - * <ul> - * <li> If {@link #initSingleton(boolean) initSingleton( <b>firstUIActionOnProcess := false</b> )} </li> - * <ul> - * <li>If <b>X11 type</b> </li> - * <ul> - * <li> If <b>shared-AWT-type</b> and <b>AWT available</b> </li> - * <ul> - * <li> return {@link jogamp.nativewindow.jawt.x11.X11JAWTToolkitLock} </li> - * </ul> - * <li> else return {@link jogamp.nativewindow.x11.X11ToolkitLock} </li> - * </ul> - * </ul> - * <li> Otherwise return {@link jogamp.nativewindow.NullToolkitLock} </li> - * </ul> + * @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 ToolkitLock createDefaultToolkitLock(String type, String sharedType, long deviceHandle) { - if( requiresToolkitLock() ) { - if( TYPE_X11 == type ) { - if( 0== deviceHandle ) { - throw new RuntimeException("JAWTUtil.createDefaultToolkitLock() called with NULL device but on X11"); - } - if( TYPE_AWT == sharedType && isAWTAvailable() ) { - return createX11AWTToolkitLock(deviceHandle); - } - return createX11ToolkitLock(deviceHandle); + public static AbstractGraphicsScreen createScreen(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); } - return NativeWindowFactoryImpl.getNullToolkitLock(); - } - - protected static ToolkitLock createX11AWTToolkitLock(long deviceHandle) { - try { - if(DEBUG) { - System.err.println("NativeWindowFactory.createX11AWTToolkitLock(0x"+Long.toHexString(deviceHandle)+")"); - // Thread.dumpStack(); - } - return (ToolkitLock) x11JAWTToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)}); - } catch (Exception ex) { - throw new RuntimeException(ex); + if(0 > screen) { + screen = 0; // FIXME: Needs native API utilization } - } - - protected static ToolkitLock createX11ToolkitLock(long deviceHandle) { - try { - return (ToolkitLock) x11ToolkitLockConstructor.newInstance(new Object[]{new Long(deviceHandle)}); - } catch (Exception ex) { - throw new RuntimeException(ex); + 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 @@ -498,7 +556,7 @@ public abstract class NativeWindowFactory { } /** Converts the given window object and it's - {@link AbstractGraphicsConfiguration AbstractGraphicsConfiguration} into a + {@link AbstractGraphicsConfiguration AbstractGraphicsConfiguration} into a {@link NativeWindow NativeWindow} which can be operated upon by a custom toolkit, e.g. {@link javax.media.opengl.GLDrawableFactory javax.media.opengl.GLDrawableFactory}.<br> The object may be a component for a particular window toolkit, such as an AWT @@ -509,7 +567,7 @@ public abstract class NativeWindowFactory { 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 @@ -528,22 +586,22 @@ public abstract class NativeWindowFactory { 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 + * 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>. + * 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()}. + * @param ifEnabled If true, only return the enabled {@link OffscreenLayerSurface}, see {@link OffscreenLayerOption#isOffscreenLayerSurfaceEnabled()}. * @return */ public static OffscreenLayerSurface getOffscreenLayerSurface(NativeSurface surface, boolean ifEnabled) { - if(surface instanceof OffscreenLayerSurface && + if(surface instanceof OffscreenLayerSurface && ( !ifEnabled || surface instanceof OffscreenLayerOption ) ) { final OffscreenLayerSurface ols = (OffscreenLayerSurface) surface; return ( !ifEnabled || ((OffscreenLayerOption)ols).isOffscreenLayerSurfaceEnabled() ) ? ols : null; @@ -556,9 +614,97 @@ public abstract class NativeWindowFactory { final OffscreenLayerSurface ols = (OffscreenLayerSurface) nw; return ( !ifEnabled || ((OffscreenLayerOption)ols).isOffscreenLayerSurfaceEnabled() ) ? ols : null; } - nw = nw.getParent(); + nw = nw.getParent(); } } - return null; + 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(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(String displayConnection, 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 UpstreamSurfaceHookMutableSizePos} 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(AbstractGraphicsScreen aScreen, long surfaceHandle, long windowHandle, + UpstreamSurfaceHookMutableSizePos hook) { + final CapabilitiesImmutable caps = new Capabilities(); + final AbstractGraphicsConfiguration config = new DefaultGraphicsConfiguration(aScreen, caps, caps); + return new WrappedWindow(config, surfaceHandle, hook, true, windowHandle); + } + + public static PointImmutable getLocationOnScreen(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(), null == nw.getParent(), 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/javax/media/nativewindow/OffscreenLayerOption.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerOption.java index 12d30b3cd..11496899a 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerOption.java +++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerOption.java @@ -32,30 +32,30 @@ package javax.media.nativewindow; * 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() + * @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) + * + * @see #setShallUseOffscreenLayer(boolean) */ public boolean isOffscreenLayerSurfaceEnabled(); }
\ No newline at end of file diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java index dd36509ba..cf8cf89d2 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java @@ -27,22 +27,60 @@ */ package javax.media.nativewindow; +import javax.media.nativewindow.util.PixelRectangle; +import javax.media.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 void detachSurfaceLayer(final long layerHandle) throws NativeWindowException; + public boolean hideCursor(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java index 6a36bb130..0af2bdaf9 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * 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: @@ -28,154 +28,100 @@ package javax.media.nativewindow; - import jogamp.nativewindow.Debug; -import jogamp.nativewindow.SurfaceUpdatedHelper; - -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; -public abstract class ProxySurface implements NativeSurface { +/** + * 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"); - - private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); - private AbstractGraphicsConfiguration config; // control access due to delegation - protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); - private long surfaceHandle_old; - protected long displayHandle; - protected int height; - protected int scrnIndex; - protected int width; - - public ProxySurface(AbstractGraphicsConfiguration cfg) { - invalidate(); - config = cfg; - displayHandle=cfg.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - surfaceHandle_old = 0; - } - - void invalidate() { - displayHandle = 0; - invalidateImpl(); - } - protected abstract void invalidateImpl(); - - public final long getDisplayHandle() { - return displayHandle; - } - - protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() { - return config; - } - - public final AbstractGraphicsConfiguration getGraphicsConfiguration() { - return config.getNativeGraphicsConfiguration(); - } - - public final int getScreenIndex() { - return getGraphicsConfiguration().getScreen().getIndex(); - } - - public abstract long getSurfaceHandle(); - - public final int getWidth() { - return width; - } - - public final int getHeight() { - return height; - } - - public void surfaceSizeChanged(int width, int height) { - this.width = width; - this.height = height; - } - - public boolean surfaceSwap() { - return false; - } - - public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { - surfaceUpdatedHelper.addSurfaceUpdatedListener(l); - } - - public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { - surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l); - } - - public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { - surfaceUpdatedHelper.removeSurfaceUpdatedListener(l); - } - - public void surfaceUpdated(Object updater, NativeSurface ns, long when) { - surfaceUpdatedHelper.surfaceUpdated(updater, ns, when); - } - - public int lockSurface() throws NativeWindowException { - surfaceLock.lock(); - int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ? - - if ( LOCK_SURFACE_NOT_READY == res ) { - try { - final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); - adevice.lock(); - try { - res = lockSurfaceImpl(); - if(LOCK_SUCCESS == res && surfaceHandle_old != getSurfaceHandle()) { - res = LOCK_SURFACE_CHANGED; - if(DEBUG) { - System.err.println("ProxySurface: surface change 0x"+Long.toHexString(surfaceHandle_old)+" -> 0x"+Long.toHexString(getSurfaceHandle())); - // Thread.dumpStack(); - } - } - } finally { - if (LOCK_SURFACE_NOT_READY >= res) { - adevice.unlock(); - } - } - } finally { - if (LOCK_SURFACE_NOT_READY >= res) { - surfaceLock.unlock(); - } - } - } - return res; - } - - public final void unlockSurface() { - surfaceLock.validateLocked(); - surfaceHandle_old = getSurfaceHandle(); - - if (surfaceLock.getHoldCount() == 1) { - final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); - try { - unlockSurfaceImpl(); - } finally { - adevice.unlock(); - } - } - surfaceLock.unlock(); - } - - protected abstract int lockSurfaceImpl(); - - protected abstract void unlockSurfaceImpl() ; - - public final void validateSurfaceLocked() { - surfaceLock.validateLocked(); - } - - public final boolean isSurfaceLocked() { - return surfaceLock.isLocked(); - } - - public final boolean isSurfaceLockedByOtherThread() { - return surfaceLock.isLockedByOtherThread(); - } - - public final Thread getSurfaceLockOwner() { - return surfaceLock.getOwner(); - } - - public abstract String toString(); + + /** + * 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; + + /** Allow redefining the AbstractGraphicsConfiguration */ + public void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg); + + /** + * Return the upstream {@link NativeSurface} if used, otherwise <code>null</code>. + * <p> + * An upstream {@link NativeSurface} may backup this {@link ProxySurface} instance's representation, + * e.g. via a {@link #setUpstreamSurfaceHook(UpstreamSurfaceHook) set} {@link UpstreamSurfaceHook}. + * </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(); + + /** + * Sets the {@link UpstreamSurfaceHook} and returns the previous value. + */ + 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/javax/media/nativewindow/SurfaceChangeable.java b/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java deleted file mode 100644 index 956e68e61..000000000 --- a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 javax.media.nativewindow; - -public interface SurfaceChangeable { - - /** Sets the surface handle which is created outside of this implementation */ - public void setSurfaceHandle(long surfaceHandle); - - /** - * The surface's size has been determined or changed. - * Implementation shall update the stored surface size with the given ones. - */ - public void surfaceSizeChanged(int width, int height); - -} - diff --git a/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java b/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java index 0912b5afe..de65a3031 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java +++ b/src/nativewindow/classes/javax/media/nativewindow/SurfaceUpdatedListener.java @@ -1,22 +1,22 @@ /* * 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 @@ -29,7 +29,7 @@ * 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 javax.media.nativewindow; diff --git a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java index 30f9660f0..017b996d7 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ToolkitLock.java @@ -33,12 +33,46 @@ import jogamp.nativewindow.Debug; /** * Marker for a singleton global recursive blocking lock implementation, * optionally locking a native windowing toolkit as well. - * <br> - * One use case is the AWT locking on X11, see {@link jogamp.nativewindow.jawt.JAWTToolkitLock}. + * <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/javax/media/nativewindow/UpstreamSurfaceHook.java b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java new file mode 100644 index 000000000..f08a6c938 --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java @@ -0,0 +1,52 @@ +/** + * 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 javax.media.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 width of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */ + public int getWidth(ProxySurface s); + /** Returns the height of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */ + public int getHeight(ProxySurface s); + + /** + * {@link UpstreamSurfaceHook} w/ mutable size, allowing it's {@link ProxySurface} user to resize. + */ + public interface MutableSize extends UpstreamSurfaceHook { + public void setSize(int width, int height); + } +} diff --git a/src/nativewindow/classes/javax/media/nativewindow/VisualIDHolder.java b/src/nativewindow/classes/javax/media/nativewindow/VisualIDHolder.java index 4f3d3ff00..4ed79b1dc 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/VisualIDHolder.java +++ b/src/nativewindow/classes/javax/media/nativewindow/VisualIDHolder.java @@ -38,7 +38,7 @@ import java.util.Comparator; * </p> */ public interface VisualIDHolder { - + public enum VIDType { // Generic Values INTRINSIC(0), NATIVE(1), @@ -47,19 +47,19 @@ public interface VisualIDHolder { // X11 Values X11_XVISUAL(20), X11_FBCONFIG(21), // Windows Values - WIN32_PFD(30); - + WIN32_PFD(30); + public final int id; VIDType(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> + * <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> @@ -76,7 +76,7 @@ public interface VisualIDHolder { * <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> + * <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> @@ -91,35 +91,36 @@ public interface VisualIDHolder { * </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 + * 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. + * 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> + * </p> */ static final int VID_UNDEFINED = 0; - + /** Comparing {@link VIDType#NATIVE} */ public static class VIDComparator implements Comparator<VisualIDHolder> { private VIDType type; - + public VIDComparator(VIDType type) { this.type = type; } - + + @Override public int compare(VisualIDHolder vid1, VisualIDHolder vid2) { final int id1 = vid1.getVisualID(type); final int id2 = vid2.getVisualID(type); @@ -131,5 +132,5 @@ public interface VisualIDHolder { } return 0; } - } + } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java index 884c916e4..8570b78da 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java +++ b/src/nativewindow/classes/javax/media/nativewindow/WindowClosingProtocol.java @@ -37,13 +37,17 @@ package javax.media.nativewindow; * 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. diff --git a/src/nativewindow/classes/javax/media/nativewindow/package.html b/src/nativewindow/classes/javax/media/nativewindow/package.html index 14730a548..3fe42bab0 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/package.html +++ b/src/nativewindow/classes/javax/media/nativewindow/package.html @@ -1,7 +1,7 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> - <title>NativeWindow Protocol Draft Public Review Specification</title> + <title>NativeWindow Specification Overview</title> </head> <body> @@ -10,7 +10,7 @@ <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:<br><br> + Currently specified <i>native windowing systems</i> are: <ul> <li> EGL/OpenKODE Windowing System</li> <li> X11 Windowing System</li> @@ -20,95 +20,79 @@ </ul> <br> However, any other native windowing system may be added to the implementation, - using a generic string identifier and an optional specialisation of:<br><br> + using a generic string identifier and an optional specialisation of: <ul> - <li>{@link javax.media.nativewindow.AbstractGraphicsDevice AbstractGraphicsDevice},<br> - <br> - Shall return the new string identifier with {@link javax.media.nativewindow.AbstractGraphicsDevice#getType() getType()}</li> + <li>{@link javax.media.nativewindow.AbstractGraphicsDevice AbstractGraphicsDevice}, + <p>Shall return the new string identifier with {@link javax.media.nativewindow.AbstractGraphicsDevice#getType() getType()}</p></li> <li>{@link javax.media.nativewindow.AbstractGraphicsScreen AbstractGraphicsScreen}</li> <li>{@link javax.media.nativewindow.AbstractGraphicsConfiguration AbstractGraphicsConfiguration}</li> </ul> - <br> - The implementor has to provide the following:<br><br> + <p>The implementor has to provide the following:</p> <ul> - <li> The specialisation of the abstract class {@link javax.media.nativewindow.NativeWindowFactory NativeWindowFactory}<br> - <br> - shall be registered with {@link javax.media.nativewindow.NativeWindowFactory#registerFactory NativeWindowFactory.registerFactory(..)}.</li> + <li> The specialisation of the abstract class {@link javax.media.nativewindow.NativeWindowFactory NativeWindowFactory} + <p>shall be registered with {@link javax.media.nativewindow.NativeWindowFactory#registerFactory NativeWindowFactory.registerFactory(..)}.</p></li> - <li> The specialisation of the abstract class {@link javax.media.nativewindow.GraphicsConfigurationFactory GraphicsConfigurationFactory}<br> - <br> - shall be registered with {@link javax.media.nativewindow.GraphicsConfigurationFactory#registerFactory GraphicsConfigurationFactory.registerFactory(..)}.</li> - </ul><br> - 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 javax.media.nativewindow.NativeSurface NativeSurface}.<br> - {@link javax.media.nativewindow.NativeWindow NativeWindow} specializes the NativeSurface.<br> - However, an implementation of this protocol (e.g. {@link com.jogamp.newt}) may support the creation.<br> + <li> The specialisation of the abstract class {@link javax.media.nativewindow.GraphicsConfigurationFactory GraphicsConfigurationFactory} + <p>shall be registered with {@link javax.media.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 javax.media.nativewindow.NativeSurface NativeSurface}.</p> + <p>{@link javax.media.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:<br/> + <li> Either of the following Java implementations: <ul> - <li> <a href="http://java.sun.com/j2se/1.5.0/docs/api/">Java SE 1.5 or later</a> </li> - <li> A mobile JavaVM with language 1.5 support, ie: + <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">Dalvik API Level 7</a> </li> + <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://java.sun.com/products/foundation/">Foundation Profile 1.1.2 (JSR 219)</a> </li> - <li> <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/package-summary.html"> Java 1.4 <i>java.nio</i> implementation</a> </li> + <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:<br/><br/> + The packages defined by this specification include: <ul> - <li>The <b>javax.media.nativewindow</b> package<br> - <br> - This package contains Java bindings for a native windowing system.<br> - Subsequent packages contain marker type classes, containing native characteristics of the windowing system. - - <ul> - <li>The <b>javax.media.nativewindow.awt</b> package<br> - <br> - This sub package contains classes to cover the native characteristics of the AWT windowing system.</li> + <li>The <b>javax.media.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>javax.media.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>javax.media.nativewindow.x11</b> package<br> - <br> - This sub package contains classes to cover the native characteristics of the X11 windowing system.</li> + <li>The <b>javax.media.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>javax.media.nativewindow.windows</b> package<br> - <br> - This sub package contains classes to cover the native characteristics of the Windows windowing system.</li> + <li>The <b>javax.media.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>javax.media.nativewindow.macosx</b> package<br> - <br> - This sub package contains classes to cover the native characteristics of the MacOSX windowing system.</li> + <li>The <b>javax.media.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>javax.media.nativewindow.egl</b> package<br> - <br> - This sub package contains classes to cover the native characteristics of the EGL/OpenKODE windowing system.</li> + <li>The <b>javax.media.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> -Running on a platform with a supported windowing system, the factory model shall be used -to instantiate a native window, see {@link javax.media.nativewindow.NativeWindowFactory NativeWindowFactory}.<br> -The implementor has to specialize -All supported -Regardless of the knowledge of the underly -<br> +<p>Running on a platform with a supported windowing system, the factory model shall be used +to instantiate a native window, see {@link javax.media.nativewindow.NativeWindowFactory NativeWindowFactory}.</p> -<h3>Revision History<br> - </h3> +<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> diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java b/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java index 0a5a94565..24ccc836a 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java @@ -4,14 +4,14 @@ * * 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 @@ -21,12 +21,12 @@ * 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 javax.media.nativewindow.util; public class Dimension implements Cloneable, DimensionImmutable { @@ -45,10 +45,12 @@ public class Dimension implements Cloneable, DimensionImmutable { this.height=height; } + @Override public Object cloneMutable() { return clone(); } - + + @Override public Object clone() { try { return super.clone(); @@ -57,40 +59,62 @@ public class Dimension implements Cloneable, DimensionImmutable { } } - public int getWidth() { return width; } - public int getHeight() { return height; } + @Override + public final int getWidth() { return width; } + @Override + public final int getHeight() { return height; } - public void setWidth(int width) { + public final void set(int width, int height) { this.width = width; + this.height = height; } - public void setHeight(int height) { + public final void setWidth(int width) { + this.width = width; + } + public final void setHeight(int height) { this.height = height; } - public Dimension scale(int s) { + public final Dimension scale(int s) { width *= s; height *= s; return this; } - public Dimension add(Dimension pd) { + public final Dimension add(Dimension pd) { width += pd.width ; height += pd.height ; return this; } + @Override public String toString() { - return new String(width+" x "+height); + 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(Object obj) { if(this == obj) { return true; } if (obj instanceof Dimension) { Dimension p = (Dimension)obj; - return height == p.height && + return height == p.height && width == p.width ; } return false; } + @Override public int hashCode() { // 31 * x == (x << 5) - x int hash = 31 + width; diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/DimensionImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/util/DimensionImmutable.java index d14e94c10..e6cacf4ff 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/DimensionImmutable.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/DimensionImmutable.java @@ -37,21 +37,32 @@ import com.jogamp.common.type.WriteCloneable; * <li><code>height</code></li> * </ul> */ -public interface DimensionImmutable extends WriteCloneable { +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/javax/media/nativewindow/util/Insets.java b/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java index 199ec27cb..3644916fe 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/Insets.java @@ -3,14 +3,14 @@ * * 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 @@ -20,18 +20,18 @@ * 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 javax.media.nativewindow.util; public class Insets implements Cloneable, InsetsImmutable { static final InsetsImmutable zeroInsets = new Insets(); public static final InsetsImmutable getZero() { return zeroInsets; } - + int l, r, t, b; public Insets() { @@ -44,11 +44,13 @@ public class Insets implements Cloneable, InsetsImmutable { this.t=top; this.b=bottom; } - + + @Override public Object cloneMutable() { return clone(); } - + + @Override protected Object clone() { try { return super.clone(); @@ -57,18 +59,28 @@ public class Insets implements Cloneable, InsetsImmutable { } } + @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; } - public void setLeftWidth(int left) { l = left; } - public void setRightWidth(int right) { r = right; } - public void setTopHeight(int top) { t = top; } - public void setBottomHeight(int bottom) { b = bottom; } - + public final void set(int left, int right, int top, int bottom) { + l = left; r = right; t = top; b = bottom; + } + public final void setLeftWidth(int left) { l = left; } + public final void setRightWidth(int right) { r = right; } + public final void setTopHeight(int top) { t = top; } + public final void setBottomHeight(int bottom) { b = bottom; } + + @Override public boolean equals(Object obj) { if(this == obj) { return true; } if (obj instanceof Insets) { @@ -79,6 +91,7 @@ public class Insets implements Cloneable, InsetsImmutable { return false; } + @Override public int hashCode() { int sum1 = l + b; int sum2 = t + r; @@ -88,8 +101,9 @@ public class Insets implements Cloneable, InsetsImmutable { return sum3 * (sum3 + 1)/2 + val2; } + @Override public String toString() { - return new String("[ l "+l+", r "+r+" - t "+t+", b "+b+" - "+getTotalWidth()+"x"+getTotalHeight()+"]"); + return "[ l "+l+", r "+r+" - t "+t+", b "+b+" - "+getTotalWidth()+"x"+getTotalHeight()+"]"; } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/InsetsImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/util/InsetsImmutable.java index 075641ede..8256068cd 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/InsetsImmutable.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/InsetsImmutable.java @@ -41,13 +41,13 @@ public interface InsetsImmutable extends WriteCloneable { /** @return total width, ie. <code>left_width + right_width</code> */ int getTotalWidth(); - + /** @return top inset height */ int getTopHeight(); /** @return bottom inset height */ int getBottomHeight(); - + /** @return total height, ie. <code>top_height + bottom_height</code> */ int getTotalHeight(); @@ -59,8 +59,10 @@ public interface InsetsImmutable extends WriteCloneable { * @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/javax/media/nativewindow/util/PixelFormat.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java new file mode 100644 index 000000000..823496a92 --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java @@ -0,0 +1,196 @@ +/** + * 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 javax.media.nativewindow.util; + +/** + * 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 { + /** + * Pixel size is 1 bytes (8 bits) with one component of size 1 byte (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(1, 8), + + /** + * Pixel size is 3 bytes (24 bits) with each component of size 1 byte (8 bits). + * <p> + * The components are interleaved in the order: + * <ul> + * <li>Low to High: R, G, B</li> + * </ul> + * </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(3, 24), + + /** + * Pixel size is 3 bytes (24 bits) with each component of size 1 byte (8 bits). + * <p> + * The components are interleaved in the order: + * <ul> + * <li>Low to High: B, G, R</li> + * </ul> + * </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(3, 24), + + /** + * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits). + * <p> + * The components are interleaved in the order: + * <ul> + * <li>Low to High: R, G, B, A</li> + * </ul> + * </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: X11 (XCURSOR)</li> + * <li>PNGJ: Scanlines</li> + * </ul> + * </p> + */ + RGBA8888(4, 32), + + /** + * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits). + * <p> + * The components are interleaved in the order: + * <ul> + * <li>Low to High: A, B, G, R</li> + * </ul> + * </p> + * <p> + * Compatible with: + * <ul> + * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_8_8_8_8</li> + * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_4BYTE_ABGR TYPE_4BYTE_ABGR}</li> + * </ul> + * </p> + */ + ABGR8888(4, 32), + + /** + * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits). + * <p> + * The components are interleaved in the order: + * <ul> + * <li>Low to High: A, R, G, B</li> + * </ul> + * </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(4, 32), + + /** + * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits). + * <p> + * The components are interleaved in the order: + * <ul> + * <li>Low to High: B, G, R, A</li> + * </ul> + * </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: Win32, OSX (NSBitmapImageRep), AWT</li> + * <li>Window Icon: X11, Win32, OSX (NSBitmapImageRep)</li> + * </ul> + * </p> + */ + BGRA8888(4, 32); + + /** Number of components per pixel, e.g. 4 for RGBA. */ + public final int componentCount; + /** Number of bits per pixel, e.g. 32 for RGBA. */ + public final int bitsPerPixel; + /** Number of bytes per pixel, e.g. 4 for RGBA. */ + public final int bytesPerPixel() { return (7+bitsPerPixel)/8; } + + private PixelFormat(int componentCount, int bpp) { + this.componentCount = componentCount; + this.bitsPerPixel = bpp; + } +} diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java new file mode 100644 index 000000000..87a9ca4fc --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java @@ -0,0 +1,373 @@ +/** + * 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 javax.media.nativewindow.util; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import com.jogamp.common.nio.Buffers; + +/** + * Pixel Rectangle Utilities. + * <p> + * All conversion methods are endian independent. + * </p> + */ +public class PixelFormatUtil { + public static interface PixelSink { + /** Return the sink's destination pixelformat. */ + PixelFormat getPixelformat(); + + /** + * 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 sink's memory is laid out in + * OpenGL's coordinate system, <i>origin at bottom left</i>. + * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>. + */ + boolean isGLOriented(); + } + /** + * Pixel sink for up-to 32bit. + */ + public static interface PixelSink32 extends PixelSink { + /** + * Will be invoked over all rows top-to down + * and all columns left-to-right. + * <p> + * Shall consider dest pixelformat and only store as much components + * as defined, up to 32bit. + * </p> + * <p> + * Implementation may better write single bytes from low-to-high bits, + * e.g. {@link ByteOrder#LITTLE_ENDIAN} order. + * Otherwise a possible endian conversion must be taken into consideration. + * </p> + * @param x + * @param y + * @param pixel + */ + void store(int x, int y, int pixel); + } + + /** + * 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(PixelFormat fmt) { + switch(fmt) { + case LUMINANCE: + return PixelFormat.LUMINANCE; + 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: + throw new InternalError("Unhandled format "+fmt); + } + } + + public static int getValue32(PixelFormat src_fmt, ByteBuffer src, int srcOff) { + switch(src_fmt) { + case LUMINANCE: { + final byte c1 = src.get(srcOff++); + return ( 0xff ) << 24 | ( 0xff & c1 ) << 16 | ( 0xff & c1 ) << 8 | ( 0xff & c1 ); + } + case RGB888: + case BGR888: { + final byte c1 = src.get(srcOff++); + final byte c2 = src.get(srcOff++); + final byte c3 = src.get(srcOff++); + return ( 0xff ) << 24 | ( 0xff & c3 ) << 16 | ( 0xff & c2 ) << 8 | ( 0xff & c1 ); + } + case RGBA8888: + case ABGR8888: + case ARGB8888: + case BGRA8888: { + final byte c1 = src.get(srcOff++); + final byte c2 = src.get(srcOff++); + final byte c3 = src.get(srcOff++); + final byte c4 = src.get(srcOff++); + return ( 0xff & c4 ) << 24 | ( 0xff & c3 ) << 16 | ( 0xff & c2 ) << 8 | ( 0xff & c1 ); + } + default: + throw new InternalError("Unhandled format "+src_fmt); + } + } + + public static int convertToInt32(PixelFormat dest_fmt, final byte r, final byte g, final byte b, final byte a) { + switch(dest_fmt) { + case LUMINANCE: { + final byte l = ( byte) ( ( ( ( 0xff & r ) + ( 0xff & g ) + ( 0xff & b ) ) / 3 ) ); + 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 "+dest_fmt); + } + } + + public static int convertToInt32(PixelFormat dest_fmt, PixelFormat src_fmt, 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(dest_fmt, r, g, b, a); + } + + public static int convertToInt32(PixelFormat dest_fmt, 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 convert32(final PixelRectangle src, + final PixelFormat destFmt, int ddestStride, final boolean isGLOriented, + final boolean destIsDirect) { + final int width = src.getSize().getWidth(); + final int height = src.getSize().getHeight(); + final int bpp = destFmt.bytesPerPixel(); + final int destStride; + if( 0 != ddestStride ) { + destStride = ddestStride; + if( destStride < bpp * width ) { + throw new IllegalArgumentException("Invalid stride "+destStride+", must be greater than bytesPerPixel "+bpp+" * width "+width); + } + } else { + destStride = bpp * width; + } + final int capacity = destStride*height; + final ByteBuffer bb = destIsDirect ? Buffers.newDirectByteBuffer(capacity) : ByteBuffer.allocate(capacity).order(src.getPixels().order()); + + // System.err.println("XXX: SOURCE "+src); + // System.err.println("XXX: DEST fmt "+destFmt+", stride "+destStride+" ("+ddestStride+"), isGL "+isGLOriented+", "+width+"x"+height+", capacity "+capacity+", "+bb); + + final PixelFormatUtil.PixelSink32 imgSink = new PixelFormatUtil.PixelSink32() { + public void store(int x, int y, int pixel) { + int o = destStride*y+x*bpp; + bb.put(o++, (byte) ( pixel )); // 1 + if( 3 <= bpp ) { + bb.put(o++, (byte) ( pixel >>> 8 )); // 2 + bb.put(o++, (byte) ( pixel >>> 16 )); // 3 + if( 4 <= bpp ) { + bb.put(o++, (byte) ( pixel >>> 24 )); // 4 + } + } + } + @Override + public final PixelFormat getPixelformat() { + return destFmt; + } + @Override + public final int getStride() { + return destStride; + } + @Override + public final boolean isGLOriented() { + return isGLOriented; + } + }; + convert32(imgSink, src); + return new PixelRectangle.GenericPixelRect(destFmt, src.getSize(), destStride, isGLOriented, bb); + } + + public static void convert32(PixelSink32 destInt32, final PixelRectangle src) { + convert32(destInt32, + src.getPixels(), src.getPixelformat(), + src.isGLOriented(), + src.getSize().getWidth(), src.getSize().getHeight(), + src.getStride()); + } + + /** + * + * @param dest32 32bit pixel sink + * @param src_bb + * @param src_fmt + * @param src_glOriented if true, the source memory is laid out in OpenGL's coordinate system, <i>origin at bottom left</i>, + * otherwise <i>origin at top left</i>. + * @param width + * @param height + * @param strideInBytes stride in byte-size, i.e. byte count from one line to the next. + * If zero, stride is set to <code>width * bytes-per-pixel</code>. + * If not zero, value must be >= <code>width * bytes-per-pixel</code>. + * @param stride_bytes stride in byte-size, i.e. byte count from one line to the next. + * Must be >= {@link PixelFormat#bytesPerPixel() src_fmt.bytesPerPixel()} * width. + * @throws IllegalArgumentException if <code>strideInBytes</code> is invalid + */ + public static void convert32(PixelSink32 dest32, + final ByteBuffer src_bb, final PixelFormat src_fmt, final boolean src_glOriented, final int width, final int height, int stride_bytes) { + final int src_bpp = src_fmt.bytesPerPixel(); + if( 0 != stride_bytes ) { + if( stride_bytes < src_bpp * width ) { + throw new IllegalArgumentException("Invalid stride "+stride_bytes+", must be greater than bytesPerPixel "+src_bpp+" * width "+width); + } + } else { + stride_bytes = src_bpp * width; + } + final PixelFormat dest_fmt = dest32.getPixelformat(); + final boolean vert_flip = src_glOriented != dest32.isGLOriented(); + final boolean fast_copy = src_fmt == dest_fmt && dest_fmt.bytesPerPixel() == 4 ; + // System.err.println("XXX: SRC fmt "+src_fmt+", stride "+stride_bytes+", isGL "+src_glOriented+", "+width+"x"+height); + // System.err.println("XXX: DST fmt "+dest_fmt+", fast_copy "+fast_copy); + + if( fast_copy ) { + // Fast copy + for(int y=0; y<height; y++) { + int o = vert_flip ? ( height - 1 - y ) * stride_bytes : y * stride_bytes; + for(int x=0; x<width; x++) { + dest32.store(x, y, getValue32(src_fmt, src_bb, o)); + o += src_bpp; + } + } + } else { + // Conversion + for(int y=0; y<height; y++) { + int o = vert_flip ? ( height - 1 - y ) * stride_bytes : y * stride_bytes; + for(int x=0; x<width; x++) { + dest32.store( x, y, convertToInt32( dest_fmt, src_fmt, src_bb, o)); + o += src_bpp; + } + } + } + } +} + diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java new file mode 100644 index 000000000..96c1f7b33 --- /dev/null +++ b/src/nativewindow/classes/javax/media/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 javax.media.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.bytesPerPixel() * size.getWidth()) { + throw new IllegalArgumentException("Invalid stride "+strideInBytes+", must be greater than bytesPerPixel "+pixelformat.bytesPerPixel()+" * width "+size.getWidth()); + } + } else { + strideInBytes = pixelformat.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 = 31 + pixelformat.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/javax/media/nativewindow/util/Point.java b/src/nativewindow/classes/javax/media/nativewindow/util/Point.java index c53b16928..331c1388e 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/Point.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/Point.java @@ -42,10 +42,12 @@ public class Point implements Cloneable, PointImmutable { this(0, 0); } + @Override public Object cloneMutable() { return clone(); } - + + @Override public Object clone() { try { return super.clone(); @@ -54,6 +56,20 @@ public class Point implements Cloneable, PointImmutable { } } + @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(Object obj) { if(this == obj) { return true; } if (obj instanceof Point) { @@ -63,14 +79,17 @@ public class Point implements Cloneable, PointImmutable { 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; @@ -78,29 +97,31 @@ public class Point implements Cloneable, PointImmutable { return hash; } + @Override public String toString() { - return new String( x + " / " + y ); + return x + " / " + y; } - public void setX(int x) { this.x = x; } - public void setY(int y) { this.y = y; } + public final void set(int x, int y) { this.x = x; this.y = y; } + public final void setX(int x) { this.x = x; } + public final void setY(int y) { this.y = y; } - public Point translate(Point pd) { + public final Point translate(Point pd) { x += pd.x ; y += pd.y ; return this; } - public Point translate(int dx, int dy) { + public final Point translate(int dx, int dy) { x += dx ; y += dy ; return this; } - public Point scale(int sx, int sy) { + public final Point scale(int sx, int sy) { x *= sx ; y *= sy ; return this; } - + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PointImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/util/PointImmutable.java index d7eb0e7b4..08c628cc1 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/PointImmutable.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/PointImmutable.java @@ -32,21 +32,32 @@ package javax.media.nativewindow.util; import com.jogamp.common.type.WriteCloneable; /** Immutable Point interface */ -public interface PointImmutable extends WriteCloneable { +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/javax/media/nativewindow/util/Rectangle.java b/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java index 8d6bfe48f..d0d8bfb13 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/Rectangle.java @@ -3,14 +3,14 @@ * * 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 @@ -20,14 +20,16 @@ * 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 javax.media.nativewindow.util; +import java.util.List; + public class Rectangle implements Cloneable, RectangleImmutable { int x; int y; @@ -44,11 +46,13 @@ public class Rectangle implements Cloneable, RectangleImmutable { this.width=width; this.height=height; } - + + @Override public Object cloneMutable() { return clone(); } - + + @Override protected Object clone() { try { return super.clone(); @@ -57,15 +61,118 @@ public class Rectangle implements Cloneable, RectangleImmutable { } } + @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 void setX(int x) { this.x = x; } - public void setY(int y) { this.y = y; } - public void setWidth(int width) { this.width = width; } - public void setHeight(int height) { this.height = height; } + public final void set(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + public final void setX(int x) { this.x = x; } + public final void setY(int y) { this.y = y; } + public final void setWidth(int width) { this.width = width; } + public final void setHeight(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(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(RectangleImmutable r) { + final RectangleImmutable isect = intersection(r); + final float sqI = (float) ( isect.getWidth()*isect.getHeight() ); + final float sqT = (float) ( width*height ); + return sqI / sqT; + } + + @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(Object obj) { if(this == obj) { return true; } if (obj instanceof Rectangle) { @@ -76,6 +183,7 @@ public class Rectangle implements Cloneable, RectangleImmutable { return false; } + @Override public int hashCode() { int sum1 = x + height; int sum2 = width + y; @@ -85,8 +193,9 @@ public class Rectangle implements Cloneable, RectangleImmutable { return sum3 * (sum3 + 1)/2 + val2; } + @Override public String toString() { - return new String("[ "+x+" / "+y+" "+width+" x "+height+" ]"); + return "[ "+x+" / "+y+" "+width+" x "+height+" ]"; } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java b/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java index d3b43c864..7ca92ff53 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/RectangleImmutable.java @@ -31,7 +31,7 @@ package javax.media.nativewindow.util; import com.jogamp.common.type.WriteCloneable; /** Immutable Rectangle interface */ -public interface RectangleImmutable extends WriteCloneable { +public interface RectangleImmutable extends WriteCloneable, Comparable<RectangleImmutable> { int getHeight(); @@ -41,6 +41,35 @@ public interface RectangleImmutable extends WriteCloneable { 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 @@ -49,8 +78,10 @@ public interface RectangleImmutable extends WriteCloneable { * @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/javax/media/nativewindow/util/SurfaceSize.java b/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java index 8f21bc49b..77619731f 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/SurfaceSize.java @@ -4,14 +4,14 @@ * * 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 @@ -21,23 +21,24 @@ * 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 javax.media.nativewindow.util; -/** Immutable SurfaceSize Class, consisting of it's read only components:<br> +/** + * Immutable SurfaceSize Class, consisting of it's read only components:<br> * <ul> * <li>{@link javax.media.nativewindow.util.DimensionImmutable} size in pixels</li> * <li><code>bits per pixel</code></li> * </ul> */ -public class SurfaceSize { - DimensionImmutable resolution; - int bitsPerPixel; +public class SurfaceSize implements Comparable<SurfaceSize> { + final DimensionImmutable resolution; + final int bitsPerPixel; public SurfaceSize(DimensionImmutable resolution, int bitsPerPixel) { if(null==resolution || bitsPerPixel<=0) { @@ -55,8 +56,30 @@ public class SurfaceSize { return bitsPerPixel; } + @Override public final String toString() { - return new String("[ "+resolution+" x "+bitsPerPixel+" bpp ]"); + return "[ "+resolution+" 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; } /** @@ -67,6 +90,7 @@ public class SurfaceSize { * @return <code>true</code> if the two dimensions are equal; * otherwise <code>false</code>. */ + @Override public final boolean equals(Object obj) { if(this == obj) { return true; } if (obj instanceof SurfaceSize) { @@ -77,6 +101,7 @@ public class SurfaceSize { return false; } + @Override public final int hashCode() { // 31 * x == (x << 5) - x int hash = 31 + getResolution().hashCode(); |