diff options
20 files changed, 589 insertions, 272 deletions
diff --git a/make/config/jogl/egl-CustomJavaCode.java b/make/config/jogl/egl-CustomJavaCode.java index 15689b5d8..4cc486fd4 100644 --- a/make/config/jogl/egl-CustomJavaCode.java +++ b/make/config/jogl/egl-CustomJavaCode.java @@ -1,6 +1,6 @@ private static EGLProcAddressTable _table = new EGLProcAddressTable(new GLProcAddressResolver()); - public static void resetProcAddressTable(DynamicLookupHelper lookup) { + static void resetProcAddressTable(DynamicLookupHelper lookup) { _table.reset(lookup); } @@ -12,7 +12,7 @@ public static final int EGL_DONT_CARE = -1; public static final int EGL_UNKNOWN = -1; - protected static long eglGetProcAddress(long eglGetProcAddressHandle, java.lang.String procname) + static long eglGetProcAddress(long eglGetProcAddressHandle, java.lang.String procname) { if (eglGetProcAddressHandle == 0) { throw new GLException("Passed null pointer for method \"eglGetProcAddress\""); diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index d7868c6dd..e3382e5b0 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -381,8 +381,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook); /** - * A dummy surface is not visible on screen and will not be used to render directly to, - * it maybe on- or offscreen. + * A dummy surface is not visible on screen, it may be on- or offscreen. * <p> * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. * It also allows creation of framebuffer objects which are used for rendering or using a shared GLContext w/o actually rendering to a usable framebuffer. @@ -410,8 +409,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } /** - * A dummy surface is not visible on screen and will not be used to render directly to, - * it maybe on- or offscreen. + * A dummy surface is not visible on screen and may be on- or offscreen. * <p> * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. * It also allows creation of framebuffer objects which are used for rendering or using a shared GLContext w/o actually rendering to a usable framebuffer. @@ -431,6 +429,27 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice, GLCapabilitiesImmutable chosenCaps, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height); + /** + * A surfaceless {@link ProxySurface} is a non-existing surface and will not be used as a render target. + * <p> + * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} w/o default framebuffer to query information. + * It also allows creation of framebuffer objects which are used for rendering or using a shared GLContext w/o actually rendering to a usable framebuffer. + * </p> + * @param device a valid platform dependent target device. + * @param createNewDevice if <code>true</code> a new device instance is created using <code>device</code> details, + * otherwise <code>device</code> instance is used as-is. + * @param chosenCaps + * @param requestedCaps + * @param chooser the custom chooser, may be null for default + * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()}, not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()}, not the actual dummy surface height, + * The latter is platform specific and small + * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}. + */ + public abstract ProxySurface createSurfacelessImpl(AbstractGraphicsDevice device, boolean createNewDevice, + GLCapabilitiesImmutable chosenCaps, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height); + //--------------------------------------------------------------------------- // // ProxySurface (Wrapped pre-existing native surface) construction diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java index 9499c70f4..98ecbbe51 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java @@ -38,7 +38,10 @@ import javax.media.nativewindow.ToolkitLock; import javax.media.opengl.GLException; import jogamp.opengl.Debug; +import jogamp.opengl.egl.EGL; +import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.LongObjectHashMap; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; @@ -148,7 +151,7 @@ public class EGLDisplayUtil { if(DEBUG || verbose || openEGLDisplays.size() > 0 ) { System.err.println("EGLDisplayUtil.EGLDisplays: Shutdown (open: "+openEGLDisplays.size()+")"); if(DEBUG) { - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } if( openEGLDisplays.size() > 0) { dumpOpenDisplayConnections(); @@ -198,17 +201,30 @@ public class EGLDisplayUtil { * * @see EGL#eglInitialize(long, IntBuffer, IntBuffer) */ - private static synchronized boolean eglInitialize(final long eglDisplay, final IntBuffer major, final IntBuffer minor) { + private static synchronized boolean eglInitialize(final long eglDisplay, final int[] major, final int[] minor) { if( EGL.EGL_NO_DISPLAY == eglDisplay) { return false; } - final EGLDisplayRef d = EGLDisplayRef.getOrCreateOpened(eglDisplay, major, minor); + final EGLDisplayRef d = EGLDisplayRef.getOrCreateOpened(eglDisplay, _eglMajorVersion, _eglMinorVersion); + final int _major = _eglMajorVersion.get(0); + final int _minor = _eglMinorVersion.get(0); + if( null != major && null != minor ) { + if( null != d ) { + major[0] = _major; + minor[0] = _minor; + } else { + major[0] = 0; + minor[0] = 0; + } + } if(DEBUG) { - System.err.println("EGLDisplayUtil.eglInitialize("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+(null != d)+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")"); + System.err.println("EGLDisplayUtil.eglInitialize("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+(null != d)+", eglVersion "+_major+"."+_minor+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")"); // Thread.dumpStack(); } return null != d; } + private static final IntBuffer _eglMajorVersion = Buffers.newDirectIntBuffer(1); + private static final IntBuffer _eglMinorVersion = Buffers.newDirectIntBuffer(1); /** * @param nativeDisplayID @@ -222,7 +238,7 @@ public class EGLDisplayUtil { * @see #eglGetDisplay(long) * @see #eglInitialize(long, IntBuffer, IntBuffer) */ - private static synchronized int eglGetDisplayAndInitialize(final long nativeDisplayID, final long[] eglDisplay, final int[] eglErr, final IntBuffer major, final IntBuffer minor) { + private static synchronized int eglGetDisplayAndInitialize(final long nativeDisplayID, final long[] eglDisplay, final int[] eglErr, final int[] major, final int[] minor) { eglDisplay[0] = EGL.EGL_NO_DISPLAY; final long _eglDisplay = eglGetDisplay( nativeDisplayID ); if ( EGL.EGL_NO_DISPLAY == _eglDisplay ) { @@ -244,13 +260,15 @@ public class EGLDisplayUtil { * * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails incl fallback * @param nativeDisplayID in/out array of size 1, passing the requested nativeVisualID, may return a different revised nativeVisualID handle + * @param major + * @param minor * @return the initialized EGL display ID * @throws GLException if not successful */ - private static synchronized long eglGetDisplayAndInitialize(final long[] nativeDisplayID) { + private static synchronized long eglGetDisplayAndInitialize(final long[] nativeDisplayID, final int[] major, final int[] minor) { final long[] eglDisplay = new long[1]; final int[] eglError = new int[1]; - int eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(nativeDisplayID[0], eglDisplay, eglError, null, null); + int eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(nativeDisplayID[0], eglDisplay, eglError, major, minor); if( EGL.EGL_SUCCESS == eglRes ) { return eglDisplay[0]; } @@ -258,7 +276,7 @@ public class EGLDisplayUtil { if(DEBUG) { System.err.println("EGLDisplayUtil.eglGetAndInitDisplay failed with native "+EGLContext.toHexString(nativeDisplayID[0])+", error "+EGLContext.toHexString(eglRes)+"/"+EGLContext.toHexString(eglError[0])+" - fallback!"); } - eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(EGL.EGL_DEFAULT_DISPLAY, eglDisplay, eglError, null, null); + eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(EGL.EGL_DEFAULT_DISPLAY, eglDisplay, eglError, major, minor); if( EGL.EGL_SUCCESS == eglRes ) { nativeDisplayID[0] = EGL.EGL_DEFAULT_DISPLAY; return eglDisplay[0]; @@ -286,8 +304,8 @@ public class EGLDisplayUtil { private static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() { @Override - public long eglGetAndInitDisplay(final long[] nativeDisplayID) { - return eglGetDisplayAndInitialize(nativeDisplayID); + public long eglGetAndInitDisplay(final long[] nativeDisplayID, final int[] major, final int[] minor) { + return eglGetDisplayAndInitialize(nativeDisplayID, major, minor); } @Override public void eglTerminate(final long eglDisplayHandle) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index bacf9f18e..0cd686c5b 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -36,114 +36,66 @@ package jogamp.opengl.egl; -import java.nio.IntBuffer; - -import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.ProxySurface; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; +import jogamp.nativewindow.ProxySurfaceImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.egl.EGL; -import com.jogamp.common.nio.Buffers; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; -public abstract class EGLDrawable extends GLDrawableImpl { +public class EGLDrawable extends GLDrawableImpl { + static boolean DEBUG = GLDrawableImpl.DEBUG; - protected EGLDrawable(final EGLDrawableFactory factory, final NativeSurface component) throws GLException { + protected EGLDrawable(final EGLDrawableFactory factory, final EGLSurface component) throws GLException { super(factory, component, false); } @Override - public abstract GLContext createContext(GLContext shareWith); - - protected abstract long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle); - - private final long createEGLSurface() { - final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; - final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) eglws.getGraphicsConfiguration(); - final NativeSurface upstreamSurface = eglws.getUpstreamSurface(); - - long eglSurface = createSurface(eglConfig, eglws.getSurfaceWidth(), eglws.getSurfaceHeight(), upstreamSurface.getSurfaceHandle()); - - int eglError0; - if (EGL.EGL_NO_SURFACE == eglSurface) { - eglError0 = EGL.eglGetError(); - if(EGL.EGL_BAD_NATIVE_WINDOW == eglError0) { - // Try window handle if available and differs (Windows HDC / HWND). - // ANGLE impl. required HWND on Windows. - if(upstreamSurface instanceof NativeWindow) { - final NativeWindow nw = (NativeWindow) upstreamSurface; - if(nw.getWindowHandle() != nw.getSurfaceHandle()) { - if(DEBUG) { - System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle"); - } - eglSurface = createSurface(eglConfig, eglws.getSurfaceWidth(), eglws.getSurfaceHeight(), nw.getWindowHandle()); - if (EGL.EGL_NO_SURFACE == eglSurface) { - eglError0 = EGL.eglGetError(); - } - } - } - } - } else { - eglError0 = EGL.EGL_SUCCESS; - } - if (EGL.EGL_NO_SURFACE == eglSurface) { - throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0)); - } - if(DEBUG) { - System.err.println(getThreadName() + ": createEGLSurface handle "+toHexString(eglSurface)); - } - return eglSurface; + public final GLContext createContext(final GLContext shareWith) { + return new EGLContext(this, shareWith); } @Override protected final void createHandle() { - final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + final EGLSurface eglSurf = (EGLSurface) surface; if(DEBUG) { - System.err.println(getThreadName() + ": createHandle of "+eglws); + System.err.println(getThreadName() + ": createHandle of "+eglSurf); + ProxySurfaceImpl.dumpHierarchy(System.err, eglSurf); } - if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { - if( EGL.EGL_NO_SURFACE != eglws.getSurfaceHandle() ) { - throw new InternalError("Set surface but claimed to be invalid: "+eglws); + if( eglSurf.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( EGL.EGL_NO_SURFACE != eglSurf.getSurfaceHandle() ) { + throw new InternalError("Set surface but claimed to be invalid: "+eglSurf); + } + if( !eglSurf.containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS ) ) { + eglSurf.setEGLSurfaceHandle(); } - eglws.setSurfaceHandle( createEGLSurface() ); - } else if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) { - throw new InternalError("Nil surface but claimed to be valid: "+eglws); + } else if( EGL.EGL_NO_SURFACE == eglSurf.getSurfaceHandle() ) { + throw new InternalError("Nil surface but claimed to be valid: "+eglSurf); } } @Override protected void destroyHandle() { - final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + final EGLSurface eglSurf = (EGLSurface) surface; + final long eglSurfHandle = eglSurf.getSurfaceHandle(); if(DEBUG) { - System.err.println(getThreadName() + ": destroyHandle of "+eglws); + System.err.println(getThreadName() + ": destroyHandle of "+eglSurf); } - if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) { - throw new InternalError("Nil surface but claimed to be valid: "+eglws); - } - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglws.getGraphicsConfiguration().getScreen().getDevice(); - if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { - EGL.eglDestroySurface(eglDevice.getHandle(), eglws.getSurfaceHandle()); - eglws.setSurfaceHandle(EGL.EGL_NO_SURFACE); - } - } - - protected static boolean isValidEGLSurface(final long eglDisplayHandle, final long surfaceHandle) { - if( 0 == surfaceHandle ) { - return false; + if( !eglSurf.containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS ) && + EGL.EGL_NO_SURFACE == eglSurfHandle ) { + throw new InternalError("Nil surface but claimed to be valid: "+eglSurf); } - final IntBuffer val = Buffers.newDirectIntBuffer(1); - final boolean eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surfaceHandle, EGL.EGL_CONFIG_ID, val); - if( !eglSurfaceValid ) { - final int eglErr = EGL.eglGetError(); - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.isValidEGLSurface eglQuerySuface failed: error "+toHexString(eglErr)+", "+toHexString(surfaceHandle)); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglSurf.getGraphicsConfiguration().getScreen().getDevice(); + if( eglSurf.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( EGL.EGL_NO_SURFACE != eglSurfHandle ) { + EGL.eglDestroySurface(eglDevice.getHandle(), eglSurfHandle); + eglSurf.setSurfaceHandle(EGL.EGL_NO_SURFACE); } } - return eglSurfaceValid; } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index 2edb22314..beac4aa12 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -66,7 +66,6 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import jogamp.common.os.PlatformPropsImpl; -import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableFactoryImpl; @@ -74,12 +73,15 @@ import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.SharedResourceRunner; +import jogamp.opengl.egl.EGL; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.common.os.Platform; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.common.util.VersionNumber; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; import com.jogamp.opengl.GLRendererQuirks; @@ -723,7 +725,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - return new EGLOnscreenDrawable(this, EGLWrappedSurface.get(target)); + return new EGLDrawable(this, EGLSurface.get(target)); } @Override @@ -737,7 +739,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { throw new GLException("Non pbuffer not yet implemented"); } // PBuffer GLDrawable Creation - return new EGLPbufferDrawable(this, EGLWrappedSurface.get(target)); + return new EGLDrawable(this, EGLSurface.get(target)); } @Override @@ -747,28 +749,35 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return true; } - @Override - protected ProxySurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, - final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested, - final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstreamHook) { - final boolean ownDevice; + private final EGLGraphicsConfiguration evalConfig(final boolean[] ownDevice, final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested, + final GLCapabilitiesChooser chooser) { final EGLGraphicsDevice device; if( createNewDevice || ! (deviceReq instanceof EGLGraphicsDevice) ) { final long nativeDisplayID = ( deviceReq instanceof EGLGraphicsDevice) ? ( (EGLGraphicsDevice) deviceReq ).getNativeDisplayID() : deviceReq.getHandle() ; device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(nativeDisplayID, deviceReq.getConnection(), deviceReq.getUnitID()); device.open(); - ownDevice = true; + ownDevice[0] = true; } else { device = (EGLGraphicsDevice) deviceReq; - ownDevice = false; + ownDevice[0] = false; } final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } - return new WrappedSurface(config, 0, upstreamHook, ownDevice); + return config; + } + + @Override + protected final ProxySurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested, + final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstreamHook) { + final boolean[] ownDevice = { false }; + final EGLGraphicsConfiguration config = evalConfig(ownDevice, deviceReq, createNewDevice, capsChosen, capsRequested, chooser); + return EGLSurface.createWrapped(config, 0, upstreamHook, ownDevice[0]); } @Override @@ -778,6 +787,15 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new EGLDummyUpstreamSurfaceHook(width, height)); } + @Override + public final ProxySurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) { + chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps); + final boolean[] ownDevice = { false }; + final EGLGraphicsConfiguration config = evalConfig(ownDevice, deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser); + return EGLSurface.createSurfaceless(config, new EGLUpstreamSurfacelessHook(width, height), ownDevice[0]); + } + /** * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface. * It will also hold the resulting pbuffer surface handle. @@ -813,13 +831,15 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) { + protected ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, + final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, + final UpstreamSurfaceHook upstream) { final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); device.open(); final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); - return new WrappedSurface(cfg, windowHandle, upstream, true); + return EGLSurface.createWrapped(cfg, windowHandle, upstream, true); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java deleted file mode 100644 index 4c018fe25..000000000 --- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - * - * Sun gratefully acknowledges that this software was originally authored - * and developed by Kenneth Bradley Russell and Christopher John Kline. - */ - -package jogamp.opengl.egl; - -import javax.media.opengl.*; -import javax.media.nativewindow.*; - -public class EGLOnscreenDrawable extends EGLDrawable { - protected EGLOnscreenDrawable(final EGLDrawableFactory factory, final NativeSurface component) throws GLException { - super(factory, component); - } - - @Override - public GLContext createContext(final GLContext shareWith) { - return new EGLContext(this, shareWith); - } - - @Override - protected long createSurface(final EGLGraphicsConfiguration config, final int width, final int height, final long nativeSurfaceHandle) { - return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), config.getNativeConfig(), nativeSurfaceHandle, null); - } -} - diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java deleted file mode 100644 index 8842edbc0..000000000 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - * - * Sun gratefully acknowledges that this software was originally authored - * and developed by Kenneth Bradley Russell and Christopher John Kline. - */ - -package jogamp.opengl.egl; - -import javax.media.nativewindow.NativeSurface; -import javax.media.opengl.GLContext; - -public class EGLPbufferDrawable extends EGLDrawable { - protected static final boolean useTexture = false; // No yet .. - - protected EGLPbufferDrawable(final EGLDrawableFactory factory, final NativeSurface target) { - super(factory, target); - } - - @Override - protected long createSurface(final EGLGraphicsConfiguration config, final int width, final int height, final long nativeSurfaceHandle) { - return EGLDrawableFactory.createPBufferSurfaceImpl(config, width, height, false); - } - - @Override - public GLContext createContext(final GLContext shareWith) { - return new EGLContext(this, shareWith); - } -} - diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLSurface.java new file mode 100644 index 000000000..d00656a34 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLSurface.java @@ -0,0 +1,164 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.opengl.egl; + +import java.nio.IntBuffer; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLException; + +import com.jogamp.common.nio.Buffers; + +import jogamp.nativewindow.ProxySurfaceImpl; +import jogamp.nativewindow.WrappedSurface; +import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.egl.EGL; + +/** + * <pre> + * EGLSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a + * EGLUpstreamSurfaceHook [ is_a -> UpstreamSurfaceHook.MutableSize -> UpstreamSurfaceHook ] has_a + * NativeSurface (e.g. native [X11, WGL, ..] surface, or WrappedSurface, ..) + * </pre> + */ +public class EGLSurface extends WrappedSurface { + static boolean DEBUG = EGLDrawable.DEBUG || ProxySurface.DEBUG; + + public static EGLSurface get(final NativeSurface surface) { + if(surface instanceof EGLSurface) { + return (EGLSurface)surface; + } + return new EGLSurface(surface); + } + private EGLSurface(final NativeSurface surface) { + super(surface.getGraphicsConfiguration(), EGL.EGL_NO_SURFACE, new EGLUpstreamSurfaceHook(surface), false /* tbd in UpstreamSurfaceHook */); + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLSurface.ctor().1: "+this); + ProxySurfaceImpl.dumpHierarchy(System.err, this); + } + } + + public static EGLSurface createWrapped(final EGLGraphicsConfiguration cfg, final long handle, + final UpstreamSurfaceHook upstream, final boolean ownsDevice) { + return new EGLSurface(cfg, handle, upstream, ownsDevice); + } + private EGLSurface(final EGLGraphicsConfiguration cfg, final long handle, + final UpstreamSurfaceHook upstream, final boolean ownsDevice) { + super(cfg, EGL.EGL_NO_SURFACE, new EGLUpstreamSurfaceHook(cfg, handle, upstream, ownsDevice), false /* tbd in UpstreamSurfaceHook */); + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLSurface.ctor().2: "+this); + ProxySurfaceImpl.dumpHierarchy(System.err, this); + } + } + + public static EGLSurface createSurfaceless(final EGLGraphicsConfiguration cfg, final EGLUpstreamSurfacelessHook upstream, final boolean ownsDevice) { + return new EGLSurface(cfg, upstream, ownsDevice); + } + private EGLSurface(final EGLGraphicsConfiguration cfg, final EGLUpstreamSurfacelessHook upstream, final boolean ownsDevice) { + super(cfg, EGL.EGL_NO_SURFACE, upstream, ownsDevice); + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLSurface.ctor().3: "+this); + ProxySurfaceImpl.dumpHierarchy(System.err, this); + } + } + + public void setEGLSurfaceHandle() throws GLException { + setSurfaceHandle( createEGLSurfaceHandle() ); + } + private long createEGLSurfaceHandle() throws GLException { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) getGraphicsConfiguration(); + final NativeSurface nativeSurface = getUpstreamSurface(); + final boolean isPBuffer = ((GLCapabilitiesImmutable) config.getChosenCapabilities()).isPBuffer(); + + long eglSurface = createEGLSurfaceHandle(isPBuffer, true /* useSurfaceHandle */, config, nativeSurface); + if ( EGL.EGL_NO_SURFACE == eglSurface ) { + final int eglError0 = EGL.eglGetError(); + if( EGL.EGL_BAD_NATIVE_WINDOW == eglError0 && !isPBuffer ) { + // Try window handle if available and differs (Windows HDC / HWND). + // ANGLE impl. required HWND on Windows. + if( hasUniqueNativeWindowHandle(nativeSurface) ) { + if(DEBUG) { + System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+config+", error "+GLDrawableImpl.toHexString(eglError0)+", retry w/ windowHandle"); + } + eglSurface = createEGLSurfaceHandle(isPBuffer, false /* useSurfaceHandle */, config, nativeSurface); + if (EGL.EGL_NO_SURFACE == eglSurface) { + throw new GLException("Creation of window surface w/ window handle failed: "+config+", "+this+", error "+GLDrawableImpl.toHexString(EGL.eglGetError())); + } + } else { + throw new GLException("Creation of window surface w/ surface handle failed (2): "+config+", "+this+", error "+GLDrawableImpl.toHexString(eglError0)); + } + } else { + throw new GLException("Creation of window surface w/ surface handle failed (1): "+config+", "+this+", error "+GLDrawableImpl.toHexString(eglError0)); + } + } + if(DEBUG) { + System.err.println(getThreadName() + ": createEGLSurface handle "+GLDrawableImpl.toHexString(eglSurface)); + } + return eglSurface; + } + private long createEGLSurfaceHandle(final boolean isPBuffer, final boolean useSurfaceHandle, + final EGLGraphicsConfiguration config, final NativeSurface nativeSurface) { + if( isPBuffer ) { + return EGLDrawableFactory.createPBufferSurfaceImpl(config, getSurfaceWidth(), getSurfaceHeight(), false); + } else { + if( useSurfaceHandle ) { + return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), + config.getNativeConfig(), + nativeSurface.getSurfaceHandle(), null); + } else { + return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), + config.getNativeConfig(), + ((NativeWindow)nativeSurface).getWindowHandle(), null); + } + } + } + private static boolean hasUniqueNativeWindowHandle(final NativeSurface nativeSurface) { + return nativeSurface instanceof NativeWindow && + ((NativeWindow)nativeSurface).getWindowHandle() != nativeSurface.getSurfaceHandle(); + } + static String getThreadName() { return Thread.currentThread().getName(); } + + public static boolean isValidEGLSurfaceHandle(final long eglDisplayHandle, final long eglSurfaceHandle) { + if( 0 == eglSurfaceHandle ) { + return false; + } + final IntBuffer val = Buffers.newDirectIntBuffer(1); + final boolean eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, eglSurfaceHandle, EGL.EGL_CONFIG_ID, val); + if( !eglSurfaceValid ) { + final int eglErr = EGL.eglGetError(); + if(DEBUG) { + System.err.println(getThreadName() + ": EGLSurface.isValidEGLSurfaceHandle eglQuerySuface failed: error "+GLDrawableImpl.toHexString(eglErr)+", "+GLDrawableImpl.toHexString(eglSurfaceHandle)); + } + } + return eglSurfaceValid; + } +} diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java index cc15f0cd6..694f2d30d 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java @@ -1,3 +1,30 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ package jogamp.opengl.egl; import javax.media.nativewindow.AbstractGraphicsConfiguration; @@ -11,13 +38,15 @@ import javax.media.nativewindow.VisualIDHolder.VIDType; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLException; +import jogamp.nativewindow.WrappedSurface; + import com.jogamp.nativewindow.egl.EGLGraphicsDevice; /** * <pre> - * EGLWrappedSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a + * EGLSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a * EGLUpstreamSurfaceHook [ is_a -> UpstreamSurfaceHook.MutableSize -> UpstreamSurfaceHook ] has_a - * NativeSurface (e.g. native X11 surface) + * NativeSurface (e.g. native [X11, WGL, ..] surface, or WrappedSurface, ..) * </pre> */ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize { @@ -40,6 +69,11 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize { } } + public EGLUpstreamSurfaceHook(final EGLGraphicsConfiguration cfg, final long handle, + final UpstreamSurfaceHook upstream, final boolean ownsDevice) { + this( new WrappedSurface(cfg, handle, upstream, ownsDevice) ); + } + static String getThreadName() { return Thread.currentThread().getName(); } /** @@ -176,10 +210,10 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize { } surface.setGraphicsConfiguration(eglConfig); - if(isEGLSurfaceValid) { - isEGLSurfaceValid = EGLDrawable.isValidEGLSurface(eglDevice.getHandle(), upstreamSurface.getSurfaceHandle()); + if( isEGLSurfaceValid ) { + isEGLSurfaceValid = EGLSurface.isValidEGLSurfaceHandle(eglDevice.getHandle(), upstreamSurface.getSurfaceHandle()); } - if(isEGLSurfaceValid) { + if( isEGLSurfaceValid ) { surface.setSurfaceHandle(upstreamSurface.getSurfaceHandle()); surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); if(DEBUG) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfacelessHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfacelessHook.java new file mode 100644 index 000000000..40629d7da --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfacelessHook.java @@ -0,0 +1,90 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.opengl.egl; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import jogamp.opengl.egl.EGL; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; + +public class EGLUpstreamSurfacelessHook extends UpstreamSurfaceHookMutableSize { + /** + * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public EGLUpstreamSurfacelessHook(final int width, final int height) { + super(width, height); + } + + @Override + public final void create(final ProxySurface s) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + eglDevice.lock(); + try { + if(0 == eglDevice.getHandle()) { + eglDevice.open(); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + if( EGL.EGL_NO_SURFACE != s.getSurfaceHandle() ) { + throw new InternalError("Upstream surface not null: "+s); + } + s.addUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS | + ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE | + ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE ); + } finally { + eglDevice.unlock(); + } + } + + @Override + public final void destroy(final ProxySurface s) { + if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if( !s.containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS ) ) { + throw new InternalError("Owns upstream surface, but not a valid zero surface: "+s); + } + if( EGL.EGL_NO_SURFACE != s.getSurfaceHandle() ) { + throw new InternalError("Owns upstream valid zero surface, but non zero surface: "+s); + } + eglDevice.lock(); + try { + s.clearUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS | ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } finally { + eglDevice.unlock(); + } + } + } +} diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java deleted file mode 100644 index 89024eed3..000000000 --- a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java +++ /dev/null @@ -1,30 +0,0 @@ -package jogamp.opengl.egl; - -import javax.media.nativewindow.NativeSurface; - -import jogamp.nativewindow.WrappedSurface; - -/** - * <pre> - * EGLWrappedSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a - * EGLUpstreamSurfaceHook [ is_a -> UpstreamSurfaceHook.MutableSize -> UpstreamSurfaceHook ] has_a - * NativeSurface (i.e. native X11 surface) - * </pre> - */ -public class EGLWrappedSurface extends WrappedSurface { - - public static EGLWrappedSurface get(final NativeSurface surface) { - if(surface instanceof EGLWrappedSurface) { - return (EGLWrappedSurface)surface; - } - return new EGLWrappedSurface(surface); - } - - public EGLWrappedSurface(final NativeSurface surface) { - super(surface.getGraphicsConfiguration(), EGL.EGL_NO_SURFACE, new EGLUpstreamSurfaceHook(surface), false /* tbd in UpstreamSurfaceHook */); - if(EGLDrawableFactory.DEBUG) { - System.err.println("EGLWrappedSurface.ctor(): "+this); - } - } - -} diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index 045abca4c..4bde5b6ae 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -373,6 +373,12 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } @Override + public final ProxySurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + final GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) { + throw new UnsupportedOperationException("TODO"); + } + + @Override protected ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) { final MacOSXGraphicsDevice device = new MacOSXGraphicsDevice(deviceReq.getUnitID()); final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index fa052d784..c15fe0414 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -555,6 +555,12 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } @Override + public final ProxySurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + final GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) { + throw new UnsupportedOperationException("TODO"); + } + + @Override protected final ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) { final WindowsGraphicsDevice device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID()); final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index 65cb3c31d..8f614a326 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -525,6 +525,13 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } @Override + public final ProxySurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) { + chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new X11UpstreamSurfacelessHook(width, height)); + } + + @Override protected final ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) { final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), true /* owner */); final X11GraphicsScreen screen = new X11GraphicsScreen(device, screenIdx); diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java index d21994ea5..a38a48b85 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java @@ -34,11 +34,14 @@ package com.jogamp.nativewindow.egl; import javax.media.nativewindow.*; +import com.jogamp.common.util.VersionNumber; + /** Encapsulates a graphics device on EGL platforms. */ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneable { - final long[] nativeDisplayID = new long[1]; - /* final */ EGLDisplayLifecycleCallback eglLifecycleCallback; + private final long[] nativeDisplayID = new long[1]; + private /* final */ EGLDisplayLifecycleCallback eglLifecycleCallback; + private VersionNumber eglVersion = VersionNumber.zeroVersion; /** * Hack to allow inject a EGL termination call. @@ -52,9 +55,11 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl * Implementation should issue an <code>EGL.eglGetDisplay(nativeDisplayID)</code> * inclusive <code>EGL.eglInitialize(eglDisplayHandle, ..)</code> call. * @param nativeDisplayID in/out array of size 1, passing the requested nativeVisualID, may return a different revised nativeVisualID handle + * @param major out array for EGL major version + * @param minor out array for EGL minor version * @return the initialized EGL display ID, or <code>0</code> if not successful */ - public long eglGetAndInitDisplay(long[] nativeDisplayID); + public long eglGetAndInitDisplay(final long[] nativeDisplayID, final int[] major, final int[] minor); /** * Implementation should issue an <code>EGL.eglTerminate(eglDisplayHandle)</code> call. @@ -79,6 +84,9 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl this.eglLifecycleCallback = eglLifecycleCallback; } + /** EGL server version as returned by {@code eglInitialize(..)}. Only valid after {@link #open()}. */ + public VersionNumber getEGLVersion() { return eglVersion; } + public long getNativeDisplayID() { return nativeDisplayID[0]; } @Override @@ -98,11 +106,16 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl if(DEBUG) { System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.open(): "+this); } - handle = eglLifecycleCallback.eglGetAndInitDisplay(nativeDisplayID); + final int[] major = { 0 }; + final int[] minor = { 0 }; + handle = eglLifecycleCallback.eglGetAndInitDisplay(nativeDisplayID, major, minor); if(0 == handle) { + eglVersion = VersionNumber.zeroVersion; throw new NativeWindowException("EGLGraphicsDevice.open() failed: "+this); + } else { + eglVersion = new VersionNumber(major[0], minor[0], 0); + return true; } - return true; } return false; } @@ -142,5 +155,10 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl eglLifecycleCallback = (EGLDisplayLifecycleCallback) newOwnership; return oldOwnership; } + + @Override + public String toString() { + return getClass().getSimpleName()+"[type "+getType()+", v"+eglVersion+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", owner "+isHandleOwner()+", "+toolkitLock+"]"; + } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java index 7a69b9a40..377dd55cd 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java @@ -65,6 +65,14 @@ public interface ProxySurface extends MutableSurface { */ public static final int OPT_UPSTREAM_WINDOW_INVISIBLE = 1 << 8; + /** + * Implementation specific bitvalue stating the upstream's {@link NativeSurface}'s zero handle is valid. + * @see #addUpstreamOptionBits(int) + * @see #clearUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() + */ + public static final int OPT_UPSTREAM_SURFACELESS = 1 << 9; + /** Allow redefining the AbstractGraphicsConfiguration */ public void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg); diff --git a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java index deb685b51..10d957186 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java +++ b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java @@ -28,6 +28,8 @@ package jogamp.nativewindow; +import java.io.PrintStream; + import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; @@ -279,6 +281,13 @@ public abstract class ProxySurfaceImpl implements ProxySurface { sink.append("WINDOW_INVISIBLE"); needsOr = true; } + if( 0 != ( implBitfield & OPT_UPSTREAM_SURFACELESS ) ) { + if(needsOr) { + sink.append(" | "); + } + sink.append("SURFACELESS"); + needsOr = true; + } sink.append(" ]"); return sink; } @@ -297,6 +306,34 @@ public abstract class ProxySurfaceImpl implements ProxySurface { @Override public final void clearUpstreamOptionBits(final int v) { implBitfield &= ~v; } + public static void dumpHierarchy(final PrintStream out, final ProxySurface s) { + out.println("Surface Hierarchy of "+s.getClass().getName()); + dumpHierarchy(out, s, ""); + out.println(); + } + private static void dumpHierarchy(final PrintStream out, final NativeSurface s, String indentation) { + indentation = indentation + " "; + out.println(indentation+"Surface device "+s.getGraphicsConfiguration().getScreen().getDevice()); + out.println(indentation+"Surface size "+s.getSurfaceWidth()+"x"+s.getSurfaceHeight()+", handle 0x"+Long.toHexString(s.getSurfaceHandle())); + if( s instanceof ProxySurfaceImpl ) { + final ProxySurface ps = (ProxySurface)s; + out.println(indentation+"Upstream options "+ps.getUpstreamOptionBits(null).toString()); + + final UpstreamSurfaceHook psUSH = ps.getUpstreamSurfaceHook(); + if( null != psUSH ) { + out.println(indentation+"Upstream Hook "+psUSH.getClass().getName()); + final NativeSurface upstreamSurface = psUSH.getUpstreamSurface(); + indentation = indentation + " "; + if( null != upstreamSurface ) { + out.println(indentation+"Upstream Hook's Surface "+upstreamSurface.getClass().getName()); + dumpHierarchy(out, upstreamSurface, indentation); + } else { + out.println(indentation+"Upstream Hook's Surface NULL"); + } + } + } + } + @Override public StringBuilder toString(StringBuilder sink) { if(null == sink) { diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java index 7e61ba6d0..1b3b207f6 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java @@ -44,7 +44,7 @@ public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize s.setSurfaceHandle(windowHandle); s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); } - s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + s.addUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE ); } finally { device.unlock(); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11UpstreamSurfacelessHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11UpstreamSurfacelessHook.java new file mode 100644 index 000000000..4461f7691 --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11UpstreamSurfacelessHook.java @@ -0,0 +1,92 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.nativewindow.x11; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; +import com.jogamp.nativewindow.x11.X11GraphicsConfiguration; +import com.jogamp.nativewindow.x11.X11GraphicsDevice; +import com.jogamp.nativewindow.x11.X11GraphicsScreen; + +public class X11UpstreamSurfacelessHook extends UpstreamSurfaceHookMutableSize { + /** + * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public X11UpstreamSurfacelessHook(final int width, final int height) { + super(width, height); + } + + @Override + public final void create(final ProxySurface s) { + final X11GraphicsConfiguration cfg = (X11GraphicsConfiguration) s.getGraphicsConfiguration(); + final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen(); + final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice(); + device.lock(); + try { + if(0 == device.getHandle()) { + device.open(); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + if( 0 != s.getSurfaceHandle() ) { + throw new InternalError("Upstream surface not null: "+s); + } + s.addUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS | + ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE | + ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE ); + } finally { + device.unlock(); + } + } + + @Override + public final void destroy(final ProxySurface s) { + if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + final X11GraphicsDevice device = (X11GraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if( !s.containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS ) ) { + throw new InternalError("Owns upstream surface, but not a valid zero surface: "+s); + } + if( 0 != s.getSurfaceHandle() ) { + throw new InternalError("Owns upstream valid zero surface, but non zero surface: "+s); + } + device.lock(); + try { + s.clearUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS | ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } finally { + device.unlock(); + } + } + } +} diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index 749391f1f..a21016402 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -71,7 +71,7 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { setGraphicsConfiguration(cfg); synchronized(OffscreenWindow.class) { - setWindowHandle(nextWindowHandle++); + setWindowHandle(nextWindowHandle++); // just a marker } visibleChanged(false, true); } |