diff options
Diffstat (limited to 'src/nativewindow/classes')
24 files changed, 665 insertions, 230 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java index 04f616daf..b7f6ba45d 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java @@ -30,51 +30,49 @@ package com.jogamp.nativewindow; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.SurfaceChangeable; +public class WrappedSurface extends ProxySurface { + protected long surfaceHandle; -public class WrappedSurface extends ProxySurface implements SurfaceChangeable { - protected long surfaceHandle; - - public WrappedSurface(AbstractGraphicsConfiguration cfg) { - this(cfg, 0); - } - - public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle) { - super(cfg); + public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { + super(cfg, initialWidth, initialHeight, upstream); surfaceHandle=handle; } @Override - protected final void invalidateImpl() { + protected void invalidateImpl() { surfaceHandle = 0; } @Override - final public long getSurfaceHandle() { + public final long getSurfaceHandle() { return surfaceHandle; } @Override - final public void setSurfaceHandle(long surfaceHandle) { + public final void setSurfaceHandle(long surfaceHandle) { this.surfaceHandle=surfaceHandle; } - + @Override - final protected int lockSurfaceImpl() { - return LOCK_SUCCESS; + protected final int lockSurfaceImpl() { + return LOCK_SUCCESS; } @Override - final protected void unlockSurfaceImpl() { + protected final void unlockSurfaceImpl() { } @Override public String toString() { + final UpstreamSurfaceHook ush = getUpstreamSurfaceHook(); + final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil"; + return "WrappedSurface[config " + getPrivateGraphicsConfiguration()+ ", displayHandle 0x" + Long.toHexString(getDisplayHandle()) + ", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle()) + ", size " + getWidth() + "x" + getHeight() + - ", surfaceLock "+surfaceLock+"]"; + ", surfaceLock "+surfaceLock+ + ", upstreamSurfaceHook "+ush_s+"]"; } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java index 61d5e5c0d..2a152ff35 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/AWTGraphicsConfiguration.java @@ -95,8 +95,8 @@ public class AWTGraphicsConfiguration extends DefaultGraphicsConfiguration imple GraphicsConfiguration gc = awtGraphicsDevice.getDefaultConfiguration(); capsChosen = AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capsRequested, gc); } - final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(awtDevice); - final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, null, awtScreen); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(awtDevice, capsChosen); + final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, null, awtScreen, VisualIDHolder.VID_UNDEFINED); if(config instanceof AWTGraphicsConfiguration) { return (AWTGraphicsConfiguration) config; } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java index cffe495f7..d4b927cf1 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java @@ -81,6 +81,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, protected long drawable; protected Rectangle bounds; protected Insets insets; + private long offscreenSurfaceLayer; private long drawable_old; @@ -106,6 +107,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, invalidate(); this.component = windowObject; this.isApplet = false; + this.offscreenSurfaceLayer = 0; } @Override @@ -196,6 +198,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, System.err.println("JAWTWindow.attachSurfaceHandle(): 0x"+Long.toHexString(layerHandle) + ", bounds "+bounds); } attachSurfaceLayerImpl(layerHandle); + offscreenSurfaceLayer = layerHandle; } finally { unlockSurface(); } @@ -206,25 +209,34 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, * {@inheritDoc} */ @Override - public final void detachSurfaceLayer(final long layerHandle) throws NativeWindowException { + public final void detachSurfaceLayer() throws NativeWindowException { if( !isOffscreenLayerSurfaceEnabled() ) { throw new java.lang.UnsupportedOperationException("Not an offscreen layer surface"); } + if( 0 == offscreenSurfaceLayer) { + throw new NativeWindowException("No offscreen layer attached: "+this); + } int lockRes = lockSurface(); if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { throw new NativeWindowException("Could not lock (offscreen layer): "+this); } try { if(DEBUG) { - System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(layerHandle)); + System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(offscreenSurfaceLayer)); } - detachSurfaceLayerImpl(layerHandle); + detachSurfaceLayerImpl(offscreenSurfaceLayer); + offscreenSurfaceLayer = 0; } finally { unlockSurface(); } } protected abstract void detachSurfaceLayerImpl(final long layerHandle); + @Override + public final boolean isSurfaceLayerAttached() { + return 0 != offscreenSurfaceLayer; + } + // // SurfaceUpdateListener // diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java index 4ee336176..389949e90 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java @@ -36,25 +36,84 @@ import javax.media.nativewindow.*; /** Encapsulates a graphics device on EGL platforms. */ - public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneable { - boolean closeDisplay = false; + final long nativeDisplayID; + final EGLDisplayLifecycleCallback eglLifecycleCallback; /** + * Hack to allow inject a EGL termination call. + * <p> + * FIXME: This shall be removed when relocated EGL to the nativewindow package, + * since then it can be utilized directly. + * </p> + */ + public interface EGLDisplayLifecycleCallback { + /** + * Implementation should issue an <code>EGL.eglGetDisplay(nativeDisplayID)</code> + * inclusive <code>EGL.eglInitialize(eglDisplayHandle, ..)</code> call. + * @param eglDisplayHandle + */ + public long eglGetAndInitDisplay(long nativeDisplayID); + + /** + * Implementation should issue an <code>EGL.eglTerminate(eglDisplayHandle)</code> call. + * @param eglDisplayHandle + */ + void eglTerminate(long eglDisplayHandle); + } + + /** * Note that this is not an open connection, ie no native display handle exist. * This constructor exist to setup a default device connection/unit.<br> */ public EGLGraphicsDevice(String connection, int unitID) { super(NativeWindowFactory.TYPE_EGL, connection, unitID); + this.nativeDisplayID = 0 ; // EGL.EGL_DEFAULT_DISPLAY + this.eglLifecycleCallback = null; } - /** Constructs a new EGLGraphicsDevice corresponding to the given EGL display handle. */ - public EGLGraphicsDevice(long eglDisplay, String connection, int unitID) { + public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLDisplayLifecycleCallback eglLifecycleCallback) { super(NativeWindowFactory.TYPE_EGL, connection, unitID, eglDisplay); + this.nativeDisplayID = nativeDisplayID; + this.eglLifecycleCallback = eglLifecycleCallback; } + public long getNativeDisplayID() { return nativeDisplayID; } + + @Override public Object clone() { return super.clone(); } + + @Override + public boolean open() { + if(null != eglLifecycleCallback && 0 == handle) { + if(DEBUG) { + System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.open(): "+this); + } + handle = eglLifecycleCallback.eglGetAndInitDisplay(nativeDisplayID); + if(0 == handle) { + throw new NativeWindowException("EGLGraphicsDevice.open() failed: "+this); + } + return true; + } + return false; + } + + @Override + public boolean close() { + if(null != eglLifecycleCallback && 0 != handle) { + if(DEBUG) { + System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.close(): "+this); + } + eglLifecycleCallback.eglTerminate(handle); + } + return super.close(); + } + + @Override + public String toString() { + return "EGLGraphicsDevice[type EGL, connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", nativeDisplayID 0x"+Long.toHexString(nativeDisplayID)+"]"; + } } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java index 735d85fb1..ba07d97dc 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java @@ -34,17 +34,21 @@ import java.lang.reflect.Method; import org.eclipse.swt.graphics.GCData; import org.eclipse.swt.widgets.Control; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.VisualIDHolder; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsDevice; +import com.jogamp.nativewindow.x11.X11GraphicsScreen; -import jogamp.common.awt.AWTEDTExecutor; import jogamp.nativewindow.macosx.OSXUtil; +import jogamp.nativewindow.x11.X11Lib; public class SWTAccessor { static final Field swt_control_handle; @@ -204,8 +208,6 @@ public class SWTAccessor { if( null != OS_gtk_class ) { long widgedHandle = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle); long displayHandle = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, widgedHandle); - // FIXME: May think about creating a private non-shared X11 Display handle, like we use to for AWT - // to avoid locking problems ! return new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, false); } if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ) { @@ -216,6 +218,26 @@ public class SWTAccessor { } throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); } + public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) { + if( null != OS_gtk_class ) { + return new X11GraphicsScreen((X11GraphicsDevice)device, screen); + } + if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) || + NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) { + return new DefaultGraphicsScreen(device, screen); + } + throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); + } + public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) { + if( null != OS_gtk_class ) { + return X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle); + } + if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) || + NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) { + return VisualIDHolder.VID_UNDEFINED; + } + throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); + } public static long getWindowHandle(Control swtControl) { long handle = getHandle(swtControl); diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java index 308756b54..5e4d6f41a 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java @@ -33,7 +33,6 @@ package com.jogamp.nativewindow.x11; -import jogamp.nativewindow.Debug; import jogamp.nativewindow.x11.X11Lib; import jogamp.nativewindow.x11.X11Util; @@ -46,8 +45,7 @@ import javax.media.nativewindow.ToolkitLock; */ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable { - public static final boolean DEBUG = Debug.debug("GraphicsDevice"); - final boolean closeDisplay; + final boolean handleOwner; /** Constructs a new X11GraphicsDevice corresponding to the given connection and default * {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#getDefaultToolkitLock(String)}.<br> @@ -57,7 +55,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl */ public X11GraphicsDevice(String connection, int unitID) { super(NativeWindowFactory.TYPE_X11, connection, unitID); - closeDisplay = false; + handleOwner = false; } /** Constructs a new X11GraphicsDevice corresponding to the given native display handle and default @@ -70,7 +68,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl if(0==display) { throw new NativeWindowException("null display"); } - closeDisplay = owner; + handleOwner = owner; } /** @@ -83,16 +81,39 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl if(0==display) { throw new NativeWindowException("null display"); } - closeDisplay = owner; + handleOwner = owner; } + public int getDefaultVisualID() { + // It still could be an AWT hold handle .. + final long display = getHandle(); + final int scrnIdx = X11Lib.DefaultScreen(display); + return X11Lib.DefaultVisualID(display, scrnIdx); + } + + @Override public Object clone() { return super.clone(); } + @Override + public boolean open() { + if(handleOwner && 0 == handle) { + if(DEBUG) { + System.err.println(Thread.currentThread().getName() + " - X11GraphicsDevice.open(): "+this); + } + handle = X11Util.openDisplay(connection); + if(0 == handle) { + throw new NativeWindowException("X11GraphicsDevice.open() failed: "+this); + } + return true; + } + return false; + } + + @Override public boolean close() { - // FIXME: shall we respect the unitID ? - if(closeDisplay && 0 != handle) { + if(handleOwner && 0 != handle) { if(DEBUG) { System.err.println(Thread.currentThread().getName() + " - X11GraphicsDevice.close(): "+this); } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java index 94013ec38..5f3c220ca 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsScreen.java @@ -56,13 +56,11 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl return new X11GraphicsScreen(new X11GraphicsDevice(display, AbstractGraphicsDevice.DEFAULT_UNIT, owner), screenIdx); } - public long getDefaultVisualID() { + public int getVisualID() { // It still could be an AWT hold handle .. - long display = getDevice().getHandle(); - int scrnIdx = X11Lib.DefaultScreen(display); - return X11Lib.DefaultVisualID(display, scrnIdx); + return X11Lib.DefaultVisualID(getDevice().getHandle(), getIndex()); } - + private static int fetchScreen(X11GraphicsDevice device, int screen) { // It still could be an AWT hold handle .. if(X11Util.XineramaIsEnabled(device.getHandle())) { diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java index 1dd01a274..756e4451b 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java @@ -40,11 +40,15 @@ 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"; @@ -109,16 +113,33 @@ public interface AbstractGraphicsDevice extends Cloneable { */ public void unlock(); + /** + * Optionally [re]opening the device if handle is <code>null</code>. + * <p> + * The default implementation is a <code>NOP</code>. + * </p> + * <p> + * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice} + * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice} + * issue the native open operation in case handle is <code>null</code>. + * </p> + * + * @return true if the handle was <code>null</code> and opening was successful, otherwise false. + */ + public boolean open(); + /** - * Optionally closing the device. + * Optionally closing the device if handle is not <code>null</code>. * <p> * The default implementation is a <code>NOP</code>, just setting the handle to <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> + * <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 handles's ownership. + * </p> * - * @return true if the handle was not <code>null</code>, otherwise false. + * @return true if the handle was not <code>null</code> and closing was successful, otherwise false. */ public boolean close(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java index 196f23598..cb33aec5e 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java +++ b/src/nativewindow/classes/javax/media/nativewindow/Capabilities.java @@ -211,9 +211,18 @@ public class Capabilities implements CapabilitiesImmutable, Cloneable { 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; } diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index 187959a67..583fde07f 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -97,22 +97,27 @@ 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; } @@ -124,6 +129,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice * @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(); } @@ -135,10 +141,17 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice * @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() { if(0 != handle) { handle = 0; diff --git a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java index 2610f2cfa..c3fdc6798 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/GraphicsConfigurationFactory.java @@ -36,9 +36,15 @@ 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 @@ -59,8 +65,43 @@ 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; + } + + public final int hashCode() { + return hash32; + } + + 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 { @@ -69,7 +110,8 @@ public abstract class GraphicsConfigurationFactory { 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() { @@ -79,14 +121,13 @@ 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()); + registerFactory(defaultDeviceCapsType.deviceType, defaultDeviceCapsType.capsType, new DefaultGraphicsConfigurationFactoryImpl()); if (NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) { try { @@ -112,7 +153,6 @@ public abstract class GraphicsConfigurationFactory { System.err.println(Thread.currentThread().getName()+" - GraphicsConfigurationFactory.shutdown()"); } registeredFactories.clear(); - registeredFactories = null; } } @@ -133,74 +173,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> + * + * <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> * - * @throws IllegalArgumentException if the given class does not implement AbstractGraphicsDevice + * @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"); } - - 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); + 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(); + } + + 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); } } @@ -244,6 +385,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 +400,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 +417,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 +425,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..ff53c8109 --- /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/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index b85ad47f2..6faa9890c 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -561,4 +561,21 @@ public abstract class NativeWindowFactory { } 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 ; + } + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java index dd36509ba..f7dbc6c27 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java @@ -42,7 +42,12 @@ public interface OffscreenLayerSurface { * Detaches a previously attached offscreen layer from this offscreen layer surface. * @see #attachSurfaceLayer(long) * @see #isOffscreenLayerSurfaceEnabled() - * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false + * @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false + * or no surface layer is attached. */ - public void detachSurfaceLayer(final long layerHandle) throws NativeWindowException; + public void detachSurfaceLayer() throws NativeWindowException; + + /** Returns true if a surface layer is attached, otherwise false. */ + public boolean isSurfaceLayerAttached(); + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java index 1dabc3dcd..7fc9789c2 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java @@ -28,38 +28,108 @@ 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 { +public abstract class ProxySurface implements NativeSurface, MutableSurface { public static final boolean DEBUG = Debug.debug("ProxySurface"); + + /** + * Implementation specific bitvalue stating the upstream's {@link AbstractGraphicsDevice} is owned by this {@link ProxySurface}. + * @see #setImplBitfield(int) + * @see #getImplBitfield() + */ + public static final int OWN_DEVICE = 1 << 7; + + /** + * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete. + * @see #setImplBitfield(int) + * @see #getImplBitfield() + */ + public static final int INVISIBLE_WINDOW = 1 << 8; - private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); - private AbstractGraphicsConfiguration config; // control access due to delegation - protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); + /** 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 */ + public int getWidth(ProxySurface s); + /** Returns the height of the upstream surface */ + public int getHeight(ProxySurface s); + } + + private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); + private final AbstractGraphicsConfiguration config; // control access due to delegation + private final UpstreamSurfaceHook upstream; + public final int initialWidth; + public final int initialHeight; private long surfaceHandle_old; + protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); protected long displayHandle; - protected int height; protected int scrnIndex; - protected int width; + protected int implBitfield; - public ProxySurface(AbstractGraphicsConfiguration cfg) { - invalidate(); - config = cfg; - displayHandle=cfg.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - surfaceHandle_old = 0; + /** + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param initialWidth the initial width + * @param initialHeight the initial height + */ + protected ProxySurface(AbstractGraphicsConfiguration cfg, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { + if(null == cfg) { + throw new IllegalArgumentException("null config"); + } + this.config = cfg; + this.upstream = upstream; + this.initialWidth = initialWidth; + this.initialHeight = initialHeight; + this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); + this.surfaceHandle_old = 0; + this.implBitfield = 0; } - void invalidate() { - displayHandle = 0; - invalidateImpl(); + public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; } + + /** + * If a valid {@link UpstreamSurfaceHook} instance is passed in the + * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, + * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set. + */ + public void createNotify() { + if(null != upstream) { + upstream.create(this); + } + this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); + this.surfaceHandle_old = 0; } - protected abstract void invalidateImpl(); - + + /** + * If a valid {@link UpstreamSurfaceHook} instance is passed in the + * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, + * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all fields are cleared. + */ + public void destroyNotify() { + if(null != upstream) { + upstream.destroy(this); + invalidateImpl(); + } + this.displayHandle = 0; + this.surfaceHandle_old = 0; + } + + /** + * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed. + * @see #destroyNotify() + */ + protected void invalidateImpl() { + throw new InternalError("UpstreamSurfaceHook given, but required method not implemented."); + } + @Override public final long getDisplayHandle() { return displayHandle; @@ -83,18 +153,22 @@ public abstract class ProxySurface implements NativeSurface { public abstract long getSurfaceHandle(); @Override + public abstract void setSurfaceHandle(long surfaceHandle); + + @Override public final int getWidth() { - return width; + if(null != upstream) { + return upstream.getWidth(this); + } + return initialWidth; } @Override public final int getHeight() { - return height; - } - - public void surfaceSizeChanged(int width, int height) { - this.width = width; - this.height = height; + if(null != upstream) { + return upstream.getHeight(this); + } + return initialHeight; } @Override @@ -187,7 +261,10 @@ public abstract class ProxySurface implements NativeSurface { public final Thread getSurfaceLockOwner() { return surfaceLock.getOwner(); } - + @Override public abstract String toString(); + + public int getImplBitfield() { return implBitfield; } + public void setImplBitfield(int v) { implBitfield=v; } } 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/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java b/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java index f34b740d4..52e9c8308 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java +++ b/src/nativewindow/classes/jogamp/nativewindow/DefaultGraphicsConfigurationFactoryImpl.java @@ -37,7 +37,7 @@ import javax.media.nativewindow.*; public class DefaultGraphicsConfigurationFactoryImpl extends GraphicsConfigurationFactory { protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( - CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen) { + CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID) { return new DefaultGraphicsConfiguration(screen, capsChosen, capsRequested); } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java index 4877d5c4f..4f68c6945 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java +++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java @@ -34,8 +34,8 @@ import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.SurfaceUpdatedListener; public class SurfaceUpdatedHelper implements SurfaceUpdatedListener { - private Object surfaceUpdatedListenersLock = new Object(); - private ArrayList<SurfaceUpdatedListener> surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>(); + private final Object surfaceUpdatedListenersLock = new Object(); + private final ArrayList<SurfaceUpdatedListener> surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>(); // // Management Utils diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java index 42fd08df1..e81d61e0f 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java @@ -48,7 +48,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.Capabilities; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.util.Point; import com.jogamp.nativewindow.MutableGraphicsConfiguration; @@ -62,7 +62,7 @@ import jogamp.nativewindow.jawt.JAWT_DrawingSurfaceInfo; import jogamp.nativewindow.jawt.macosx.JAWT_MacOSXDrawingSurfaceInfo; import jogamp.nativewindow.macosx.OSXUtil; -public class MacOSXJAWTWindow extends JAWTWindow implements SurfaceChangeable { +public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { public MacOSXJAWTWindow(Object comp, AbstractGraphicsConfiguration config) { super(comp, config); if(DEBUG) { @@ -103,24 +103,9 @@ public class MacOSXJAWTWindow extends JAWTWindow implements SurfaceChangeable { if(DEBUG) { System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); } - sscSet &= 0 != surfaceHandle; // reset ssc flag if NULL surfaceHandle, ie. back to JAWT this.surfaceHandle = surfaceHandle; } - public void surfaceSizeChanged(int width, int height) { - sscSet = true; - sscWidth = width; - sscHeight = height; - } - - public int getWidth() { - return sscSet ? sscWidth : super.getWidth(); - } - - public int getHeight() { - return sscSet ? sscHeight: super.getHeight(); - } - protected JAWT fetchJAWTImpl() throws NativeWindowException { // use offscreen if supported and [ applet or requested ] return JAWTUtil.getJAWT(getShallUseOffscreenLayer() || isApplet()); @@ -280,8 +265,6 @@ public class MacOSXJAWTWindow extends JAWTWindow implements SurfaceChangeable { private long rootSurfaceLayerHandle = 0; // attached to the JAWT_SurfaceLayer private long surfaceHandle = 0; - private int sscWidth, sscHeight; - private boolean sscSet = false; // Workaround for instance of 4796548 private boolean firstLock = true; diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 4d472b01a..894084fce 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -28,6 +28,7 @@ package jogamp.nativewindow.macosx; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; import jogamp.nativewindow.Debug; @@ -59,23 +60,52 @@ public class OSXUtil { return false; } - public static Point GetLocationOnScreen(long windowOrView, int src_x, int src_y) { - return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); + public static boolean isNSView(long object) { + return isNSView0(object); } - public static long CreateNSView(int x, int y, int width, int height) { - return CreateNSView0(x, y, width, height); + /** + * In case the <code>windowOrView</code> is top-level, + * you shall set <code>topLevel</code> to true where + * insets gets into account to compute the client position as follows: + * <pre> + if(topLevel) { + // top-level position -> client window position + final Insets insets = GetInsets(windowOrView); + los.setX(los.getX() + insets.getLeftWidth()); + los.setY(los.getY() + insets.getTopHeight()); + } + * </pre> + * @param windowOrView + * @param topLevel + * @param src_x + * @param src_y + * @return the client position + */ + public static Point GetLocationOnScreen(long windowOrView, boolean topLevel, int src_x, int src_y) { + final Point los = (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); + if(topLevel) { + // top-level position -> client window position + final Insets insets = GetInsets(windowOrView); + los.setX(los.getX() + insets.getLeftWidth()); + los.setY(los.getY() + insets.getTopHeight()); + } + return los; } - public static void DestroyNSView(long nsView) { - DestroyNSView0(nsView); + + public static Insets GetInsets(long windowOrView) { + return (Insets) GetInsets0(windowOrView); } - + public static long CreateNSWindow(int x, int y, int width, int height) { return CreateNSWindow0(x, y, width, height); } public static void DestroyNSWindow(long nsWindow) { DestroyNSWindow0(nsWindow); } + public static long GetNSView(long nsWindow) { + return GetNSView0(nsWindow); + } public static long CreateCALayer(int x, int y, int width, int height) { return CreateCALayer0(x, y, width, height); @@ -133,11 +163,12 @@ public class OSXUtil { } */ private static native boolean initIDs0(); + private static native boolean isNSView0(long object); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); - private static native long CreateNSView0(int x, int y, int width, int height); - private static native void DestroyNSView0(long nsView); + private static native Object GetInsets0(long windowOrView); private static native long CreateNSWindow0(int x, int y, int width, int height); private static native void DestroyNSWindow0(long nsWindow); + private static native long GetNSView0(long nsWindow); private static native long CreateCALayer0(int x, int y, int width, int height); private static native void AddCASublayer0(long rootCALayer, long subCALayer); private static native void RemoveCASublayer0(long rootCALayer, long subCALayer); diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java index c24f64b32..e368aa6a1 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java @@ -31,6 +31,7 @@ package jogamp.nativewindow.windows; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; /** @@ -43,22 +44,49 @@ public class GDISurface extends ProxySurface { protected long windowHandle; protected long surfaceHandle; - public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle) { - super(cfg); - if(0 == windowHandle) { - throw new NativeWindowException("Error hwnd 0, werr: "+GDI.GetLastError()); - } + public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { + super(cfg, initialWidth, initialHeight, upstream); this.windowHandle=windowHandle; + this.surfaceHandle=0; } @Override - protected final void invalidateImpl() { - windowHandle=0; - surfaceHandle=0; + protected void invalidateImpl() { + if(0 != surfaceHandle) { + throw new NativeWindowException("didn't release surface Handle: "+this); + } + windowHandle = 0; + // surfaceHandle = 0; + } + + /** + * {@inheritDoc} + * <p> + * Actually the window handle (HWND), since the surfaceHandle (HDC) is derived + * from it at {@link #lockSurface()}. + * </p> + */ + @Override + public final void setSurfaceHandle(long surfaceHandle) { + this.windowHandle = surfaceHandle; + } + + /** + * Sets the window handle (HWND). + */ + public final void setWindowHandle(long windowHandle) { + this.windowHandle = windowHandle; + } + + public final long getWindowHandle() { + return windowHandle; } @Override final protected int lockSurfaceImpl() { + if (0 == windowHandle) { + throw new NativeWindowException("null window handle: "+this); + } if (0 != surfaceHandle) { throw new InternalError("surface not released"); } @@ -89,12 +117,15 @@ public class GDISurface extends ProxySurface { @Override final public String toString() { - return "GDISurface[config "+getPrivateGraphicsConfiguration()+ + final UpstreamSurfaceHook ush = getUpstreamSurfaceHook(); + final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil"; + return getClass().getSimpleName()+"[config "+getPrivateGraphicsConfiguration()+ ", displayHandle 0x"+Long.toHexString(getDisplayHandle())+ ", windowHandle 0x"+Long.toHexString(windowHandle)+ ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+ ", size "+getWidth()+"x"+getHeight()+ - ", surfaceLock "+surfaceLock+"]"; + ", surfaceLock "+surfaceLock+ + ", upstreamSurfaceHook "+ush_s+"]"; } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java index 070f87216..b11dd1df1 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11GraphicsConfigurationFactory.java @@ -39,33 +39,39 @@ import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.VisualIDHolder; import com.jogamp.nativewindow.x11.X11GraphicsConfiguration; import com.jogamp.nativewindow.x11.X11GraphicsScreen; public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactory { public static void registerFactory() { - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, new X11GraphicsConfigurationFactory()); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class, new X11GraphicsConfigurationFactory()); } private X11GraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( - CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen) + CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen screen, int nativeVisualID) throws IllegalArgumentException, NativeWindowException { if(!(screen instanceof X11GraphicsScreen)) { throw new NativeWindowException("Only valid X11GraphicsScreen are allowed"); } - final X11Capabilities x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, capsChosen)); - AbstractGraphicsConfiguration res = new X11GraphicsConfiguration((X11GraphicsScreen)screen, x11CapsChosen, capsRequested, x11CapsChosen.getXVisualInfo()); + final X11Capabilities x11CapsChosen; + if(VisualIDHolder.VID_UNDEFINED == nativeVisualID) { + x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, capsChosen)); + } else { + x11CapsChosen = new X11Capabilities(getXVisualInfo(screen, nativeVisualID)); + } + final AbstractGraphicsConfiguration res = new X11GraphicsConfiguration((X11GraphicsScreen)screen, x11CapsChosen, capsRequested, x11CapsChosen.getXVisualInfo()); if(DEBUG) { - System.err.println("X11GraphicsConfigurationFactory.chooseGraphicsConfigurationImpl("+screen+","+capsChosen+"): "+res); + System.err.println("X11GraphicsConfigurationFactory.chooseGraphicsConfigurationImpl(visualID 0x"+Integer.toHexString(nativeVisualID)+", "+screen+","+capsChosen+"): "+res); } return res; } - public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, long visualID) + public static XVisualInfo getXVisualInfo(AbstractGraphicsScreen screen, int visualID) { XVisualInfo xvi_temp = XVisualInfo.create(); xvi_temp.setVisualid(visualID); diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java index fcc374751..7b46a1df0 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java @@ -255,7 +255,7 @@ public class X11Util { */ public static int shutdown(boolean realXCloseOpenAndPendingDisplays, boolean verbose) { int num=0; - if(DEBUG||verbose||pendingDisplayList.size() > 0) { + if(DEBUG || verbose || openDisplayMap.size() > 0 || pendingDisplayList.size() > 0) { System.err.println("X11Util.Display: Shutdown (close open / pending Displays: "+realXCloseOpenAndPendingDisplays+ ", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+ ", pending (not closed, marked uncloseable): "+pendingDisplayList.size()+")"); diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java index b6bf63d44..1de03e8be 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/awt/X11AWTGraphicsConfigurationFactory.java @@ -61,14 +61,14 @@ import jogamp.nativewindow.x11.X11Util; public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFactory { public static void registerFactory() { - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new X11AWTGraphicsConfigurationFactory()); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, CapabilitiesImmutable.class, new X11AWTGraphicsConfigurationFactory()); } private X11AWTGraphicsConfigurationFactory() { } protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) { if (absScreen != null && !(absScreen instanceof AWTGraphicsScreen)) { throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects"); @@ -77,18 +77,18 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac absScreen = AWTGraphicsScreen.createDefault(); } - return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, (AWTGraphicsScreen)absScreen); + return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, (AWTGraphicsScreen)absScreen, nativeVisualID); } public static AWTGraphicsConfiguration chooseGraphicsConfigurationStatic( CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AWTGraphicsScreen awtScreen) { + CapabilitiesChooser chooser, AWTGraphicsScreen awtScreen, int nativeVisualID) { if(DEBUG) { System.err.println("X11AWTGraphicsConfigurationFactory: got "+awtScreen); } final GraphicsDevice device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); - + final long displayHandleAWT = X11SunJDKReflection.graphicsDeviceGetDisplay(device); final long displayHandle; boolean owner = false; @@ -121,8 +121,8 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac System.err.println("X11AWTGraphicsConfigurationFactory: made "+x11Screen); } - final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(x11Device); - AbstractGraphicsConfiguration aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(x11Device, capsChosen); + AbstractGraphicsConfiguration aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen, nativeVisualID); if (aConfig == null) { throw new NativeWindowException("Unable to choose a GraphicsConfiguration (1): "+capsChosen+",\n\t"+chooser+"\n\t"+x11Screen); } @@ -160,7 +160,7 @@ public class X11AWTGraphicsConfigurationFactory extends GraphicsConfigurationFac // try again using an AWT Colormodel compatible configuration GraphicsConfiguration gc = device.getDefaultConfiguration(); capsChosen = AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capsChosen, gc); - aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen); + aConfig = factory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, x11Screen, nativeVisualID); if (aConfig == null) { throw new NativeWindowException("Unable to choose a GraphicsConfiguration (2): "+capsChosen+",\n\t"+chooser+"\n\t"+x11Screen); } |