diff options
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/egl')
19 files changed, 2092 insertions, 1150 deletions
diff --git a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java index cddd142e9..7b85c3e75 100644 --- a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java @@ -3,14 +3,14 @@ * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR @@ -20,12 +20,12 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ - + package jogamp.opengl.egl; import java.util.*; @@ -36,8 +36,8 @@ import jogamp.opengl.*; * Implementation of the DynamicLookupHelper for Desktop ES2 (AMD, ..) * where EGL and ES2 functions reside within the desktop OpenGL library. */ -public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo { - static List<String> glueLibNames; +public final class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo { + static final List<String> glueLibNames; static { glueLibNames = new ArrayList<String>(); glueLibNames.add("jogl_mobile"); @@ -47,35 +47,29 @@ public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleIn super(); } - /** - * Might be a desktop GL library, and might need to allow symbol access to subsequent libs. - * - * This respects old DRI requirements:<br> - * <pre> - * http://dri.sourceforge.net/doc/DRIuserguide.html - * </pre> - */ - public boolean shallLinkGlobal() { return true; } - + @Override public final List<String> getToolGetProcAddressFuncNameList() { List<String> res = new ArrayList<String>(); res.add("eglGetProcAddress"); return res; } + @Override public final long toolGetProcAddress(long toolGetProcAddressHandle, String funcName) { return EGL.eglGetProcAddress(toolGetProcAddressHandle, funcName); } + @Override public final boolean useToolGetProcAdressFirst(String funcName) { return true; } - - public List<List<String>> getToolLibNames() { + + @Override + public final List<List<String>> getToolLibNames() { final List<List<String>> libsList = new ArrayList<List<String>>(); final List<String> libsGL = new ArrayList<String>(); - - // Be aware that on DRI systems, eg ATI fglrx, etc, + + // Be aware that on DRI systems, eg ATI fglrx, etc, // you have to set LIBGL_DRIVERS_PATH env variable. // Eg on Ubuntu 64bit systems this is: // export LIBGL_DRIVERS_PATH=/usr/lib/fglrx/dri:/usr/lib32/fglrx/dri @@ -92,15 +86,16 @@ public class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBundleIn // OSX (guess ES2 on OSX will never happen) libsGL.add("/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"); - + // last but not least .. the generic one libsGL.add("GL"); - + libsList.add(libsGL); return libsList; - } - + } + + @Override public final List<String> getGlueLibNames() { return glueLibNames; - } + } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index f5f9f62c4..f89ded4f6 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2011 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -29,7 +29,7 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -42,7 +42,9 @@ import java.util.Map; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; @@ -50,11 +52,12 @@ import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; import com.jogamp.common.nio.Buffers; -import com.jogamp.common.os.Platform; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.GLRendererQuirks; -public abstract class EGLContext extends GLContextImpl { +public class EGLContext extends GLContextImpl { private boolean eglQueryStringInitialized; private boolean eglQueryStringAvailable; private EGLExt _eglExt; @@ -68,14 +71,15 @@ public abstract class EGLContext extends GLContextImpl { } @Override - protected void resetStates() { + protected void resetStates(boolean isInit) { eglQueryStringInitialized = false; eglQueryStringAvailable = false; eglExtProcAddressTable = null; // no inner state _eglExt = null; - super.resetStates(); + super.resetStates(isInit); } - + + @Override public Object getPlatformGLExtensions() { return getEGLExt(); } @@ -87,6 +91,7 @@ public abstract class EGLContext extends GLContextImpl { return _eglExt; } + @Override public final ProcAddressTable getPlatformExtProcAddressTable() { return eglExtProcAddressTable; } @@ -95,75 +100,80 @@ public abstract class EGLContext extends GLContextImpl { return eglExtProcAddressTable; } + @Override protected Map<String, String> getFunctionNameMap() { return null; } + @Override protected Map<String, String> getExtensionNameMap() { return null; } + @Override public final boolean isGLReadDrawableAvailable() { return true; } + @Override protected void makeCurrentImpl() throws GLException { - if(EGL.EGL_NO_DISPLAY==((EGLDrawable)drawable).getDisplay() ) { - throw new GLException("drawable not properly initialized, NO DISPLAY: "+drawable); - } if (EGL.eglGetCurrentContext() != contextHandle) { - if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), - drawable.getHandle(), - drawableRead.getHandle(), - contextHandle)) { - throw new GLException("Error making context 0x" + - Long.toHexString(contextHandle) + " current: error code 0x" + Integer.toHexString(EGL.eglGetError())); + final long dpy = drawable.getNativeSurface().getDisplayHandle(); + if (!EGL.eglMakeCurrent(dpy, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { + throw new GLException("Error making context " + toHexString(contextHandle) + + " current on Thread " + getThreadName() + + " with display " + toHexString(dpy) + + ", drawableWrite " + toHexString(drawable.getHandle()) + + ", drawableRead "+ toHexString(drawableRead.getHandle()) + + " - Error code " + toHexString(EGL.eglGetError()) + ", " + this); } } } + @Override protected void releaseImpl() throws GLException { - if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), - EGL.EGL_NO_SURFACE, - EGL.EGL_NO_SURFACE, - EGL.EGL_NO_CONTEXT)) { - throw new GLException("Error freeing OpenGL context 0x" + - Long.toHexString(contextHandle) + ": error code 0x" + Integer.toHexString(EGL.eglGetError())); + if (!EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT)) { + throw new GLException("Error freeing OpenGL context " + toHexString(contextHandle) + + ": error code " + toHexString(EGL.eglGetError())); } } + @Override protected void destroyImpl() throws GLException { - if (!EGL.eglDestroyContext(((EGLDrawable)drawable).getDisplay(), contextHandle)) { - final int eglError = EGL.eglGetError(); - if(EGL.EGL_SUCCESS != eglError) { /* oops, Mesa EGL impl. may return false, but has no EGL error */ - throw new GLException("Error destroying OpenGL context 0x" + - Long.toHexString(contextHandle) + ": error code 0x" + Integer.toHexString(eglError)); - } - } + destroyContextARBImpl(contextHandle); } + @Override protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { return 0; // FIXME } + @Override protected void destroyContextARBImpl(long _context) { - // FIXME + if (!EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), _context)) { + final int eglError = EGL.eglGetError(); + if(EGL.EGL_SUCCESS != eglError) { /* oops, Mesa EGL impl. may return false, but has no EGL error */ + throw new GLException("Error destroying OpenGL context " + toHexString(_context) + + ": error code " + toHexString(eglError)); + } + } } - protected boolean createImpl(GLContextImpl shareWith) throws GLException { - long eglDisplay = ((EGLDrawable)drawable).getDisplay(); - EGLGraphicsConfiguration config = ((EGLDrawable)drawable).getGraphicsConfiguration(); - GLProfile glProfile = drawable.getGLProfile(); - long eglConfig = config.getNativeConfig(); - long shareWithHandle = EGL.EGL_NO_CONTEXT; - - if (eglDisplay == 0) { + @Override + protected boolean createImpl(final long shareWithHandle) throws GLException { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); + final long eglDisplay = config.getScreen().getDevice().getHandle(); + final GLProfile glProfile = drawable.getGLProfile(); + final long eglConfig = config.getNativeConfig(); + // 0 == EGL.EGL_NO_CONTEXT; + + if ( 0 == eglDisplay ) { throw new GLException("Error: attempted to create an OpenGL context without a display connection"); } - if (eglConfig == 0) { + if ( 0 == eglConfig ) { throw new GLException("Error: attempted to create an OpenGL context without a graphics configuration"); } try { // might be unavailable on EGL < 1.2 - if(!EGL.eglBindAPI(EGL.EGL_OPENGL_ES_API)) { - throw new GLException("Catched: eglBindAPI to ES failed , error 0x"+Integer.toHexString(EGL.eglGetError())); + if( !EGL.eglBindAPI(EGL.EGL_OPENGL_ES_API) ) { + throw new GLException("Catched: eglBindAPI to ES failed , error "+toHexString(EGL.eglGetError())); } } catch (GLException glex) { if (DEBUG) { @@ -171,26 +181,29 @@ public abstract class EGLContext extends GLContextImpl { } } - if (shareWith != null) { - shareWithHandle = shareWith.getHandle(); - if (shareWithHandle == 0) { - throw new GLException("GLContextShareSet returned an invalid OpenGL context"); - } - } + // Cannot check extension 'EGL_KHR_create_context' before having one current! - final IntBuffer contextAttrsNIO; + final IntBuffer contextAttrsNIO; + final int contextVersionReq, contextVersionAttr; { - final int[] contextAttrs = new int[] { - EGL.EGL_CONTEXT_CLIENT_VERSION, -1, - EGL.EGL_NONE - }; - if (glProfile.usesNativeGLES2()) { - contextAttrs[1] = 2; - } else if (glProfile.usesNativeGLES1()) { - contextAttrs[1] = 1; + if ( glProfile.usesNativeGLES3() ) { + contextVersionReq = 3; + if( GLRendererQuirks.existStickyDeviceQuirk( GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) { + contextVersionAttr = 2; + } else { + contextVersionAttr = 3; + } + } else if ( glProfile.usesNativeGLES2() ) { + contextVersionReq = 2; + contextVersionAttr = 2; + } else if ( glProfile.usesNativeGLES1() ) { + contextVersionReq = 1; + contextVersionAttr = 1; } else { throw new GLException("Error creating OpenGL context - invalid GLProfile: "+glProfile); } + // EGLExt.EGL_CONTEXT_MAJOR_VERSION_KHR == EGL.EGL_CONTEXT_CLIENT_VERSION + final int[] contextAttrs = new int[] { EGL.EGL_CONTEXT_CLIENT_VERSION, contextVersionAttr, EGL.EGL_NONE }; contextAttrsNIO = Buffers.newDirectIntBuffer(contextAttrs); } contextHandle = EGL.eglCreateContext(eglDisplay, eglConfig, shareWithHandle, contextAttrsNIO); @@ -200,31 +213,32 @@ public abstract class EGLContext extends GLContextImpl { } if (DEBUG) { System.err.println(getThreadName() + ": Created OpenGL context 0x" + - Long.toHexString(contextHandle) + + Long.toHexString(contextHandle) + ",\n\twrite surface 0x" + Long.toHexString(drawable.getHandle()) + ",\n\tread surface 0x" + Long.toHexString(drawableRead.getHandle())+ ",\n\t"+this+ ",\n\tsharing with 0x" + Long.toHexString(shareWithHandle)); } - if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), - drawable.getHandle(), - drawableRead.getHandle(), - contextHandle)) { - throw new GLException("Error making context 0x" + - Long.toHexString(contextHandle) + " current: error code " + EGL.eglGetError()); + if (!EGL.eglMakeCurrent(eglDisplay, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { + throw new GLException("Error making context " + + toHexString(contextHandle) + " current: error code " + toHexString(EGL.eglGetError())); } - int ctp = CTX_PROFILE_ES; - int major; - if(glProfile.usesNativeGLES2()) { - ctp |= CTX_IMPL_ES2_COMPAT; - major = 2; - } else { - major = 1; + if( !setGLFunctionAvailability(true, contextVersionReq, 0, CTX_PROFILE_ES, + true /* strictMatch */, // always req. strict match + false /* withinGLVersionsMapping */) ) { + if(DEBUG) { + System.err.println(getThreadName() + ": createImpl: setGLFunctionAvailability FAILED delete "+toHexString(contextHandle)); + } + EGL.eglMakeCurrent(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT); + EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), contextHandle); + contextHandle = 0; + return false; + } else { + return true; } - setGLFunctionAvailability(true, major, 0, ctp); - return true; } + @Override protected final void updateGLXProcAddressTable() { final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); @@ -255,17 +269,16 @@ public abstract class EGLContext extends GLContextImpl { } } } - + + @Override protected final StringBuilder getPlatformExtensionsStringImpl() { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); if (!eglQueryStringInitialized) { - eglQueryStringAvailable = - getDrawableImpl().getGLDynamicLookupHelper().dynamicLookupFunction("eglQueryString") != 0; + eglQueryStringAvailable = getDrawableImpl().getGLDynamicLookupHelper().isFunctionAvailable("eglQueryString"); eglQueryStringInitialized = true; } if (eglQueryStringAvailable) { - final String ret = EGL.eglQueryString(((EGLDrawable)drawable).getDisplay(), - EGL.EGL_EXTENSIONS); + final String ret = EGL.eglQueryString(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_EXTENSIONS); if (DEBUG) { System.err.println("EGL extensions: " + ret); } @@ -276,22 +289,63 @@ public abstract class EGLContext extends GLContextImpl { @Override protected boolean setSwapIntervalImpl(int interval) { - // FIXME !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // eglSwapInterval(..) issued: - // Android 4.0.3 / Pandaboard ES / PowerVR SGX 540: crashes - // FIXME !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - if( Platform.OSType.ANDROID == Platform.getOSType() && getGLRendererString(true).contains("powervr") ) { - if(DEBUG) { - System.err.println("Ignored: eglSwapInterval("+interval+") - cause: OS "+Platform.getOSType() + " / Renderer " + getGLRendererString(false)); - } + if( hasRendererQuirk(GLRendererQuirks.NoSetSwapInterval) ) { return false; } - return EGL.eglSwapInterval(((EGLDrawable)drawable).getDisplay(), interval); + return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval); } - public abstract void bindPbufferToTexture(); + // + // Accessible .. + // - public abstract void releasePbufferFromTexture(); + /* pp */ void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) { + mapStaticGLVersion(device, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + } + /* pp */ int getContextOptions() { return ctxOptions; } + /* pp */ static void mapStaticGLESVersion(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps) { + final GLProfile glp = caps.getGLProfile(); + final int[] reqMajorCTP = new int[2]; + GLContext.getRequestMajorAndCompat(glp, reqMajorCTP); + if( glp.isGLES() ) { + if( reqMajorCTP[0] >= 3 ) { + reqMajorCTP[1] |= GLContext.CTX_IMPL_ES3_COMPAT | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ; + } else if( reqMajorCTP[0] >= 2 ) { + reqMajorCTP[1] |= GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ; + } + } + if( !caps.getHardwareAccelerated() ) { + reqMajorCTP[1] |= GLContext.CTX_IMPL_ACCEL_SOFT; + } + mapStaticGLVersion(device, reqMajorCTP[0], 0, reqMajorCTP[1]); + } + /* pp */ static void mapStaticGLVersion(AbstractGraphicsDevice device, int major, int minor, int ctp) { + if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) { + // ES1, ES2, ES3, .. + mapStaticGLVersion(device, major /* reqMajor */, major, minor, ctp); + if( 3 == major ) { + // map ES2 -> ES3 + mapStaticGLVersion(device, 2 /* reqMajor */, major, minor, ctp); + } + } + } + private static void mapStaticGLVersion(AbstractGraphicsDevice device, int reqMajor, int major, int minor, int ctp) { + GLContext.mapAvailableGLVersion(device, reqMajor, GLContext.CTX_PROFILE_ES, major, minor, ctp); + if(! ( device instanceof EGLGraphicsDevice ) ) { + final EGLGraphicsDevice eglDevice = new EGLGraphicsDevice(device.getHandle(), EGL.EGL_NO_DISPLAY, device.getConnection(), device.getUnitID(), null); + GLContext.mapAvailableGLVersion(eglDevice, reqMajor, GLContext.CTX_PROFILE_ES, major, minor, ctp); + } + } + protected static String getGLVersion(int major, int minor, int ctp, String gl_version) { + return GLContext.getGLVersion(major, minor, ctp, gl_version); + } + + protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) { + return GLContext.getAvailableGLVersionsSet(device); + } + protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) { + GLContext.setAvailableGLVersionsSet(device); + } protected static String toHexString(int hex) { return GLContext.toHexString(hex); @@ -299,25 +353,23 @@ public abstract class EGLContext extends GLContextImpl { protected static String toHexString(long hex) { return GLContext.toHexString(hex); } - + //---------------------------------------------------------------------- // Currently unimplemented stuff // + @Override protected void copyImpl(GLContext source, int mask) throws GLException { throw new GLException("Not yet implemented"); } - - public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { - throw new GLException("Should not call this"); - } - - public boolean offscreenImageNeedsVerticalFlip() { + @Override + public final ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, float priority) { throw new GLException("Should not call this"); } - public int getOffscreenContextPixelDataType() { + @Override + public final void glFreeMemoryNV(ByteBuffer pointer) { throw new GLException("Should not call this"); } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java index e09400c09..c5f76f667 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java @@ -3,14 +3,14 @@ * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR @@ -20,7 +20,7 @@ * 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. @@ -29,105 +29,310 @@ package jogamp.opengl.egl; import java.nio.IntBuffer; +import java.util.Iterator; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.ToolkitLock; +import javax.media.opengl.GLException; import jogamp.opengl.Debug; -import com.jogamp.common.util.LongIntHashMap; +import com.jogamp.common.util.LongObjectHashMap; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; -/** - * This implementation provides recursive calls to +/** + * This implementation provides recursive calls to * {@link EGL#eglInitialize(long, IntBuffer, IntBuffer)} and {@link EGL#eglTerminate(long)}, * where <code>eglInitialize(..)</code> is issued only for the 1st call per <code>eglDisplay</code> * and <code>eglTerminate(..)</code> is issued only for the last call. * <p> * This class is required, due to implementation bugs within EGL where {@link EGL#eglTerminate(long)} - * does not mark the resource for deletion when still in use, bug releases them immediatly. + * does not mark the resource for deletion when still in use, bug releases them immediately. * </p> */ public class EGLDisplayUtil { - protected static final boolean DEBUG = Debug.debug("EGL"); - - static LongIntHashMap eglDisplayCounter; - + private static final boolean DEBUG = Debug.debug("EGLDisplayUtil"); + private static boolean useSingletonEGLDisplay = false; + private static EGLDisplayRef singletonEGLDisplay = null; + + private static class EGLDisplayRef { + final long eglDisplay; + final Throwable createdStack; + int initRefCount; + + /** + * Returns an already opened {@link EGLDisplayRef} or opens a new {@link EGLDisplayRef}. + * <p> + * Opened {@link EGLDisplayRef}s are mapped against their <code>eglDisplay</code> handle. + * </p> + * <p> + * Method utilizes {@link EGLDisplayRef}'s reference counter, i.e. increases it. + * </p> + * <p> + * An {@link EGLDisplayRef} is <i>opened</i> via {@link EGL#eglInitialize(long, IntBuffer, IntBuffer)}. + * </p> + */ + static EGLDisplayRef getOrCreateOpened(final long eglDisplay, final IntBuffer major, final IntBuffer minor) { + EGLDisplayRef o = (EGLDisplayRef) openEGLDisplays.get(eglDisplay); + if( null == o ) { + if( EGL.eglInitialize(eglDisplay, major, minor) ) { + final EGLDisplayRef n = new EGLDisplayRef(eglDisplay); + openEGLDisplays.put(eglDisplay, n); + n.initRefCount++; + if( null == singletonEGLDisplay ) { + singletonEGLDisplay = n; + } + return n; + } else { + return null; + } + } else { + o.initRefCount++; + return o; + } + } + + /** + * Closes an already opened {@link EGLDisplayRef}. + * <p> + * Method decreases a reference counter and closes the {@link EGLDisplayRef} if it reaches zero. + * </p> + * <p> + * An {@link EGLDisplayRef} is <i>closed</i> via {@link EGL#eglTerminate(long)}. + * </p> + */ + static EGLDisplayRef closeOpened(final long eglDisplay, final boolean[] res) { + final EGLDisplayRef o = (EGLDisplayRef) openEGLDisplays.get(eglDisplay); + res[0] = true; + if( null != o ) { + if( 0 < o.initRefCount ) { // no negative refCount + o.initRefCount--; + if( 0 == o.initRefCount ) { + res[0] = EGL.eglTerminate(eglDisplay); + if( o == singletonEGLDisplay ) { + singletonEGLDisplay = null; + } + } + } + if( 0 >= o.initRefCount ) { + openEGLDisplays.remove(eglDisplay); + } + } + return o; + } + + private EGLDisplayRef(long eglDisplay) { + this.eglDisplay = eglDisplay; + this.initRefCount = 0; + this.createdStack = DEBUG ? new Throwable() : null; + } + + @Override + public String toString() { + return "EGLDisplayRef[0x"+Long.toHexString(eglDisplay)+": refCnt "+initRefCount+"]"; + } + } + private static final LongObjectHashMap openEGLDisplays; + static { - eglDisplayCounter = new LongIntHashMap(); - eglDisplayCounter.setKeyNotFoundValue(0); + openEGLDisplays = new LongObjectHashMap(); + openEGLDisplays.setKeyNotFoundValue(null); + } + + /** + * @return number of unclosed EGL Displays.<br> + */ + public static int shutdown(boolean verbose) { + if(DEBUG || verbose || openEGLDisplays.size() > 0 ) { + System.err.println("EGLDisplayUtil.EGLDisplays: Shutdown (open: "+openEGLDisplays.size()+")"); + if(DEBUG) { + Thread.dumpStack(); + } + if( openEGLDisplays.size() > 0) { + dumpOpenDisplayConnections(); + } + } + return openEGLDisplays.size(); + } + + public static void dumpOpenDisplayConnections() { + System.err.println("EGLDisplayUtil: Open EGL Display Connections: "+openEGLDisplays.size()); + int i=0; + for(Iterator<LongObjectHashMap.Entry> iter = openEGLDisplays.iterator(); iter.hasNext(); i++) { + final LongObjectHashMap.Entry e = iter.next(); + final EGLDisplayRef v = (EGLDisplayRef) e.value; + System.err.println("EGLDisplayUtil: Open["+i+"]: 0x"+Long.toHexString(e.key)+": "+v); + if(null != v.createdStack) { + v.createdStack.printStackTrace(); + } + } } - public static long eglGetDisplay(long nativeDisplay_id) { + /* pp */ static synchronized void setSingletonEGLDisplayOnly(boolean v) { useSingletonEGLDisplay = v; } + + private static synchronized long eglGetDisplay(long nativeDisplay_id) { + if( useSingletonEGLDisplay && null != singletonEGLDisplay ) { + if(DEBUG) { + System.err.println("EGLDisplayUtil.eglGetDisplay.s: eglDisplay("+EGLContext.toHexString(nativeDisplay_id)+"): "+ + EGLContext.toHexString(singletonEGLDisplay.eglDisplay)+ + ", "+((EGL.EGL_NO_DISPLAY != singletonEGLDisplay.eglDisplay)?"OK":"Failed")+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")"); + } + return singletonEGLDisplay.eglDisplay; + } final long eglDisplay = EGL.eglGetDisplay(nativeDisplay_id); if(DEBUG) { - System.err.println("EGLDisplayUtil.eglGetDisplay(): eglDisplay("+EGLContext.toHexString(nativeDisplay_id)+"): "+ + System.err.println("EGLDisplayUtil.eglGetDisplay.X: eglDisplay("+EGLContext.toHexString(nativeDisplay_id)+"): "+ EGLContext.toHexString(eglDisplay)+ - ", "+((EGL.EGL_NO_DISPLAY != eglDisplay)?"OK":"Failed")); + ", "+((EGL.EGL_NO_DISPLAY != eglDisplay)?"OK":"Failed")+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")"); } return eglDisplay; } - - public static long eglGetDisplay(NativeSurface surface, boolean allowFallBackToDefault) { - final long nDisplay; - if( NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) { - nDisplay = surface.getSurfaceHandle(); // don't even ask .. - } else { - nDisplay = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY + + /** + * @param eglDisplay + * @param major + * @param minor + * @return true if the eglDisplay is valid and it's reference counter becomes one and {@link EGL#eglInitialize(long, IntBuffer, IntBuffer)} was successful, otherwise false + * + * @see EGL#eglInitialize(long, IntBuffer, IntBuffer) + */ + private static synchronized boolean eglInitialize(long eglDisplay, IntBuffer major, IntBuffer minor) { + if( EGL.EGL_NO_DISPLAY == eglDisplay) { + return false; + } + final EGLDisplayRef d = EGLDisplayRef.getOrCreateOpened(eglDisplay, major, minor); + if(DEBUG) { + System.err.println("EGLDisplayUtil.eglInitialize("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+(null != d)+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")"); + // Thread.dumpStack(); + } + return null != d; + } + + /** + * @param nativeDisplayID + * @param eglDisplay array of size 1 holding return value if successful, otherwise {@link EGL#EGL_NO_DISPLAY}. + * @param eglErr array of size 1 holding the EGL error value as retrieved by {@link EGL#eglGetError()} if not successful. + * @param major + * @param minor + * @return {@link EGL#EGL_SUCCESS} if successful, otherwise {@link EGL#EGL_BAD_DISPLAY} if {@link #eglGetDisplay(long)} failed + * or {@link EGL#EGL_NOT_INITIALIZED} if {@link #eglInitialize(long, IntBuffer, IntBuffer)} failed. + * + * @see #eglGetDisplay(long) + * @see #eglInitialize(long, IntBuffer, IntBuffer) + */ + private static synchronized int eglGetDisplayAndInitialize(long nativeDisplayID, long[] eglDisplay, int[] eglErr, IntBuffer major, IntBuffer minor) { + eglDisplay[0] = EGL.EGL_NO_DISPLAY; + final long _eglDisplay = eglGetDisplay( nativeDisplayID ); + if ( EGL.EGL_NO_DISPLAY == _eglDisplay ) { + eglErr[0] = EGL.eglGetError(); + return EGL.EGL_BAD_DISPLAY; } - long eglDisplay = EGLDisplayUtil.eglGetDisplay(nDisplay); - if (eglDisplay == EGL.EGL_NO_DISPLAY && nDisplay != EGL.EGL_DEFAULT_DISPLAY && allowFallBackToDefault) { + if ( !eglInitialize( _eglDisplay, major, minor) ) { + eglErr[0] = EGL.eglGetError(); + return EGL.EGL_NOT_INITIALIZED; + } + eglDisplay[0] = _eglDisplay; + return EGL.EGL_SUCCESS; + } + + /** + * Attempts to {@link #eglGetDisplayAndInitialize(long, long[], int[], IntBuffer, IntBuffer)} with given <code>nativeDisplayID</code>. + * If this fails, method retries with <code>nativeDisplayID</code> {@link EGL#EGL_DEFAULT_DISPLAY} - the fallback mechanism. + * The actual used <code>nativeDisplayID</code> is returned in it's in/out array. + * + * @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 + * @return the initialized EGL display ID + * @throws GLException if not successful + */ + private static synchronized long eglGetDisplayAndInitialize(long[] nativeDisplayID) { + final long[] eglDisplay = new long[1]; + final int[] eglError = new int[1]; + int eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(nativeDisplayID[0], eglDisplay, eglError, null, null); + if( EGL.EGL_SUCCESS == eglRes ) { + return eglDisplay[0]; + } + if( EGL.EGL_DEFAULT_DISPLAY != nativeDisplayID[0] ) { // fallback to DEGAULT_DISPLAY if(DEBUG) { - System.err.println("EGLDisplayUtil.eglGetDisplay(): Fall back to EGL_DEFAULT_DISPLAY"); + 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); + if( EGL.EGL_SUCCESS == eglRes ) { + nativeDisplayID[0] = EGL.EGL_DEFAULT_DISPLAY; + return eglDisplay[0]; } - eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); } - return eglDisplay; + throw new GLException("Failed to created/initialize EGL display incl. fallback default: native "+EGLContext.toHexString(nativeDisplayID[0])+", error "+EGLContext.toHexString(eglRes)+"/"+EGLContext.toHexString(eglError[0])); } - - public static synchronized boolean eglInitialize(long eglDisplay, int[] major, int major_offset, int[] minor, int minor_offset) { - final boolean res; - final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init - if(1==refCnt) { - res = EGL.eglInitialize(eglDisplay, major, major_offset, minor, minor_offset); - } else { - res = true; + + /** + * @param eglDisplay the EGL display handle + * @return true if the eglDisplay is valid and it's reference counter becomes zero and {@link EGL#eglTerminate(long)} was successful, otherwise false + */ + private static synchronized boolean eglTerminate(long eglDisplay) { + if( EGL.EGL_NO_DISPLAY == eglDisplay) { + return false; } - eglDisplayCounter.put(eglDisplay, refCnt); + final boolean[] res = new boolean[1]; + final EGLDisplayRef d = EGLDisplayRef.closeOpened(eglDisplay, res); if(DEBUG) { - System.err.println("EGL.eglInitialize(0x"+Long.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res); + System.err.println("EGLDisplayUtil.eglTerminate.X("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+res[0]+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")"); + // Thread.dumpStack(); } - return res; + return res[0]; } - - public static synchronized boolean eglInitialize(long eglDisplay, IntBuffer major, IntBuffer minor) { - final boolean res; - final int refCnt = eglDisplayCounter.get(eglDisplay) + 1; // 0 + 1 = 1 -> 1st init - if(1==refCnt) { // only initialize once - res = EGL.eglInitialize(eglDisplay, major, minor); - } else { - res = true; + + private static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() { + @Override + public long eglGetAndInitDisplay(long[] nativeDisplayID) { + return eglGetDisplayAndInitialize(nativeDisplayID); } - eglDisplayCounter.put(eglDisplay, refCnt); - if(DEBUG) { - System.err.println("EGL.eglInitialize(0x"+Long.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res); + @Override + public void eglTerminate(long eglDisplayHandle) { + EGLDisplayUtil.eglTerminate(eglDisplayHandle); } - return res; + }; + + /** + * Returns an uninitialized {@link EGLGraphicsDevice}. User needs to issue {@link EGLGraphicsDevice#open()} before usage. + * <p> + * Using {@link #eglGetDisplayAndInitialize(long[])} for the {@link EGLGraphicsDevice#open()} implementation + * and {@link #eglTerminate(long)} for {@link EGLGraphicsDevice#close()}. + * </p> + * <p> + * Using the default {@link ToolkitLock}, via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}. + * </p> + * @param nativeDisplayID + * @param connection + * @param unitID + * @return an uninitialized {@link EGLGraphicsDevice} + */ + public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID) { + return new EGLGraphicsDevice(nativeDisplayID, EGL.EGL_NO_DISPLAY, connection, unitID, eglLifecycleCallback); } - - public static synchronized boolean eglTerminate(long eglDisplay) { - final boolean res; - final int refCnt = eglDisplayCounter.get(eglDisplay) - 1; // 1 - 1 = 0 -> final terminate - if(0==refCnt) { // no terminate if still in use or already terminated - res = EGL.eglTerminate(eglDisplay); + + /** + * Returns an uninitialized {@link EGLGraphicsDevice}. User needs to issue {@link EGLGraphicsDevice#open()} before usage. + * <p> + * Using {@link #eglGetDisplayAndInitialize(long[])} for the {@link EGLGraphicsDevice#open()} implementation + * and {@link #eglTerminate(long)} for {@link EGLGraphicsDevice#close()}. + * </p> + * <p> + * Using the default {@link ToolkitLock}, via {@link NativeWindowFactory#getDefaultToolkitLock(String, long)}. + * </p> + * @param surface + * @return an uninitialized EGLGraphicsDevice + */ + public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(NativeSurface surface) { + final long nativeDisplayID; + if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ) { + nativeDisplayID = surface.getSurfaceHandle(); // don't even ask .. } else { - res = true; - } - if(0<=refCnt) { // no negative refCount - eglDisplayCounter.put(eglDisplay, refCnt); - } - if(DEBUG) { - System.err.println("EGL.eglTerminate(0x"+Long.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res); + nativeDisplayID = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY } - return res; + final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice(); + return new EGLGraphicsDevice(nativeDisplayID, EGL.EGL_NO_DISPLAY, adevice.getConnection(), adevice.getUnitID(), eglLifecycleCallback); } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index b2119d728..f184edae3 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2010 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -29,229 +29,146 @@ * 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. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ package jogamp.opengl.egl; -import jogamp.opengl.GLDynamicLookupHelper; -import jogamp.opengl.GLDrawableImpl; +import java.nio.IntBuffer; -import javax.media.nativewindow.*; -import javax.media.nativewindow.VisualIDHolder.VIDType; -import javax.media.opengl.*; +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.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; -import com.jogamp.nativewindow.egl.*; +import com.jogamp.common.nio.Buffers; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public abstract class EGLDrawable extends GLDrawableImpl { - protected boolean ownEGLDisplay = false; // for destruction - protected boolean ownEGLSurface = false; // for destruction - private EGLGraphicsConfiguration eglConfig; - protected long eglDisplay; - protected long eglSurface; - protected EGLDrawable(EGLDrawableFactory factory, - NativeSurface component) throws GLException { + protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException { super(factory, component, false); - eglSurface=EGL.EGL_NO_SURFACE; - eglDisplay=0; - } - - public long getDisplay() { - return eglDisplay; - } - - public long getHandle() { - return eglSurface; - } - - public EGLGraphicsConfiguration getGraphicsConfiguration() { - return eglConfig; - } - - public GLCapabilitiesImmutable getChosenGLCapabilities() { - return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilitiesImmutable)eglConfig.getChosenCapabilities(); } + @Override public abstract GLContext createContext(GLContext shareWith); - protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle); + protected abstract long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle); - private void recreateSurface() { - // create a new EGLSurface .. - if(EGL.EGL_NO_SURFACE!=eglSurface) { - EGL.eglDestroySurface(eglDisplay, eglSurface); - } + private final long createEGLSurface() { + final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) eglws.getGraphicsConfiguration(); + final NativeSurface upstreamSurface = eglws.getUpstreamSurface(); - if(DEBUG) { - System.err.println(getThreadName() + ": createSurface using eglDisplay "+toHexString(eglDisplay)+", "+eglConfig); - } + long eglSurface = createSurface(eglConfig, eglws.getWidth(), eglws.getHeight(), upstreamSurface.getSurfaceHandle()); - eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), surface.getSurfaceHandle()); - int eglError0 = EGL.EGL_SUCCESS; + 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). + // Try window handle if available and differs (Windows HDC / HWND). // ANGLE impl. required HWND on Windows. - if(surface instanceof NativeWindow) { - final NativeWindow nw = (NativeWindow) surface; + 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(eglDisplay, eglConfig.getNativeConfig(), nw.getWindowHandle()); + eglSurface = createSurface(eglConfig, eglws.getWidth(), eglws.getHeight(), 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() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface)); + System.err.println(getThreadName() + ": createEGLSurface handle "+toHexString(eglSurface)); } + return eglSurface; } @Override - protected final void updateHandle() { - if(ownEGLSurface) { - recreateSurface(); + protected final void createHandle() { + final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + if(DEBUG) { + System.err.println(getThreadName() + ": createHandle of "+eglws); + } + 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); + } + eglws.setSurfaceHandle( createEGLSurface() ); + } else if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) { + throw new InternalError("Nil surface but claimed to be valid: "+eglws); } } - - protected void setRealizedImpl() { - if (realized) { - AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); - AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); - if(aDevice instanceof EGLGraphicsDevice) { - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): using existing EGL config - START"); - } - // just fetch the data .. trust but verify .. - eglDisplay = aDevice.getHandle(); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Invalid EGL display in EGLGraphicsDevice from "+aDevice); - } - if(aConfig instanceof EGLGraphicsConfiguration) { - eglConfig = (EGLGraphicsConfiguration) aConfig; // done .. - if (null == eglConfig) { - throw new GLException("Null EGLGraphicsConfiguration from "+aConfig); - } - int[] tmp = new int[1]; - if ( 0 != surface.getSurfaceHandle() && - EGL.eglQuerySurface(eglDisplay, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) { - // surface holds static EGLSurface - eglSurface = surface.getSurfaceHandle(); - if(DEBUG) { - System.err.println(getThreadName() + ": setSurface re-using component's EGLSurface: handle "+toHexString(eglSurface)); - } - } else { - // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); - ownEGLSurface=true; - } - } else { - throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig); - } - } else { - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): creating new EGL config - START"); - } - // create a new EGL config .. - ownEGLDisplay=true; - // EGLSurface is ours .. - ownEGLSurface=true; + @Override + protected void destroyHandle() { + final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + if(DEBUG) { + System.err.println(getThreadName() + ": destroyHandle of "+eglws); + } + 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); + } + } - eglDisplay = EGLDisplayUtil.eglGetDisplay(surface, true); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Failed to created EGL display: "+surface+", "+aDevice+", error "+toHexString(EGL.eglGetError())); - } - if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { - throw new GLException("eglInitialize failed"+", error "+Integer.toHexString(EGL.eglGetError())); - } - EGLGraphicsDevice e = new EGLGraphicsDevice(eglDisplay, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); - AbstractGraphicsScreen s = new DefaultGraphicsScreen(e, aConfig.getScreen().getIndex()); - final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); - if(aConfig instanceof EGLGraphicsConfiguration) { - final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); - if(0 == capsChosen.getEGLConfig()) { - // 'refresh' the native EGLConfig handle - capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDisplay, capsChosen.getEGLConfigID())); - if(0 == capsChosen.getEGLConfig()) { - throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig); - } - } - eglConfig = new EGLGraphicsConfiguration(s, capsChosen, capsRequested, null); - if(DEBUG) { - System.err.println(getThreadName() + ": Reusing chosenCaps: "+eglConfig); - } - } else { - eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( - capsRequested, capsRequested, null, s, aConfig.getVisualID(VIDType.NATIVE), false); - - if (null == eglConfig) { - throw new GLException("Couldn't create EGLGraphicsConfiguration from "+s); - } else if(DEBUG) { - System.err.println(getThreadName() + ": Chosen eglConfig: "+eglConfig); - } - } - // subsequent updateHandle() will issue recreateSurface(); - } - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): END: ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface); - } - } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) { + protected static boolean isValidEGLSurface(long eglDisplayHandle, long surfaceHandle) { + if( 0 == surfaceHandle ) { + return false; + } + 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.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", eglDisplay: "+toHexString(eglDisplay)+", eglSurface: "+toHexString(eglSurface)); + System.err.println(getThreadName() + ": EGLDrawable.isValidEGLSurface eglQuerySuface failed: error "+toHexString(eglErr)+", "+toHexString(surfaceHandle)); } - // Destroy the window surface - if (!EGL.eglDestroySurface(eglDisplay, eglSurface)) { - throw new GLException("Error destroying window surface (eglDestroySurface)"); - } - eglSurface = EGL.EGL_NO_SURFACE; - if (ownEGLDisplay && EGL.EGL_NO_DISPLAY!=eglDisplay) { - EGLDisplayUtil.eglTerminate(eglDisplay); - } - eglDisplay=EGL.EGL_NO_DISPLAY; - eglConfig=null; } + return eglSurfaceValid; } - protected final void swapBuffersImpl() { - // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - if(!EGL.eglSwapBuffers(eglDisplay, eglSurface)) { - throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); + @Override + protected final void setRealizedImpl() { + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealized("+realized+"): NOP - "+surface); } } - /** - * Surface not realizes yet (onscreen) .. Quering EGL surface size only makes sense for external drawable. - * Leave it here for later impl. of an EGLExternalDrawable. - public int getWidth() { - int[] tmp = new int[1]; - if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) { - throw new GLException("Error querying surface width, eglError "+toHexString(EGL.eglGetError())); + @Override + protected final void swapBuffersImpl(boolean doubleBuffered) { + if(doubleBuffered) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); + // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() + if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) { + throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); + } } - return tmp[0]; } - public int getHeight() { - int[] tmp = new int[1]; - if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) { - throw new GLException("Error querying surface height, eglError "+toHexString(EGL.eglGetError())); - } - return tmp[0]; - } */ - + @Override public GLDynamicLookupHelper getGLDynamicLookupHelper() { - if (getGLProfile().usesNativeGLES2()) { + if (getGLProfile().usesNativeGLES3()) { + return getFactoryImpl().getGLDynamicLookupHelper(3); + } else if (getGLProfile().usesNativeGLES2()) { return getFactoryImpl().getGLDynamicLookupHelper(2); } else if (getGLProfile().usesNativeGLES1()) { return getFactoryImpl().getGLDynamicLookupHelper(1); @@ -260,12 +177,13 @@ public abstract class EGLDrawable extends GLDrawableImpl { } } + @Override public String toString() { return getClass().getName()+"[realized "+isRealized()+ ",\n\tfactory "+getFactory()+ ",\n\tsurface "+getNativeSurface()+ - ",\n\teglSurface "+toHexString(eglSurface)+ - ",\n\teglConfig "+eglConfig+ + ",\n\teglSurface "+toHexString(surface.getSurfaceHandle())+ + ",\n\teglConfig "+surface.getGraphicsConfiguration()+ ",\n\trequested "+getRequestedGLCapabilities()+ ",\n\tchosen "+getChosenGLCapabilities()+"]"; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index 4b77bfa87..9ee0134f1 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2010 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -29,93 +29,109 @@ * 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. - * + * * 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.*; -import javax.media.opengl.*; -import javax.media.opengl.GLProfile.ShutdownType; - -import com.jogamp.common.JogampRuntimeException; -import com.jogamp.common.os.Platform; -import com.jogamp.common.util.*; -import com.jogamp.nativewindow.WrappedSurface; -import com.jogamp.nativewindow.egl.EGLGraphicsDevice; - -import jogamp.opengl.*; - +import java.nio.IntBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; +import javax.media.nativewindow.VisualIDHolder; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.WrappedSurface; +import jogamp.opengl.Debug; +import jogamp.opengl.GLContextImpl; +import jogamp.opengl.GLDrawableFactoryImpl; +import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.GLGraphicsConfigurationUtil; +import jogamp.opengl.SharedResourceRunner; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.common.nio.PointerBuffer; +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.GLRendererQuirks; public class EGLDrawableFactory extends GLDrawableFactoryImpl { + protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG; // allow package access + + /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK; + + static { + Debug.initSingleton(); + QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); + } + private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null; - private static boolean isANGLE = false; - + private static final boolean isANGLE(GLDynamicLookupHelper dl) { if(Platform.OSType.WINDOWS == Platform.OS_TYPE) { - final boolean r = 0 != dl.dynamicLookupFunction("eglQuerySurfacePointerANGLE") || - 0 != dl.dynamicLookupFunction("glBlitFramebufferANGLE") || - 0 != dl.dynamicLookupFunction("glRenderbufferStorageMultisampleANGLE"); - return r; + return dl.isFunctionAvailable("eglQuerySurfacePointerANGLE") || + dl.isFunctionAvailable("glBlitFramebufferANGLE") || + dl.isFunctionAvailable("glRenderbufferStorageMultisampleANGLE"); } else { return false; } } - + + private static final boolean includesES1(GLDynamicLookupHelper dl) { + return dl.isFunctionAvailable("glLoadIdentity") && + dl.isFunctionAvailable("glEnableClientState") && + dl.isFunctionAvailable("glColorPointer"); + } + public EGLDrawableFactory() { super(); - + // Register our GraphicsConfigurationFactory implementations // The act of constructing them causes them to be registered EGLGraphicsConfigurationFactory.registerFactory(); // Check for other underlying stuff .. - if(NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) { + if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true)) { + hasX11 = true; try { ReflectionUtil.createInstance("jogamp.opengl.x11.glx.X11GLXGraphicsConfigurationFactory", EGLDrawableFactory.class.getClassLoader()); - } catch (JogampRuntimeException jre) { /* n/a .. */ } + } catch (Exception jre) { /* n/a .. */ } } - defaultDevice = new EGLGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); - - // FIXME: Probably need to move EGL from a static model - // to a dynamic one, where there can be 2 instances + // FIXME: Probably need to move EGL from a static model + // to a dynamic one, where there can be 2 instances // for each ES profile with their own ProcAddressTable. synchronized(EGLDrawableFactory.class) { - /** - * Currently AMD's EGL impl. crashes at eglGetDisplay(EGL_DEFAULT_DISPLAY) - * - // Check Desktop ES2 Availability first (AMD, ..) - if(null==eglES2DynamicLookupHelper) { - GLDynamicLookupHelper tmp=null; - try { - tmp = new GLDynamicLookupHelper(new DesktopES2DynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); - } - } - if(null!=tmp && tmp.isLibComplete()) { - eglES2DynamicLookupHelper = tmp; - EGL.resetProcAddressTable(eglES2DynamicLookupHelper); - if (GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: Desktop ES2 - OK"); - } - } else if (GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: Desktop ES2 - NOPE"); - } - } */ final boolean hasDesktopES2 = null != eglES2DynamicLookupHelper; - + if(!hasDesktopES2 && null==eglES1DynamicLookupHelper) { GLDynamicLookupHelper tmp=null; try { @@ -124,18 +140,18 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if(DEBUG) { gle.printStackTrace(); } - } + } if(null!=tmp && tmp.isLibComplete()) { eglES1DynamicLookupHelper = tmp; EGL.resetProcAddressTable(eglES1DynamicLookupHelper); final boolean isANGLEES1 = isANGLE(eglES1DynamicLookupHelper); isANGLE |= isANGLEES1; - if (GLProfile.DEBUG) { + if (DEBUG || GLProfile.DEBUG) { System.err.println("Info: EGLDrawableFactory: EGL ES1 - OK, isANGLE: "+isANGLEES1); - } - } else if (GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: EGL ES1 - NOPE"); - } + } + } else if (DEBUG || GLProfile.DEBUG) { + System.err.println("Info: EGLDrawableFactory: EGL ES1 - NOPE (ES1 lib)"); + } } if(!hasDesktopES2 && null==eglES2DynamicLookupHelper) { GLDynamicLookupHelper tmp=null; @@ -145,196 +161,545 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if(DEBUG) { gle.printStackTrace(); } - } + } if(null!=tmp && tmp.isLibComplete()) { eglES2DynamicLookupHelper = tmp; EGL.resetProcAddressTable(eglES2DynamicLookupHelper); + final boolean includesES1 = null == eglES1DynamicLookupHelper && includesES1(eglES2DynamicLookupHelper); + if(includesES1) { + eglES1DynamicLookupHelper = tmp; + } final boolean isANGLEES2 = isANGLE(eglES2DynamicLookupHelper); isANGLE |= isANGLEES2; - if (GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: EGL ES2 - OK, isANGLE: "+isANGLEES2); - } - } else if (GLProfile.DEBUG) { + if (DEBUG || GLProfile.DEBUG) { + System.err.println("Info: EGLDrawableFactory: EGL ES2 - OK (includesES1 "+includesES1+", isANGLE: "+isANGLEES2+")"); + if(includesES1) { + System.err.println("Info: EGLDrawableFactory: EGL ES1 - OK (ES2 lib)"); + } + } + } else if (DEBUG || GLProfile.DEBUG) { System.err.println("Info: EGLDrawableFactory: EGL ES2 - NOPE"); - } + } + } + if( null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper ) { + if(isANGLE && !enableANGLE) { + if(DEBUG || GLProfile.DEBUG) { + System.err.println("Info: EGLDrawableFactory.init - EGL/ES2 ANGLE disabled"); + } + } else { + if( isANGLE && ( DEBUG || GLProfile.DEBUG ) ) { + System.err.println("Info: EGLDrawableFactory.init - EGL/ES2 ANGLE enabled"); + } + sharedMap = new HashMap<String /*uniqueKey*/, SharedResource>(); + sharedMapCreateAttempt = new HashSet<String>(); + // FIXME: defaultDevice.open() triggers eglInitialize(..) which crashed on Windows w/ Chrome/ANGLE, FF/ANGLE! + defaultDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + } } } } - protected final void destroy(ShutdownType shutdownType) { + @Override + protected final boolean isComplete() { + return null != sharedMap; // null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper; + } + + + @Override + protected final void shutdownImpl() { + if( DEBUG ) { + System.err.println("EGLDrawableFactory.shutdown"); + } if(null != sharedMap) { + if(DEBUG) { + dumpMap(); + } Collection<SharedResource> srl = sharedMap.values(); for(Iterator<SharedResource> sri = srl.iterator(); sri.hasNext(); ) { SharedResource sr = sri.next(); if(DEBUG) { - System.err.println("EGLDrawableFactory.destroy("+shutdownType+"): "+sr.device.toString()); - } - final long eglDisplay = sr.device.getHandle(); - if(EGL.EGL_NO_DISPLAY != eglDisplay) { - EGLDisplayUtil.eglTerminate(eglDisplay); + System.err.println("EGLDrawableFactory.shutdown: "+sr.device.toString()); } + sr.device.close(); } sharedMap.clear(); + sharedMapCreateAttempt.clear(); sharedMap = null; + sharedMapCreateAttempt = null; + } + if(null != defaultSharedResource) { + defaultSharedResource = null; + } + if(null != defaultDevice) { + defaultDevice.close(); + defaultDevice = null; } - defaultDevice = null; /** * Pulling away the native library may cause havoc .. */ - if(ShutdownType.COMPLETE == shutdownType) { - if(null != eglES1DynamicLookupHelper) { - // eglES1DynamicLookupHelper.destroy(); - eglES1DynamicLookupHelper = null; - } - if(null != eglES2DynamicLookupHelper) { - // eglES2DynamicLookupHelper.destroy(); - eglES2DynamicLookupHelper = null; - } + if(null != eglES1DynamicLookupHelper) { + // eglES1DynamicLookupHelper.destroy(); + eglES1DynamicLookupHelper = null; + } + if(null != eglES2DynamicLookupHelper) { + // eglES2DynamicLookupHelper.destroy(); + eglES2DynamicLookupHelper = null; } EGLGraphicsConfigurationFactory.unregisterFactory(); + EGLDisplayUtil.shutdown(DEBUG); + } + + private void dumpMap() { + synchronized(sharedMap) { + System.err.println("EGLDrawableFactory.map "+sharedMap.size()); + int i=0; + Set<String> keys = sharedMap.keySet(); + for(Iterator<String> keyI = keys.iterator(); keyI.hasNext(); i++) { + String key = keyI.next(); + SharedResource sr = sharedMap.get(key); + System.err.println("EGLDrawableFactory.map["+i+"] "+key+" -> "+sr.getDevice()+", "+ + "es1 [avail "+sr.wasES1ContextCreated+", pbuffer "+sr.hasPBufferES1+", quirks "+sr.rendererQuirksES1+", ctp "+EGLContext.getGLVersion(1, 0, sr.ctpES1, null)+"], "+ + "es2/3 [es2 "+sr.wasES2ContextCreated+", es3 "+sr.wasES3ContextCreated+", [pbuffer "+sr.hasPBufferES3ES2+", quirks "+sr.rendererQuirksES3ES2+", ctp "+EGLContext.getGLVersion(2, 0, sr.ctpES3ES2, null)+"]]"); + } + ; + } } - private HashMap<String /*connection*/, SharedResource> sharedMap = new HashMap<String /*connection*/, SharedResource>(); - private EGLGraphicsDevice defaultDevice; + private HashMap<String /*uniqueKey*/, SharedResource> sharedMap = null; + private HashSet<String> sharedMapCreateAttempt = null; + private EGLGraphicsDevice defaultDevice = null; + private SharedResource defaultSharedResource = null; + private boolean isANGLE = false; + private boolean hasX11 = false; - static class SharedResource { + static class SharedResource implements SharedResourceRunner.Resource { private final EGLGraphicsDevice device; - // private final EGLDrawable drawable; // private final EGLContext contextES1; // private final EGLContext contextES2; + // private final EGLContext contextES3; private final boolean wasES1ContextCreated; private final boolean wasES2ContextCreated; + private final boolean wasES3ContextCreated; + private final GLRendererQuirks rendererQuirksES1; + private final GLRendererQuirks rendererQuirksES3ES2; + private final int ctpES1; + private final int ctpES3ES2; + private final boolean hasPBufferES1; + private final boolean hasPBufferES3ES2; - SharedResource(EGLGraphicsDevice dev, boolean wasContextES1Created, boolean wasContextES2Created - /*EGLDrawable draw, EGLContext ctxES1, EGLContext ctxES2 */) { + SharedResource(EGLGraphicsDevice dev, + boolean wasContextES1Created, boolean hasPBufferES1, GLRendererQuirks rendererQuirksES1, int ctpES1, + boolean wasContextES2Created, boolean wasContextES3Created, + boolean hasPBufferES3ES2, GLRendererQuirks rendererQuirksES3ES2, int ctpES3ES2) { this.device = dev; - // this.drawable = draw; // this.contextES1 = ctxES1; - // this.contextES2 = ctxES2; this.wasES1ContextCreated = wasContextES1Created; + this.hasPBufferES1= hasPBufferES1; + this.rendererQuirksES1 = rendererQuirksES1; + this.ctpES1 = ctpES1; + + // this.contextES2 = ctxES2; + // this.contextES3 = ctxES3; this.wasES2ContextCreated = wasContextES2Created; + this.wasES3ContextCreated = wasContextES3Created; + this.hasPBufferES3ES2= hasPBufferES3ES2; + this.rendererQuirksES3ES2 = rendererQuirksES3ES2; + this.ctpES3ES2 = ctpES3ES2; } - final EGLGraphicsDevice getDevice() { return device; } - // final EGLDrawable getDrawable() { return drawable; } + @Override + public final boolean isValid() { + return wasES1ContextCreated || wasES2ContextCreated || wasES3ContextCreated; + } + @Override + public final EGLGraphicsDevice getDevice() { return device; } // final EGLContext getContextES1() { return contextES1; } // final EGLContext getContextES2() { return contextES2; } - final boolean wasES1ContextAvailable() { return wasES1ContextCreated; } - final boolean wasES2ContextAvailable() { return wasES2ContextCreated; } + // final EGLContext getContextES3() { return contextES3; } + + @Override + public AbstractGraphicsScreen getScreen() { + return null; + } + @Override + public GLDrawableImpl getDrawable() { + return null; + } + @Override + public GLContextImpl getContext() { + return null; + } + @Override + public GLRendererQuirks getRendererQuirks() { + return null != rendererQuirksES3ES2 ? rendererQuirksES3ES2 : rendererQuirksES1 ; + } } + @Override public final AbstractGraphicsDevice getDefaultDevice() { return defaultDevice; } + @Override public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) { // via mappings (X11/WGL/.. -> EGL) we shall be able to handle all types. - return null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper; + return null != sharedMap ; // null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper; } - /** - private boolean isEGLContextAvailable(EGLGraphicsDevice sharedDevice, String profile) { - boolean madeCurrent = false; - final GLCapabilities caps = new GLCapabilities(GLProfile.get(profile)); - caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); - caps.setDoubleBuffered(false); - caps.setOnscreen(false); - caps.setPBuffer(true); - final EGLDrawable drawable = (EGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) ); - if(null!=drawable) { - final EGLContext context = (EGLContext) drawable.createContext(null); - if (null != context) { - context.setSynchronized(true); - try { - context.makeCurrent(); // could cause exception - madeCurrent = context.isCurrent(); - } catch (GLException gle) { - if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: INFO: makeCurrent failed"); - gle.printStackTrace(); - } - } finally { - context.destroy(); - } + private static List<GLCapabilitiesImmutable> getAvailableEGLConfigs(EGLGraphicsDevice eglDisplay, GLCapabilitiesImmutable caps) { + final IntBuffer numConfigs = Buffers.newDirectIntBuffer(1); + if(!EGL.eglGetConfigs(eglDisplay.getHandle(), null, 0, numConfigs)) { + throw new GLException("EGLDrawableFactory.getAvailableEGLConfigs: Get maxConfigs (eglGetConfigs) call failed, error "+EGLContext.toHexString(EGL.eglGetError())); + } + if(0 < numConfigs.get(0)) { + final PointerBuffer configs = PointerBuffer.allocateDirect(numConfigs.get(0)); + final IntBuffer attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(caps); + final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(caps); + if( EGL.eglChooseConfig(eglDisplay.getHandle(), attrs, configs, configs.capacity(), numConfigs) && numConfigs.get(0) > 0) { + return EGLGraphicsConfigurationFactory.eglConfigs2GLCaps(eglDisplay, caps.getGLProfile(), configs, numConfigs.get(0), winattrmask, false /* forceTransparentFlag */, false /* onlyFirstValid */); } - drawable.destroy(); } - return madeCurrent; - } */ - - /* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) { - if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) { - return null; + return new ArrayList<GLCapabilitiesImmutable>(0); + } + + private static void dumpEGLInfo(final String prefix, final long eglDisplay) { + final String eglVendor = EGL.eglQueryString(eglDisplay, EGL.EGL_VENDOR); + final String eglClientAPIs = EGL.eglQueryString(eglDisplay, EGL.EGL_CLIENT_APIS); + final String eglVersion = EGL.eglQueryString(eglDisplay, EGL.EGL_VERSION); + System.err.println(prefix+"EGL vendor "+eglVendor+", version "+eglVersion+", clientAPIs "+eglClientAPIs); + } + + private boolean mapAvailableEGLESConfig(AbstractGraphicsDevice adevice, int[] esProfile, + boolean[] hasPBuffer, GLRendererQuirks[] rendererQuirks, int[] ctp) { + final String profileString; + switch( esProfile[0] ) { + case 3: + profileString = GLProfile.GLES3; break; + case 2: + profileString = GLProfile.GLES2; break; + case 1: + profileString = GLProfile.GLES1; break; + default: + throw new GLException("Invalid ES profile number "+esProfile); } - String connection = adevice.getConnection(); - SharedResource sr; - synchronized(sharedMap) { - sr = (SharedResource) sharedMap.get(connection); - } - if(null==sr) { - long eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Failed to created EGL default display: error 0x"+Integer.toHexString(EGL.eglGetError())); - } else if(DEBUG) { - System.err.println("EGLDrawableFactory.createShared: eglDisplay(EGL_DEFAULT_DISPLAY): 0x"+Long.toHexString(eglDisplay)); + if ( !GLProfile.isAvailable(adevice, profileString) ) { + if( DEBUG ) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" n/a on "+adevice); } - if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { - throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + return false; + } + final GLProfile glp = GLProfile.get(adevice, profileString) ; + final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory(); + final boolean initDefaultDevice = 0 == defaultDevice.getHandle(); // Note: GLProfile always triggers EGL device initialization first! + final boolean mapsADeviceToDefaultDevice = !QUERY_EGL_ES_NATIVE_TK || initDefaultDevice || + null == desktopFactory || adevice instanceof EGLGraphicsDevice ; + if( DEBUG ) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" ( "+esProfile+" ), "+ + "defaultSharedResourceSet "+(null!=defaultSharedResource)+", mapsADeviceToDefaultDevice "+mapsADeviceToDefaultDevice+ + " (QUERY_EGL_ES_NATIVE_TK "+QUERY_EGL_ES_NATIVE_TK+", hasDesktopFactory "+(null != desktopFactory)+ + ", isEGLGraphicsDevice "+(adevice instanceof EGLGraphicsDevice)+")"); + } + + EGLGraphicsDevice eglDevice = null; + NativeSurface surface = null; + ProxySurface upstreamSurface = null; // X11, GLX, .. + ProxySurface downstreamSurface = null; // EGL + boolean success = false; + try { + final GLCapabilities reqCapsAny = new GLCapabilities(glp); + reqCapsAny.setRedBits(5); reqCapsAny.setGreenBits(5); reqCapsAny.setBlueBits(5); reqCapsAny.setAlphaBits(0); + reqCapsAny.setDoubleBuffered(false); + + if( mapsADeviceToDefaultDevice ) { + // In this branch, any non EGL device is mapped to EGL default shared resources (default behavior). + // Only one default shared resource instance is ever be created. + if( initDefaultDevice ) { + defaultDevice.open(); + + // Probe for GLRendererQuirks.SingletonEGLDisplayOnly + final long secondEGLDisplay = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); + if ( EGL.EGL_NO_DISPLAY == secondEGLDisplay ) { + final int[] quirks = { GLRendererQuirks.SingletonEGLDisplayOnly }; + GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, 0, 1); + EGLDisplayUtil.setSingletonEGLDisplayOnly(true); + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirks[0])+": cause: Second eglGetDisplay(EGL_DEFAULT_DISPLAY) failed"); + } + } + } + if( DEBUG ) { + dumpEGLInfo("EGLDrawableFactory.mapAvailableEGLESConfig: ", defaultDevice.getHandle()); + } + + final GLCapabilitiesImmutable reqCapsPBuffer = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(reqCapsAny); + final List<GLCapabilitiesImmutable> availablePBufferCapsL = getAvailableEGLConfigs(defaultDevice, reqCapsPBuffer); + hasPBuffer[0] = availablePBufferCapsL.size() > 0; + + // 1st case: adevice is not the EGL default device, map default shared resources + if( adevice != defaultDevice ) { + if(null == defaultSharedResource) { + return false; + } + switch(esProfile[0]) { + case 3: + if( !defaultSharedResource.wasES3ContextCreated ) { + return false; + } + rendererQuirks[0] = defaultSharedResource.rendererQuirksES3ES2; + ctp[0] = defaultSharedResource.ctpES3ES2; + break; + case 2: + if( !defaultSharedResource.wasES2ContextCreated ) { + return false; + } + rendererQuirks[0] = defaultSharedResource.rendererQuirksES3ES2; + ctp[0] = defaultSharedResource.ctpES3ES2; + break; + case 1: + if( !defaultSharedResource.wasES1ContextCreated ) { + return false; + } + rendererQuirks[0] = defaultSharedResource.rendererQuirksES1; + ctp[0] = defaultSharedResource.ctpES1; + break; + } + if( null != rendererQuirks[0] ) { + GLRendererQuirks.addStickyDeviceQuirks(adevice, rendererQuirks[0]); + } + EGLContext.mapStaticGLVersion(adevice, esProfile[0], 0, ctp[0]); + return true; + } + + // attempt to created the default shared resources .. + + if( hasPBuffer[0] ) { + // 2nd case create defaultDevice shared resource using pbuffer surface + downstreamSurface = createDummySurfaceImpl(defaultDevice, false, reqCapsPBuffer, reqCapsPBuffer, null, 64, 64); // egl pbuffer offscreen + if( null != downstreamSurface ) { + downstreamSurface.createNotify(); + } + surface = downstreamSurface; + } else { + // 3rd case fake creation of defaultDevice shared resource, no pbuffer available + final List<GLCapabilitiesImmutable> capsAnyL = getAvailableEGLConfigs(defaultDevice, reqCapsAny); + if(capsAnyL.size() > 0) { + final GLCapabilitiesImmutable chosenCaps = capsAnyL.get(0); + EGLContext.mapStaticGLESVersion(defaultDevice, chosenCaps); + success = true; + } + if(DEBUG) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig() no pbuffer config available, detected !pbuffer config: "+success); + EGLGraphicsConfigurationFactory.printCaps("!PBufferCaps", capsAnyL, System.err); + } + } + eglDevice = defaultDevice; // reuse + } else { + // 4th case always creates a true mapping of given device to EGL + upstreamSurface = desktopFactory.createDummySurface(adevice, reqCapsAny, null, 64, 64); // X11, WGL, .. dummy window + if(null != upstreamSurface) { + upstreamSurface.createNotify(); + } + surface = upstreamSurface; + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface); + eglDevice.open(); + if( DEBUG ) { + dumpEGLInfo("EGLDrawableFactory.mapAvailableEGLESConfig: ", eglDevice.getHandle()); + } + hasPBuffer[0] = true; } - final EGLGraphicsDevice sharedDevice = new EGLGraphicsDevice(eglDisplay, connection, adevice.getUnitID()); - // final boolean madeCurrentES1 = isEGLContextAvailable(sharedDevice, GLProfile.GLES1); - // final boolean madeCurrentES2 = isEGLContextAvailable(sharedDevice, GLProfile.GLES2); - final boolean madeCurrentES1 = true; // FIXME - final boolean madeCurrentES2 = true; // FIXME - sr = new SharedResource(sharedDevice, madeCurrentES1, madeCurrentES2); - synchronized(sharedMap) { - sharedMap.put(connection, sr); + + if(null != surface) { + final EGLDrawable drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface ); // works w/ implicit pbuffer surface via proxy-hook + drawable.setRealized(true); + final EGLContext context = (EGLContext) drawable.createContext(null); + if (null != context) { + try { + context.makeCurrent(); // could cause exception + if(context.isCurrent()) { + final String glVersion = context.getGL().glGetString(GL.GL_VERSION); + if(null != glVersion) { + context.mapCurrentAvailableGLVersion(eglDevice); + if(eglDevice != adevice) { + context.mapCurrentAvailableGLVersion(adevice); + } + rendererQuirks[0] = context.getRendererQuirks(); + ctp[0] = context.getContextOptions(); + esProfile[0] = context.getGLVersionNumber().getMajor(); + success = true; + } else { + // Oops .. something is wrong + if(DEBUG) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!"); + } + } + } + } catch (Throwable t) { + if (DEBUG) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: INFO: context create/makeCurrent failed"); + t.printStackTrace(); + } + } finally { + context.destroy(); + } + } + drawable.setRealized(false); + } + } catch (Throwable t) { + if(DEBUG) { + System.err.println("Catched Exception on thread "+getThreadName()); + t.printStackTrace(); + } + success = false; + } finally { + if(null != downstreamSurface) { + downstreamSurface.destroyNotify(); + } + if( defaultDevice != eglDevice ) { // don't close default device + if(null != eglDevice) { + eglDevice.close(); + } + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } } - if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: device: " + sharedDevice); - System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1); - System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2); - } } - return sr; + return success; } - protected final Thread getSharedResourceThread() { - return null; + private final boolean needsToCreateSharedResource(String key, SharedResource[] existing) { + synchronized(sharedMap) { + final SharedResource sr = sharedMap.get(key); + if( null == sr ) { + final boolean createAttempted = sharedMapCreateAttempt.contains(key); + if(!createAttempted) { + sharedMapCreateAttempt.add(key); + } + return !createAttempted; + } else { + if(null != existing) { + existing[0] = sr; + } + return false; + } + } } - - protected final boolean createSharedResource(AbstractGraphicsDevice device) { - try { - SharedResource sr = getOrCreateEGLSharedResource(device); - if(null!=sr) { - return sr.wasES1ContextAvailable() || sr.wasES2ContextAvailable(); + + @Override + protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice adevice) { + if(null == sharedMap) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper + return null; + } + + if( needsToCreateSharedResource(defaultDevice.getUniqueID(), null) ) { + if (DEBUG) { + System.err.println("EGLDrawableFactory.createShared: (defaultDevice): req. device: "+adevice+", defaultDevice "+defaultDevice); + Thread.dumpStack(); } - } catch (GLException gle) { - if(DEBUG) { - System.err.println("Catched Exception while EGL Shared Resource initialization"); - gle.printStackTrace(); + if(null != defaultSharedResource) { + dumpMap(); + throw new InternalError("defaultSharedResource already exist: "+defaultSharedResource); } + defaultSharedResource = createEGLSharedResourceImpl(defaultDevice); + } + + final String key = adevice.getUniqueID(); + if( defaultDevice.getUniqueID().equals(key) ) { + return defaultSharedResource; + } else { + if( null == defaultSharedResource) { // defaultDevice must be initialized before host-device + dumpMap(); + throw new InternalError("defaultSharedResource does not exist"); + } + final SharedResource[] existing = new SharedResource[] { null }; + if ( !needsToCreateSharedResource(key, existing) ) { + return existing[0]; + } + return createEGLSharedResourceImpl(adevice); } - return false; } - - protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) { - return null; // n/a for EGL .. since we don't keep the resources + + private SharedResource createEGLSharedResourceImpl(AbstractGraphicsDevice adevice) { + final boolean madeCurrentES1; + boolean[] hasPBufferES1 = new boolean[] { false }; + boolean[] hasPBufferES3ES2 = new boolean[] { false }; + // EGLContext[] eglCtxES1 = new EGLContext[] { null }; + // EGLContext[] eglCtxES2 = new EGLContext[] { null }; + GLRendererQuirks[] rendererQuirksES1 = new GLRendererQuirks[] { null }; + GLRendererQuirks[] rendererQuirksES3ES2 = new GLRendererQuirks[] { null }; + int[] ctpES1 = new int[] { -1 }; + int[] ctpES3ES2 = new int[] { -1 }; + + + if (DEBUG) { + System.err.println("EGLDrawableFactory.createShared(): device "+adevice); + } + + if( null != eglES1DynamicLookupHelper ) { + final int[] esProfile = { 1 }; + madeCurrentES1 = mapAvailableEGLESConfig(adevice, esProfile, hasPBufferES1, rendererQuirksES1, ctpES1) && 1 == esProfile[0]; + } else { + madeCurrentES1 = false; + } + boolean madeCurrentES2 = false; + boolean madeCurrentES3 = false; + if( null != eglES2DynamicLookupHelper ) { + // ES3 Query + final int[] esProfile = { 3 }; + madeCurrentES3 = mapAvailableEGLESConfig(adevice, esProfile, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2) && 3 == esProfile[0]; + if( !madeCurrentES3 ) { + // ES2 Query, may result in ES3 + esProfile[0] = 2; + if( mapAvailableEGLESConfig(adevice, esProfile, hasPBufferES3ES2, rendererQuirksES3ES2, ctpES3ES2) ) { + switch( esProfile[0] ) { + case 2: madeCurrentES2 = true; break; + case 3: madeCurrentES3 = true; break; + default: throw new InternalError("XXXX Got "+esProfile[0]); + } + } + } + } + if( !EGLContext.getAvailableGLVersionsSet(adevice) ) { + // Even though we override the non EGL native mapping intentionally, + // avoid exception due to double 'set' - carefull exception of the rule. + EGLContext.setAvailableGLVersionsSet(adevice); + } + if( hasX11 ) { + handleDontCloseX11DisplayQuirk(rendererQuirksES1[0]); + handleDontCloseX11DisplayQuirk(rendererQuirksES3ES2[0]); + } + final SharedResource sr = new SharedResource(defaultDevice, madeCurrentES1, hasPBufferES1[0], rendererQuirksES1[0], ctpES1[0], + madeCurrentES2, madeCurrentES3, hasPBufferES3ES2[0], rendererQuirksES3ES2[0], ctpES3ES2[0]); + + synchronized(sharedMap) { + sharedMap.put(adevice.getUniqueID(), sr); + } + if (DEBUG) { + System.err.println("EGLDrawableFactory.createShared: devices: queried nativeTK "+QUERY_EGL_ES_NATIVE_TK+", adevice " + adevice + ", defaultDevice " + defaultDevice); + System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1 + ", hasPBuffer "+hasPBufferES1[0]+", quirks "+rendererQuirksES1[0]); + System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2 + ", hasPBuffer "+hasPBufferES3ES2[0]+", quirks "+rendererQuirksES3ES2[0]); + System.err.println("EGLDrawableFactory.createShared: context ES3: " + madeCurrentES3 + ", hasPBuffer "+hasPBufferES3ES2[0]+", quirks "+rendererQuirksES3ES2[0]); + dumpMap(); + } + return sr; } - - protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateEGLSharedResource(device); - if(null!=sr) { - return sr.getDevice(); + + private void handleDontCloseX11DisplayQuirk(GLRendererQuirks quirks) { + if( null != quirks && quirks.exist( GLRendererQuirks.DontCloseX11Display ) ) { + jogamp.nativewindow.x11.X11Util.markAllDisplaysUnclosable(); } + } + + @Override + protected final Thread getSharedResourceThread() { return null; } - public boolean isANGLE() { + public final boolean isANGLE() { return isANGLE; } - + + @Override public GLDynamicLookupHelper getGLDynamicLookupHelper(int esProfile) { - if (2==esProfile) { + if ( 2==esProfile || 3==esProfile ) { return eglES2DynamicLookupHelper; } else if (1==esProfile) { return eglES1DynamicLookupHelper; @@ -343,20 +708,23 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } } + @Override protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) { - if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) { + if(null == sharedMap) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper return new ArrayList<GLCapabilitiesImmutable>(); // null } return EGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device); } + @Override protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { if (target == null) { throw new IllegalArgumentException("Null target"); } - return new EGLOnscreenDrawable(this, target); + return new EGLOnscreenDrawable(this, EGLWrappedSurface.get(target)); } + @Override protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) { if (target == null) { throw new IllegalArgumentException("Null target"); @@ -367,47 +735,104 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { throw new GLException("Non pbuffer not yet implemented"); } // PBuffer GLDrawable Creation - return new EGLPbufferDrawable(this, target); + return new EGLPbufferDrawable(this, EGLWrappedSurface.get(target)); } - public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + @Override + public boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp) { + // SharedResource sr = getOrCreateEGLSharedResource(device); + // return sr.hasES1PBuffer() || sr.hasES2PBuffer(); return true; } - protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { - WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser)); - ns.surfaceSizeChanged(width, height); - return ns; + @Override + protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) { + final boolean ownDevice; + 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; + } else { + device = (EGLGraphicsDevice) deviceReq; + ownDevice = 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); + } + + @Override + public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable chosenCaps, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { + chosenCaps = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(chosenCaps); // complete validation in EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(..) above + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new EGLDummyUpstreamSurfaceHook(width, height)); + } + + /** + * @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. + * @param useTexture + * @return the passed {@link MutableSurface} which now has the EGL pbuffer surface set as it's handle + */ + protected static MutableSurface createPBufferSurfaceImpl(MutableSurface ms, boolean useTexture) { + return null; + } + protected static long createPBufferSurfaceImpl(EGLGraphicsConfiguration config, int width, int height, boolean useTexture) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final int texFormat; + + if(useTexture) { + texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; + } else { + texFormat = EGL.EGL_NO_TEXTURE; + } + + if (DEBUG) { + System.out.println("Pbuffer config: " + config); + } + + final IntBuffer attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(width, height, texFormat); + final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs); + if (EGL.EGL_NO_SURFACE==surf) { + throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+width+"x"+height+", "+eglDevice+", "+config+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf)); + } + return surf; } - protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { - // FIXME device/windowHandle -> screen ?! - EGLGraphicsDevice device = (EGLGraphicsDevice) adevice; - DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); - EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); - WrappedSurface ns = new WrappedSurface(cfg, windowHandle); - return ns; + @Override + protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, 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); } - + + @Override protected GLContext createExternalGLContextImpl() { AbstractGraphicsScreen absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_EGL); return new EGLExternalContext(absScreen); } + @Override public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { return false; } + @Override protected GLDrawable createExternalGLDrawableImpl() { throw new GLException("Not yet implemented"); } - - public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { - return false; - } - - public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) - throws GLException { - throw new GLException("Unimplemented on this platform"); - } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java new file mode 100644 index 000000000..818f32607 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java @@ -0,0 +1,60 @@ +package jogamp.opengl.egl; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; + +/** Uses a PBuffer offscreen surface */ +public class EGLDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { + /** + * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public EGLDummyUpstreamSurfaceHook(int width, int height) { + super(width, height); + } + + @Override + public final void create(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() ) { + s.setSurfaceHandle( EGLDrawableFactory.createPBufferSurfaceImpl((EGLGraphicsConfiguration)s.getGraphicsConfiguration(), 64, 64, false) ); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + } finally { + eglDevice.unlock(); + } + } + + @Override + public final void destroy(ProxySurface s) { + if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) { + throw new InternalError("Owns upstream surface, but no EGL surface: "+s); + } + eglDevice.lock(); + try { + EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle()); + s.setSurfaceHandle(EGL.EGL_NO_SURFACE); + s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } finally { + eglDevice.unlock(); + } + } + } +} diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java index fe9d7573d..ebe8f49c8 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java @@ -3,14 +3,14 @@ * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR @@ -20,15 +20,16 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ - + package jogamp.opengl.egl; import com.jogamp.common.os.AndroidVersion; +import com.jogamp.common.os.Platform; import java.util.*; @@ -38,10 +39,10 @@ import jogamp.opengl.*; * Abstract implementation of the DynamicLookupHelper for EGL, * which decouples it's dependencies to EGLDrawable. * - * Currently two implementations exist, one for ES1 and one for ES2. + * Currently two implementations exist, one for ES1 and one for ES3 and ES2. */ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo { - static List<String> glueLibNames; + static final List<String> glueLibNames; static { glueLibNames = new ArrayList<String>(); glueLibNames.add("jogl_mobile"); @@ -51,27 +52,23 @@ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundle super(); } - /** - * Might be a desktop GL library, and might need to allow symbol access to subsequent libs. - * - * This respects old DRI requirements:<br> - * <pre> - * http://dri.sourceforge.net/doc/DRIuserguide.html - * </pre> + /** + * Returns <code>true</code> on <code>Android</code>, + * and <code>false</code> otherwise. + * <p> + * {@inheritDoc} + * </p> */ @Override - public boolean shallLinkGlobal() { return true; } - - @Override - public boolean shallLookupGlobal() { - if ( AndroidVersion.isAvailable ) { + public final boolean shallLookupGlobal() { + if ( Platform.OSType.ANDROID == Platform.OS_TYPE ) { // Android requires global symbol lookup return true; } // default behavior for other platforms return false; } - + @Override public final List<String> getToolGetProcAddressFuncNameList() { List<String> res = new ArrayList<String>(); @@ -93,26 +90,26 @@ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundle return true; } } - - protected List<String> getEGLLibNamesList() { + + protected final List<String> getEGLLibNamesList() { List<String> eglLibNames = new ArrayList<String>(); - - // this is the default EGL lib name, according to the spec + + // this is the default EGL lib name, according to the spec eglLibNames.add("libEGL.so.1"); - + // try these as well, if spec fails eglLibNames.add("libEGL.so"); eglLibNames.add("EGL"); - - // for windows distributions using the 'unlike' lib prefix, + + // for windows distributions using the 'unlike' lib prefix, // where our tool does not add it. eglLibNames.add("libEGL"); - + return eglLibNames; } @Override public final List<String> getGlueLibNames() { return glueLibNames; - } + } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java index 0a373eb7f..361ec26ff 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java @@ -3,14 +3,14 @@ * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR @@ -20,48 +20,49 @@ * 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.util.*; -public class EGLES1DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo { +public final class EGLES1DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo { protected EGLES1DynamicLibraryBundleInfo() { super(); } - public List<List<String>> getToolLibNames() { + @Override + public final List<List<String>> getToolLibNames() { final List<List<String>> libsList = new ArrayList<List<String>>(); { final List<String> libsGL = new ArrayList<String>(); - - // this is the default lib name, according to the spec + + // this is the default lib name, according to the spec libsGL.add("libGLESv1_CM.so.2"); - + // try these as well, if spec fails libsGL.add("libGLESv1_CM.so"); - libsGL.add("GLESv1_CM"); + libsGL.add("GLESv1_CM"); // alternative names libsGL.add("GLES_CM"); libsGL.add("GLES_CL"); - - // for windows distributions using the 'unlike' lib prefix, + + // for windows distributions using the 'unlike' lib prefix, // where our tool does not add it. libsGL.add("libGLESv1_CM"); libsGL.add("libGLES_CM"); libsGL.add("libGLES_CL"); - + libsList.add(libsGL); } libsList.add(getEGLLibNamesList()); - + return libsList; - } + } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java index d4ee852b1..74738463f 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java @@ -3,14 +3,14 @@ * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR @@ -20,49 +20,70 @@ * 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.util.*; -public class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo { +/** + * <p> + * Covering ES3 and ES2. + * </p> + */ +public final class EGLES2DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo { protected EGLES2DynamicLibraryBundleInfo() { super(); } - public List<List<String>> getToolLibNames() { + @Override + public final List<List<String>> getToolLibNames() { final List<List<String>> libsList = new ArrayList<List<String>>(); { final List<String> libsGL = new ArrayList<String>(); - - // this is the default lib name, according to the spec + + // ES3: This is the default lib name, according to the spec + libsGL.add("libGLESv3.so.3"); + + // ES3: Try these as well, if spec fails + libsGL.add("libGLESv3.so"); + libsGL.add("GLESv3"); + + // ES3: Alternative names + libsGL.add("GLES30"); + + // ES3: For windows distributions using the 'unlike' lib prefix + // where our tool does not add it. + libsGL.add("libGLESv3"); + libsGL.add("libGLES30"); + + // ES2: This is the default lib name, according to the spec libsGL.add("libGLESv2.so.2"); - - // try these as well, if spec fails - libsGL.add("libGLESv2.so"); + + // ES2: Try these as well, if spec fails + libsGL.add("libGLESv2.so"); libsGL.add("GLESv2"); - // alternative names + // ES2: Alternative names libsGL.add("GLES20"); libsGL.add("GLESv2_CM"); - // for windows distributions using the 'unlike' lib prefix + // ES2: For windows distributions using the 'unlike' lib prefix // where our tool does not add it. libsGL.add("libGLESv2"); libsGL.add("libGLESv2_CM"); - libsGL.add("libGLES20"); - + libsGL.add("libGLES20"); + libsList.add(libsGL); } libsList.add(getEGLLibNamesList()); - + return libsList; - } - + } + } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java index ff60a5262..aff18fc81 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java @@ -1,21 +1,21 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -28,7 +28,7 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -36,51 +36,27 @@ package jogamp.opengl.egl; import javax.media.opengl.*; + import jogamp.opengl.*; + import javax.media.nativewindow.*; public class EGLExternalContext extends EGLContext { - private GLContext lastContext; public EGLExternalContext(AbstractGraphicsScreen screen) { super(null, null); GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_IS_ARB_CREATED|CTX_PROFILE_ES); - getGLStateTracker().setEnabled(false); // external context usage can't track state in Java - } - - public int makeCurrent() throws GLException { - // Save last context if necessary to allow external GLContexts to - // talk to other GLContexts created by this library - GLContext cur = getCurrent(); - if (cur != null && cur != this) { - lastContext = cur; - setCurrent(null); + if( !setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION + throw new InternalError("setGLFunctionAvailability !strictMatch failed"); } - return super.makeCurrent(); - } - - public void release() throws GLException { - super.release(); - setCurrent(lastContext); - lastContext = null; - } - - protected void makeCurrentImpl() throws GLException { + getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } + @Override protected void releaseImpl() throws GLException { } + @Override protected void destroyImpl() throws GLException { } - - public void bindPbufferToTexture() { - throw new GLException("Should not call this"); - } - - public void releasePbufferFromTexture() { - throw new GLException("Should not call this"); - } - } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java index f813edf86..e28b53235 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java @@ -33,39 +33,43 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; + public class EGLGLCapabilities extends GLCapabilities { private long eglcfg; final private int eglcfgid; - final private int renderableType; + final private int renderableType; final private int nativeVisualID; - + /** - * + * * @param eglcfg * @param eglcfgid * @param visualID native visualID if valid, otherwise VisualIDHolder.VID_UNDEFINED - * @param glp desired GLProfile, or null if determined by renderableType + * @param glp desired GLProfile * @param renderableType actual EGL renderableType - * + * * May throw GLException if given GLProfile is not compatible w/ renderableType */ public EGLGLCapabilities(long eglcfg, int eglcfgid, int visualID, GLProfile glp, int renderableType) { - super( ( null != glp ) ? glp : getCompatible(renderableType) ); + super( glp ); this.eglcfg = eglcfg; this.eglcfgid = eglcfgid; if(!isCompatible(glp, renderableType)) { - throw new GLException("Incompatible "+glp+ - " with EGL-RenderableType["+renderableTypeToString(null, renderableType)+"]"); + throw new GLException("Requested GLProfile "+glp+ + " not compatible with EGL-RenderableType["+renderableTypeToString(null, renderableType)+"]"); } this.renderableType = renderableType; this.nativeVisualID = visualID; } + @Override public Object cloneMutable() { return clone(); } + @Override public Object clone() { try { return super.clone(); @@ -73,13 +77,13 @@ public class EGLGLCapabilities extends GLCapabilities { throw new GLException(e); } } - + final protected void setEGLConfig(long v) { eglcfg=v; } final public long getEGLConfig() { return eglcfg; } final public int getEGLConfigID() { return eglcfgid; } final public int getRenderableType() { return renderableType; } final public int getNativeVisualID() { return nativeVisualID; } - + @Override final public int getVisualID(VIDType type) throws NativeWindowException { switch(type) { @@ -90,43 +94,50 @@ public class EGLGLCapabilities extends GLCapabilities { return getNativeVisualID(); default: throw new NativeWindowException("Invalid type <"+type+">"); - } + } } - + public static boolean isCompatible(GLProfile glp, int renderableType) { if(null == glp) { return true; } - if(0 != (renderableType & EGL.EGL_OPENGL_ES_BIT) && glp.usesNativeGLES1()) { + if(0 != (renderableType & EGLExt.EGL_OPENGL_ES3_BIT_KHR) && glp.usesNativeGLES3()) { return true; } if(0 != (renderableType & EGL.EGL_OPENGL_ES2_BIT) && glp.usesNativeGLES2()) { return true; } + if(0 != (renderableType & EGL.EGL_OPENGL_ES_BIT) && glp.usesNativeGLES1()) { + return true; + } if(0 != (renderableType & EGL.EGL_OPENGL_BIT) && !glp.usesNativeGLES()) { return true; } return false; } - public static GLProfile getCompatible(int renderableType) { - if(0 != (renderableType & EGL.EGL_OPENGL_ES2_BIT) && GLProfile.isAvailable(GLProfile.GLES2)) { - return GLProfile.get(GLProfile.GLES2); + public static GLProfile getCompatible(EGLGraphicsDevice device, int renderableType) { + if(0 != (renderableType & EGLExt.EGL_OPENGL_ES3_BIT_KHR) && GLProfile.isAvailable(device, GLProfile.GLES3)) { + return GLProfile.get(device, GLProfile.GLES3); + } + if(0 != (renderableType & EGL.EGL_OPENGL_ES2_BIT) && GLProfile.isAvailable(device, GLProfile.GLES2)) { + return GLProfile.get(device, GLProfile.GLES2); } - if(0 != (renderableType & EGL.EGL_OPENGL_ES_BIT) && GLProfile.isAvailable(GLProfile.GLES1)) { - return GLProfile.get(GLProfile.GLES1); + if(0 != (renderableType & EGL.EGL_OPENGL_ES_BIT) && GLProfile.isAvailable(device, GLProfile.GLES1)) { + return GLProfile.get(device, GLProfile.GLES1); } if(0 != (renderableType & EGL.EGL_OPENGL_BIT)) { - return GLProfile.getDefault(); + return GLProfile.getDefault(device); } return null; } - + public static StringBuilder renderableTypeToString(StringBuilder sink, int renderableType) { if(null == sink) { sink = new StringBuilder(); } boolean first=true; + sink.append("0x").append(Integer.toHexString(renderableType)).append(": "); if(0 != (renderableType & EGL.EGL_OPENGL_BIT)) { sink.append("GL"); first=false; } @@ -136,12 +147,16 @@ public class EGLGLCapabilities extends GLCapabilities { if(0 != (renderableType & EGL.EGL_OPENGL_ES2_BIT)) { if(!first) sink.append(", "); sink.append("GLES2"); first=false; } + if(0 != (renderableType & EGLExt.EGL_OPENGL_ES3_BIT_KHR)) { + if(!first) sink.append(", "); sink.append("GLES3"); first=false; + } if(0 != (renderableType & EGL.EGL_OPENVG_API)) { if(!first) sink.append(", "); sink.append("VG"); first=false; } - return sink; + return sink; } - + + @Override public StringBuilder toString(StringBuilder sink) { if(null == sink) { sink = new StringBuilder(); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 875bcb95b..88ed0be92 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2010 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -29,7 +29,7 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -37,15 +37,16 @@ package jogamp.opengl.egl; import java.nio.IntBuffer; -import java.util.ArrayList; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.VisualIDHolder; import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; @@ -55,9 +56,14 @@ import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.GLRendererQuirks; public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { - + + private static final String dbgCfgFailIntro = "Info: EGLConfig could not retrieve "; + private static final String dbgCfgFailForConfig = " for config "; + private static final String dbgCfgFailError = ", error "; + public final long getNativeConfig() { return ((EGLGLCapabilities)capabilitiesChosen).getEGLConfig(); } @@ -66,13 +72,20 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple return ((EGLGLCapabilities)capabilitiesChosen).getEGLConfigID(); } - EGLGraphicsConfiguration(AbstractGraphicsScreen absScreen, + EGLGraphicsConfiguration(AbstractGraphicsScreen absScreen, EGLGLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { super(absScreen, capsChosen, capsRequested); this.chooser = chooser; } - public static EGLGraphicsConfiguration create(GLCapabilitiesImmutable capsRequested, AbstractGraphicsScreen absScreen, int cfgID) { + /** + * @param capsRequested + * @param absScreen + * @param eglConfigID {@link EGL#EGL_CONFIG_ID} for which the config is being created for. + * @return + * @throws GLException if invalid EGL display. + */ + public static EGLGraphicsConfiguration create(GLCapabilitiesImmutable capsRequested, AbstractGraphicsScreen absScreen, int eglConfigID) { final AbstractGraphicsDevice absDevice = absScreen.getDevice(); if(null==absDevice || !(absDevice instanceof EGLGraphicsDevice)) { throw new GLException("GraphicsDevice must be a valid EGLGraphicsDevice"); @@ -81,9 +94,11 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple if (dpy == EGL.EGL_NO_DISPLAY) { throw new GLException("Invalid EGL display: "+absDevice); } - final long cfg = EGLConfigId2EGLConfig(dpy, cfgID); + final long cfg = EGLConfigId2EGLConfig(dpy, eglConfigID); if(0 < cfg) { - final EGLGLCapabilities caps = EGLConfig2Capabilities(capsRequested.getGLProfile(), dpy, cfg, false, capsRequested.isOnscreen(), capsRequested.isPBuffer(), false); + final GLRendererQuirks defaultQuirks = GLRendererQuirks.getStickyDeviceQuirks( GLDrawableFactory.getEGLFactory().getDefaultDevice() ); + final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsRequested); + final EGLGLCapabilities caps = EGLConfig2Capabilities(defaultQuirks, (EGLGraphicsDevice)absDevice, capsRequested.getGLProfile(), cfg, winattrmask, false); return new EGLGraphicsConfiguration(absScreen, caps, capsRequested, new DefaultGLCapabilitiesChooser()); } return null; @@ -93,11 +108,12 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple public Object clone() { return super.clone(); } - + void updateGraphicsConfiguration() { + CapabilitiesImmutable capsChosen = getChosenCapabilities(); EGLGraphicsConfiguration newConfig = (EGLGraphicsConfiguration) - GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration( - getChosenCapabilities(), getRequestedCapabilities(), chooser, getScreen()); + GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), capsChosen).chooseGraphicsConfiguration( + capsChosen, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED); if(null!=newConfig) { // FIXME: setScreen( ... ); setChosenCapabilities(newConfig.getChosenCapabilities()); @@ -108,260 +124,379 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple } public static long EGLConfigId2EGLConfig(long display, int configID) { - int[] attrs = new int[] { + final IntBuffer attrs = Buffers.newDirectIntBuffer(new int[] { EGL.EGL_CONFIG_ID, configID, EGL.EGL_NONE - }; - PointerBuffer configs = PointerBuffer.allocateDirect(1); - int[] numConfigs = new int[1]; + }); + final PointerBuffer configs = PointerBuffer.allocateDirect(1); + final IntBuffer numConfigs = Buffers.newDirectIntBuffer(1); if (!EGL.eglChooseConfig(display, - attrs, 0, + attrs, configs, 1, - numConfigs, 0)) { + numConfigs)) { return 0; } - if (numConfigs[0] == 0) { + if (numConfigs.get(0) == 0) { return 0; } return configs.get(0); } - static int EGLConfigDrawableTypeBits(final long display, final long config) { + public static boolean isEGLConfigValid(long display, long config) { + if(0 == config) { + return false; + } + final IntBuffer val = Buffers.newDirectIntBuffer(1); + + // get the configID + if(!EGL.eglGetConfigAttrib(display, config, EGL.EGL_CONFIG_ID, val)) { + final int eglErr = EGL.eglGetError(); + if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_CONFIG_ID"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(eglErr)); + } + return false; + } + return true; + } + + static int EGLConfigDrawableTypeBits(final EGLGraphicsDevice device, final long config) { int val = 0; - int[] stype = new int[1]; - if(! EGL.eglGetConfigAttrib(display, config, EGL.EGL_SURFACE_TYPE, stype, 0)) { + final IntBuffer stype = Buffers.newDirectIntBuffer(1); + if(! EGL.eglGetConfigAttrib(device.getHandle(), config, EGL.EGL_SURFACE_TYPE, stype)) { throw new GLException("Could not determine EGL_SURFACE_TYPE"); } - if ( 0 != ( stype[0] & EGL.EGL_WINDOW_BIT ) ) { + final int _stype = stype.get(0); + if ( 0 != ( _stype & EGL.EGL_WINDOW_BIT ) ) { val |= GLGraphicsConfigurationUtil.WINDOW_BIT; } - if ( 0 != ( stype[0] & EGL.EGL_PIXMAP_BIT ) ) { + if ( 0 != ( _stype & EGL.EGL_PIXMAP_BIT ) ) { val |= GLGraphicsConfigurationUtil.BITMAP_BIT; } - if ( 0 != ( stype[0] & EGL.EGL_PBUFFER_BIT ) ) { - val |= GLGraphicsConfigurationUtil.PBUFFER_BIT; + if ( 0 != ( _stype & EGL.EGL_PBUFFER_BIT ) ) { + val |= GLGraphicsConfigurationUtil.PBUFFER_BIT | + GLGraphicsConfigurationUtil.FBO_BIT; } - return val; } - public static EGLGLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config, - boolean relaxed, boolean onscreen, boolean usePBuffer, boolean forceTransparentFlag) { - ArrayList bucket = new ArrayList(); - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); - if( EGLConfig2Capabilities(bucket, glp, display, config, winattrmask, forceTransparentFlag) ) { - return (EGLGLCapabilities) bucket.get(0); - } else if ( relaxed && EGLConfig2Capabilities(bucket, glp, display, config, GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag) ) { - return (EGLGLCapabilities) bucket.get(0); - } - return null; - } - - public static boolean EGLConfig2Capabilities(ArrayList capsBucket, - GLProfile glp, long display, long config, - int winattrmask, boolean forceTransparentFlag) { - final int allDrawableTypeBits = EGLConfigDrawableTypeBits(display, config); - final int drawableTypeBits = winattrmask & allDrawableTypeBits; - - if( 0 == drawableTypeBits ) { - return false; - } - - final IntBuffer val = Buffers.newDirectIntBuffer(1); + /** + * @param defaultQuirks GLRendererQuirks of the EGLDrawableFactory's defaultDevice + * @param device + * @param glp desired GLProfile, may be null + * @param config + * @param winattrmask + * @param forceTransparentFlag + * @return + */ + public static EGLGLCapabilities EGLConfig2Capabilities(GLRendererQuirks defaultQuirks, EGLGraphicsDevice device, GLProfile glp, + long config, int winattrmask, boolean forceTransparentFlag) { + final long display = device.getHandle(); final int cfgID; final int rType; final int visualID; - + + final int _attributes[] = { + EGL.EGL_CONFIG_ID, // 0 + EGL.EGL_RENDERABLE_TYPE, + EGL.EGL_NATIVE_VISUAL_ID, + EGL.EGL_CONFIG_CAVEAT, + EGL.EGL_RED_SIZE, // 4 + EGL.EGL_GREEN_SIZE, + EGL.EGL_BLUE_SIZE, + EGL.EGL_ALPHA_SIZE, // 7 + EGL.EGL_STENCIL_SIZE, // 8 + EGL.EGL_DEPTH_SIZE, + EGL.EGL_TRANSPARENT_TYPE, // 10 + EGL.EGL_TRANSPARENT_RED_VALUE, + EGL.EGL_TRANSPARENT_GREEN_VALUE, + EGL.EGL_TRANSPARENT_BLUE_VALUE, + EGL.EGL_SAMPLES, // 14 + EGLExt.EGL_COVERAGE_BUFFERS_NV, // 15 + EGLExt.EGL_COVERAGE_SAMPLES_NV + }; + final IntBuffer attributes = Buffers.newDirectIntBuffer(_attributes); + final IntBuffer values = Buffers.newDirectIntBuffer(attributes.remaining()); + EGL.eglGetConfigAttributes(display, config, attributes, values); + // get the configID - if(!EGL.eglGetConfigAttrib(display, config, EGL.EGL_CONFIG_ID, val)) { + if( EGL.EGL_CONFIG_ID != attributes.get(0) ) { if(DEBUG) { // FIXME: this happens on a ATI PC Emulation .. - System.err.println("EGL couldn't retrieve ConfigID for config "+toHexString(config)+", error "+toHexString(EGL.eglGetError())); + System.err.println(dbgCfgFailIntro+"ConfigID"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - return false; + return null; } - cfgID = val.get(0); - - if(!EGL.eglGetConfigAttrib(display, config, EGL.EGL_RENDERABLE_TYPE, val)) { + cfgID = values.get(0); + + if( EGL.EGL_RENDERABLE_TYPE != attributes.get(1) ) { if(DEBUG) { - System.err.println("EGL couldn't retrieve EGL_RENDERABLE_TYPE for config "+toHexString(config)+", error "+toHexString(EGL.eglGetError())); + System.err.println(dbgCfgFailIntro+"EGL_RENDERABLE_TYPE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - return false; + return null; } - rType = val.get(0); - - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_NATIVE_VISUAL_ID, val)) { - visualID = val.get(0); + { + final int rTypeOrig = values.get(1); + if( defaultQuirks.exist(GLRendererQuirks.GLES3ViaEGLES2Config) && 0 != ( EGL.EGL_OPENGL_ES2_BIT & rTypeOrig ) ) { + rType = rTypeOrig | EGLExt.EGL_OPENGL_ES3_BIT_KHR; + } else { + rType = rTypeOrig; + } + } + + if( EGL.EGL_NATIVE_VISUAL_ID == attributes.get(2) ) { + visualID = values.get(2); } else { + if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_NATIVE_VISUAL_ID"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); + } visualID = VisualIDHolder.VID_UNDEFINED; } - - EGLGLCapabilities caps = null; + + EGLGLCapabilities caps = null; try { + if(null == glp) { + glp = EGLGLCapabilities.getCompatible(device, rType); + } + if(!EGLGLCapabilities.isCompatible(glp, rType)) { + if(DEBUG) { + System.err.println("config "+toHexString(config)+": Requested GLProfile "+glp+ + " with quirks "+defaultQuirks+" not compatible with EGL-RenderableType["+EGLGLCapabilities.renderableTypeToString(null, rType)+"]"); + } + return null; + } caps = new EGLGLCapabilities(config, cfgID, visualID, glp, rType); } catch (GLException gle) { if(DEBUG) { System.err.println("config "+toHexString(config)+": "+gle); } - return false; - } - - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val)) { - caps.setRedBits(val.get(0)); + return null; } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val)) { - caps.setGreenBits(val.get(0)); + + if( EGL.EGL_CONFIG_CAVEAT == attributes.get(3) ) { + if( EGL.EGL_SLOW_CONFIG == values.get(3) ) { + caps.setHardwareAccelerated(false); + } + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_CONFIG_CAVEAT"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val)) { - caps.setBlueBits(val.get(0)); + // ALPHA shall be set at last - due to it's auto setting by the above (!opaque / samples) + if( EGL.EGL_RED_SIZE == attributes.get(4) ) { + caps.setRedBits(values.get(4)); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_RED_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val)) { - caps.setAlphaBits(val.get(0)); + if( EGL.EGL_GREEN_SIZE == attributes.get(5) ) { + caps.setGreenBits(values.get(5)); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_GREEN_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val)) { - caps.setStencilBits(val.get(0)); + if( EGL.EGL_BLUE_SIZE == attributes.get(6) ) { + caps.setBlueBits(values.get(6)); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_BLUE_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val)) { - caps.setDepthBits(val.get(0)); + if( EGL.EGL_ALPHA_SIZE == attributes.get(7) ) { + caps.setAlphaBits(values.get(7)); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_ALPHA_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_SAMPLES, val)) { - caps.setSampleBuffers(val.get(0)>0?true:false); - caps.setNumSamples(val.get(0)); + if( EGL.EGL_STENCIL_SIZE == attributes.get(8) ) { + caps.setStencilBits(values.get(8)); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_STENCIL_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - if(!caps.getSampleBuffers()) { - // try NV_coverage_sample extension - if(EGL.eglGetConfigAttrib(display, config, EGLExt.EGL_COVERAGE_BUFFERS_NV, val)) { - if(val.get(0)>0 && - EGL.eglGetConfigAttrib(display, config, EGLExt.EGL_COVERAGE_SAMPLES_NV, val)) { - caps.setSampleExtension(GLGraphicsConfigurationUtil.NV_coverage_sample); - caps.setSampleBuffers(true); - caps.setNumSamples(val.get(0)); - } - } + if( EGL.EGL_DEPTH_SIZE == attributes.get(9) ) { + caps.setDepthBits(values.get(9)); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_DEPTH_SIZE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - if(forceTransparentFlag) { + if( forceTransparentFlag ) { caps.setBackgroundOpaque(false); - } else if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_TYPE, val)) { - caps.setBackgroundOpaque(val.get(0) != EGL.EGL_TRANSPARENT_RGB); + } else if( EGL.EGL_TRANSPARENT_TYPE == attributes.get(10) ) { + caps.setBackgroundOpaque(values.get(10) != EGL.EGL_TRANSPARENT_RGB); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_TRANSPARENT_TYPE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } if(!caps.isBackgroundOpaque()) { - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_RED_VALUE, val)) { - caps.setTransparentRedValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0)); + if( EGL.EGL_TRANSPARENT_RED_VALUE == attributes.get(11) ) { + final int v = values.get(11); + caps.setTransparentRedValue(EGL.EGL_DONT_CARE==v?-1:v); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_TRANSPARENT_RED_VALUE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_GREEN_VALUE, val)) { - caps.setTransparentGreenValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0)); + if( EGL.EGL_TRANSPARENT_GREEN_VALUE == attributes.get(12) ) { + final int v = values.get(12); + caps.setTransparentGreenValue(EGL.EGL_DONT_CARE==v?-1:v); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_TRANSPARENT_GREEN_VALUE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_BLUE_VALUE, val)) { - caps.setTransparentBlueValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0)); + if( EGL.EGL_TRANSPARENT_BLUE_VALUE == attributes.get(13) ) { + final int v = values.get(13); + caps.setTransparentBlueValue(EGL.EGL_DONT_CARE==v?-1:v); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_TRANSPARENT_BLUE_VALUE"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); } - /** Not defined in EGL - if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_ALPHA_VALUE, val)) { - caps.setTransparentAlphaValue(val.get(0)==EGL.EGL_DONT_CARE?-1:val.get(0)); + /** Not defined in EGL + if( EGL.EGL_TRANSPARENT_ALPHA_VALUE == attributes.get(??) ) { + final int v = values.get(??); + caps.setTransparentAlphaValue(EGL.EGL_DONT_CARE==v?-1:v); + } else if(DEBUG) { + System.err.println(dbgStr01+"EGL_TRANSPARENT_ALPHA_VALUE"+dbgStr02+toHexString(config)+dbgEGLCfgFailError+toHexString(EGL.eglGetError())); } */ } - return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, caps, drawableTypeBits ); + if( EGL.EGL_SAMPLES == attributes.get(14) ) { + final int numSamples = values.get(14); + caps.setSampleBuffers(numSamples>0?true:false); + caps.setNumSamples(numSamples); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_SAMPLES"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); + } + if(!caps.getSampleBuffers()) { + // try NV_coverage_sample extension + if( EGLExt.EGL_COVERAGE_BUFFERS_NV == attributes.get(15) ) { + final boolean enabled = values.get(15) > 0; + if( enabled && EGLExt.EGL_COVERAGE_SAMPLES_NV == attributes.get(16) ) { + caps.setSampleExtension(GLGraphicsConfigurationUtil.NV_coverage_sample); + caps.setSampleBuffers(true); + caps.setNumSamples(values.get(16)); + } else if(DEBUG) { + System.err.println(dbgCfgFailIntro+"EGL_COVERAGE_SAMPLES_NV"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); + } + } /** else if(DEBUG) { // Not required - vendor extension - don't be verbose! + System.err.println(dbgCfgFailIntro+"EGL_COVERAGE_BUFFERS_NV"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(EGL.eglGetError())); + } */ + } + + // Since the passed GLProfile may be null, + // we use EGL_RENDERABLE_TYPE derived profile as created in the EGLGLCapabilities constructor. + final int availableTypeBits = EGLConfigDrawableTypeBits(device, config); + final int drawableTypeBits = winattrmask & availableTypeBits; + + if( 0 == drawableTypeBits ) { + return null; + } + + return (EGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, caps); } - public static int[] GLCapabilities2AttribList(GLCapabilitiesImmutable caps) { - int[] attrs = new int[32]; + public static IntBuffer GLCapabilities2AttribList(GLCapabilitiesImmutable caps) { + final IntBuffer attrs = Buffers.newDirectIntBuffer(32); int idx=0; - attrs[idx++] = EGL.EGL_SURFACE_TYPE; - attrs[idx++] = caps.isOnscreen() ? ( EGL.EGL_WINDOW_BIT ) : ( caps.isPBuffer() ? EGL.EGL_PBUFFER_BIT : EGL.EGL_PIXMAP_BIT ) ; + attrs.put(idx++, EGL.EGL_SURFACE_TYPE); + final int surfaceType; + if( caps.isOnscreen() ) { + surfaceType = EGL.EGL_WINDOW_BIT; + } else if( caps.isFBO() ) { + surfaceType = EGL.EGL_PBUFFER_BIT; // native replacement! + } else if( caps.isPBuffer() ) { + surfaceType = EGL.EGL_PBUFFER_BIT; + } else if( caps.isBitmap() ) { + surfaceType = EGL.EGL_PIXMAP_BIT; + } else { + throw new GLException("no surface type set in caps: "+caps); + } + attrs.put(idx++, surfaceType); - attrs[idx++] = EGL.EGL_RED_SIZE; - attrs[idx++] = caps.getRedBits(); + attrs.put(idx++, EGL.EGL_RED_SIZE); + attrs.put(idx++, caps.getRedBits()); - attrs[idx++] = EGL.EGL_GREEN_SIZE; - attrs[idx++] = caps.getGreenBits(); + attrs.put(idx++, EGL.EGL_GREEN_SIZE); + attrs.put(idx++, caps.getGreenBits()); - attrs[idx++] = EGL.EGL_BLUE_SIZE; - attrs[idx++] = caps.getBlueBits(); + attrs.put(idx++, EGL.EGL_BLUE_SIZE); + attrs.put(idx++, caps.getBlueBits()); if(caps.getAlphaBits()>0) { - attrs[idx++] = EGL.EGL_ALPHA_SIZE; - attrs[idx++] = caps.getAlphaBits(); + attrs.put(idx++, EGL.EGL_ALPHA_SIZE); + attrs.put(idx++, caps.getAlphaBits()); } - + if(caps.getStencilBits()>0) { - attrs[idx++] = EGL.EGL_STENCIL_SIZE; - attrs[idx++] = caps.getStencilBits(); + attrs.put(idx++, EGL.EGL_STENCIL_SIZE); + attrs.put(idx++, caps.getStencilBits()); } - attrs[idx++] = EGL.EGL_DEPTH_SIZE; - attrs[idx++] = caps.getDepthBits(); + attrs.put(idx++, EGL.EGL_DEPTH_SIZE); + attrs.put(idx++, caps.getDepthBits()); if(caps.getSampleBuffers()) { if(caps.getSampleExtension().equals(GLGraphicsConfigurationUtil.NV_coverage_sample)) { - attrs[idx++] = EGLExt.EGL_COVERAGE_BUFFERS_NV; - attrs[idx++] = 1; - attrs[idx++] = EGLExt.EGL_COVERAGE_SAMPLES_NV; - attrs[idx++] = caps.getNumSamples(); + attrs.put(idx++, EGLExt.EGL_COVERAGE_BUFFERS_NV); + attrs.put(idx++, 1); + attrs.put(idx++, EGLExt.EGL_COVERAGE_SAMPLES_NV); + attrs.put(idx++, caps.getNumSamples()); } else { // try default .. - attrs[idx++] = EGL.EGL_SAMPLE_BUFFERS; - attrs[idx++] = 1; - attrs[idx++] = EGL.EGL_SAMPLES; - attrs[idx++] = caps.getNumSamples(); + attrs.put(idx++, EGL.EGL_SAMPLE_BUFFERS); + attrs.put(idx++, 1); + attrs.put(idx++, EGL.EGL_SAMPLES); + attrs.put(idx++, caps.getNumSamples()); } } - attrs[idx++] = EGL.EGL_TRANSPARENT_TYPE; - attrs[idx++] = caps.isBackgroundOpaque() ? EGL.EGL_NONE : EGL.EGL_TRANSPARENT_TYPE; + attrs.put(idx++, EGL.EGL_TRANSPARENT_TYPE); + attrs.put(idx++, caps.isBackgroundOpaque() ? EGL.EGL_NONE : EGL.EGL_TRANSPARENT_TYPE); // 22 if(!caps.isBackgroundOpaque()) { - attrs[idx++] = EGL.EGL_TRANSPARENT_RED_VALUE; - attrs[idx++] = caps.getTransparentRedValue()>=0?caps.getTransparentRedValue():EGL.EGL_DONT_CARE; + attrs.put(idx++, EGL.EGL_TRANSPARENT_RED_VALUE); + attrs.put(idx++, caps.getTransparentRedValue()>=0?caps.getTransparentRedValue():EGL.EGL_DONT_CARE); - attrs[idx++] = EGL.EGL_TRANSPARENT_GREEN_VALUE; - attrs[idx++] = caps.getTransparentGreenValue()>=0?caps.getTransparentGreenValue():EGL.EGL_DONT_CARE; + attrs.put(idx++, EGL.EGL_TRANSPARENT_GREEN_VALUE); + attrs.put(idx++, caps.getTransparentGreenValue()>=0?caps.getTransparentGreenValue():EGL.EGL_DONT_CARE); - attrs[idx++] = EGL.EGL_TRANSPARENT_BLUE_VALUE; - attrs[idx++] = caps.getTransparentBlueValue()>=0?caps.getTransparentBlueValue():EGL.EGL_DONT_CARE; + attrs.put(idx++, EGL.EGL_TRANSPARENT_BLUE_VALUE); + attrs.put(idx++, caps.getTransparentBlueValue()>=0?caps.getTransparentBlueValue():EGL.EGL_DONT_CARE); /** Not define in EGL - attrs[idx++] = EGL.EGL_TRANSPARENT_ALPHA_VALUE; - attrs[idx++] = caps.getTransparentAlphaValue()>=0?caps.getTransparentAlphaValue():EGL.EGL_DONT_CARE; */ + attrs.put(idx++, EGL.EGL_TRANSPARENT_ALPHA_VALUE; + attrs.put(idx++, caps.getTransparentAlphaValue()>=0?caps.getTransparentAlphaValue():EGL.EGL_DONT_CARE; */ } - // 28 - attrs[idx++] = EGL.EGL_RENDERABLE_TYPE; + // 28 + attrs.put(idx++, EGL.EGL_RENDERABLE_TYPE); if(caps.getGLProfile().usesNativeGLES1()) { - attrs[idx++] = EGL.EGL_OPENGL_ES_BIT; + attrs.put(idx++, EGL.EGL_OPENGL_ES_BIT); } else if(caps.getGLProfile().usesNativeGLES2()) { - attrs[idx++] = EGL.EGL_OPENGL_ES2_BIT; + attrs.put(idx++, EGL.EGL_OPENGL_ES2_BIT); + } else if(caps.getGLProfile().usesNativeGLES3()) { + if( GLRendererQuirks.existStickyDeviceQuirk(GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) { + attrs.put(idx++, EGL.EGL_OPENGL_ES2_BIT); + } else { + attrs.put(idx++, EGLExt.EGL_OPENGL_ES3_BIT_KHR); + } } else { - attrs[idx++] = EGL.EGL_OPENGL_BIT; + attrs.put(idx++, EGL.EGL_OPENGL_BIT); } // 30 - attrs[idx++] = EGL.EGL_NONE; + attrs.put(idx++, EGL.EGL_NONE); return attrs; } - public static int[] CreatePBufferSurfaceAttribList(int width, int height, int texFormat) { - int[] attrs = new int[16]; + public static IntBuffer CreatePBufferSurfaceAttribList(int width, int height, int texFormat) { + IntBuffer attrs = Buffers.newDirectIntBuffer(16); int idx=0; - attrs[idx++] = EGL.EGL_WIDTH; - attrs[idx++] = width; + attrs.put(idx++, EGL.EGL_WIDTH); + attrs.put(idx++, width); - attrs[idx++] = EGL.EGL_HEIGHT; - attrs[idx++] = height; + attrs.put(idx++, EGL.EGL_HEIGHT); + attrs.put(idx++, height); - attrs[idx++] = EGL.EGL_TEXTURE_FORMAT; - attrs[idx++] = texFormat; + attrs.put(idx++, EGL.EGL_TEXTURE_FORMAT); + attrs.put(idx++, texFormat); - attrs[idx++] = EGL.EGL_TEXTURE_TARGET; - attrs[idx++] = EGL.EGL_NO_TEXTURE==texFormat ? EGL.EGL_NO_TEXTURE : EGL.EGL_TEXTURE_2D; + attrs.put(idx++, EGL.EGL_TEXTURE_TARGET); + attrs.put(idx++, EGL.EGL_NO_TEXTURE==texFormat ? EGL.EGL_NO_TEXTURE : EGL.EGL_TEXTURE_2D); - attrs[idx++] = EGL.EGL_NONE; + attrs.put(idx++, EGL.EGL_NONE); return attrs; } @@ -376,6 +511,6 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple } - private GLCapabilitiesChooser chooser; + private final GLCapabilitiesChooser chooser; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java index 904110eb2..5cfa378cb 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2010 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -38,15 +38,14 @@ import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.VisualIDHolder.VIDType; import javax.media.nativewindow.NativeWindowFactory; - import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import javax.media.opengl.GLDrawableFactory; @@ -54,6 +53,7 @@ import javax.media.opengl.GLDrawableFactory; import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.GLRendererQuirks; import jogamp.opengl.GLGraphicsConfigurationFactory; import jogamp.opengl.GLGraphicsConfigurationUtil; @@ -74,43 +74,51 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact static VisualIDHolder.VIDComparator EglCfgIDComparator = new VisualIDHolder.VIDComparator(VisualIDHolder.VIDType.EGL_CONFIG); static GraphicsConfigurationFactory nativeGraphicsConfigurationFactory = null; static GraphicsConfigurationFactory kdeglGraphicsConfigurationFactory = null; - + static GraphicsConfigurationFactory fallbackGraphicsConfigurationFactory = null; + static void registerFactory() { GraphicsConfigurationFactory eglFactory = new EGLGraphicsConfigurationFactory(); - + // become the pre-selector for X11/.. to match the native visual id w/ EGL, if native ES is selected final String nwType = NativeWindowFactory.getNativeWindowType(false); if(NativeWindowFactory.TYPE_X11 == nwType) { - nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, eglFactory); + nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory); + if(null != nativeGraphicsConfigurationFactory) { + fallbackGraphicsConfigurationFactory = nativeGraphicsConfigurationFactory; + } else { + fallbackGraphicsConfigurationFactory = GraphicsConfigurationFactory.getFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class); + } } /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) { nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, eglFactory); - } else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) { + } else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) { } */ - + // become the selector for KD/EGL .. - kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, eglFactory); + kdeglGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory); } - + static void unregisterFactory() { final String nwType = NativeWindowFactory.getNativeWindowType(false); if(NativeWindowFactory.TYPE_X11 == nwType) { - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, nativeGraphicsConfigurationFactory); + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, nativeGraphicsConfigurationFactory); } /* else if(NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false)) { GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, nativeGraphicsConfigurationFactory); - } else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) { + } else if(NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false)) { } */ nativeGraphicsConfigurationFactory = null; - - GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, kdeglGraphicsConfigurationFactory); + fallbackGraphicsConfigurationFactory = null; + + GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, GLCapabilitiesImmutable.class, kdeglGraphicsConfigurationFactory); kdeglGraphicsConfigurationFactory = null; } - + private EGLGraphicsConfigurationFactory() { } + @Override protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl ( CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, - CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) { if (absScreen == null) { throw new IllegalArgumentException("This NativeWindowFactory accepts only AbstractGraphicsDevice objects"); } @@ -132,21 +140,21 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact AbstractGraphicsDevice absDevice = absScreen.getDevice(); if(null==absDevice) { throw new GLException("Null AbstractGraphicsDevice"); - } - + } + AbstractGraphicsConfiguration cfg = null; - + if( absDevice instanceof EGLGraphicsDevice ) { cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen, (GLCapabilitiesImmutable) capsRequested, (GLCapabilitiesChooser) chooser, - absScreen, VisualIDHolder.VID_UNDEFINED, false); + absScreen, nativeVisualID, false); } else { - // handle non native cases (X11, ..) - if(null == nativeGraphicsConfigurationFactory) { - throw new InternalError("Native GraphicsConfigurationFactory is null, but call issued for device: "+absDevice+" of type "+absDevice.getClass().getSimpleName()); + // handle non native cases (X11, ..) + if(null == fallbackGraphicsConfigurationFactory) { + throw new InternalError("Native fallback GraphicsConfigurationFactory is null, but call issued for device: "+absDevice+" of type "+absDevice.getClass().getSimpleName()); } - + if(glCapsChosen.getGLProfile().usesNativeGLES()) { if(DEBUG) { System.err.println("EGLGraphicsConfigurationFactory.choose..: Handle native device "+absDevice.getClass().getSimpleName()); @@ -154,7 +162,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen, (GLCapabilitiesImmutable) capsRequested, (GLCapabilitiesChooser) chooser, - absScreen, VisualIDHolder.VID_UNDEFINED, false); + absScreen, nativeVisualID, false); if(null == cfg || VisualIDHolder.VID_UNDEFINED == cfg.getVisualID(VIDType.NATIVE)) { cfg = null; if(DEBUG) { @@ -165,23 +173,25 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(null == cfg) { // fwd to native config factory (only X11 for now) if(DEBUG) { - System.err.println("EGLGraphicsConfigurationFactory.choose..: Delegate to "+nativeGraphicsConfigurationFactory.getClass().getSimpleName()); + System.err.println("EGLGraphicsConfigurationFactory.choose..: Delegate to "+fallbackGraphicsConfigurationFactory.getClass().getSimpleName()); } - cfg = nativeGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen); - } + cfg = fallbackGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen, nativeVisualID); + } } return cfg; } protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(EGLDrawableFactory factory, AbstractGraphicsDevice device) { - EGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateEGLSharedResource(device); + final EGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device); if(null == sharedResource) { throw new GLException("Shared resource for device n/a: "+device); } - EGLGraphicsDevice eglDevice = sharedResource.getDevice(); - long eglDisplay = eglDevice.getHandle(); - - List/*<EGLGLCapabilities>*/ availableCaps = null; + final EGLGraphicsDevice eglDevice = sharedResource.getDevice(); + final long eglDisplay = eglDevice.getHandle(); + if(0 == eglDisplay) { + throw new GLException("null eglDisplay"); + } + List<GLCapabilitiesImmutable> availableCaps = null; IntBuffer numConfigs = Buffers.newDirectIntBuffer(1); if(!EGL.eglGetConfigs(eglDisplay, null, 0, numConfigs)) { @@ -197,19 +207,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact throw new GLException("Graphics configuration get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError())); } if (numConfigs.get(0) > 0) { - availableCaps = eglConfigs2GLCaps(null, eglDisplay, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, false); + availableCaps = eglConfigs2GLCaps(eglDevice, null, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, false /* forceTransparentFlag */, false /* onlyFirstValid */); if( null != availableCaps && availableCaps.size() > 1) { Collections.sort(availableCaps, EglCfgIDComparator); } } - return availableCaps; } public static EGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser, - AbstractGraphicsScreen absScreen, int nativeVisualID, + AbstractGraphicsScreen absScreen, int nativeVisualID, boolean forceTransparentFlag) { if (capsChosen == null) { capsChosen = new GLCapabilities(null); @@ -222,101 +231,107 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(null==absDevice) { throw new GLException("Null AbstractGraphicsDevice"); } - - final long eglDisplay; + + final EGLGraphicsDevice eglDevice; final boolean ownEGLDisplay; - if( !(absDevice instanceof EGLGraphicsDevice) ) { - eglDisplay = EGLDisplayUtil.eglGetDisplay(absDevice.getHandle()); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Could not get EGL display from: "+absDevice); - } - if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { - throw new GLException("eglInitialize failed eglDisplay 0x"+Long.toHexString(eglDisplay)+", "+absDevice+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - ownEGLDisplay = true; - } else { - eglDisplay = absDevice.getHandle(); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Invalid EGL display: "+absDevice); + if( absDevice instanceof EGLGraphicsDevice ) { + eglDevice = (EGLGraphicsDevice) absDevice; + if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) { + throw new GLException("Invalid EGL display: "+eglDevice); } ownEGLDisplay = false; + } else { + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(absDevice.getHandle(), absDevice.getConnection(), absDevice.getUnitID()); + eglDevice.open(); + ownEGLDisplay = true; } - EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory(); - capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(absDevice) ); - - GLProfile glp = capsChosen.getGLProfile(); - GLCapabilities fixedCaps; - - EGLGraphicsConfiguration res = eglChooseConfig(eglDisplay, capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag); + final GLProfile glp = capsChosen.getGLProfile(); + capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLDrawableFactory.getEGLFactory(), absDevice); + EGLGraphicsConfiguration res = eglChooseConfig(eglDevice, capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag); if(null==res) { if(DEBUG) { System.err.println("eglChooseConfig failed with given capabilities "+capsChosen); } - + // Last try .. add a fixed embedded profile [ATI, Nokia, Intel, ..] // // rgb888 - d16, s4 - fixedCaps = new GLCapabilities(glp); + final GLCapabilities fixedCaps = new GLCapabilities(glp); + fixedCaps.setSampleBuffers(true); + fixedCaps.setNumSamples(4); fixedCaps.setRedBits(8); fixedCaps.setGreenBits(8); fixedCaps.setBlueBits(8); fixedCaps.setDepthBits(16); - fixedCaps.setSampleBuffers(true); - fixedCaps.setNumSamples(4); + if( !capsChosen.isOnscreen() ) { + fixedCaps.setOnscreen(false); + fixedCaps.setPBuffer(capsChosen.isPBuffer()); + fixedCaps.setFBO(capsChosen.isFBO()); + } if(DEBUG) { System.err.println("trying fixed caps (1): "+fixedCaps); } - res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); + res = eglChooseConfig(eglDevice, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); } if(null==res) { // // rgb565 - d16, s0 - fixedCaps = new GLCapabilities(glp); + final GLCapabilities fixedCaps = new GLCapabilities(glp); fixedCaps.setRedBits(5); fixedCaps.setGreenBits(6); fixedCaps.setBlueBits(5); fixedCaps.setDepthBits(16); + if( !capsChosen.isOnscreen() ) { + fixedCaps.setOnscreen(false); + fixedCaps.setPBuffer(capsChosen.isPBuffer()); + fixedCaps.setFBO(capsChosen.isFBO()); + } if(DEBUG) { System.err.println("trying fixed caps (2): "+fixedCaps); } - res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); + res = eglChooseConfig(eglDevice, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); } if(null==res) { // // rgb565 - d16, s4 - fixedCaps = new GLCapabilities(glp); + final GLCapabilities fixedCaps = new GLCapabilities(glp); + fixedCaps.setSampleBuffers(true); + fixedCaps.setNumSamples(4); fixedCaps.setRedBits(5); fixedCaps.setGreenBits(6); fixedCaps.setBlueBits(5); fixedCaps.setDepthBits(16); - fixedCaps.setSampleBuffers(true); - fixedCaps.setNumSamples(4); + if( !capsChosen.isOnscreen() ) { + fixedCaps.setOnscreen(false); + fixedCaps.setPBuffer(capsChosen.isPBuffer()); + fixedCaps.setFBO(capsChosen.isFBO()); + } if(DEBUG) { System.err.println("trying fixed caps (3): "+fixedCaps); } - res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); + res = eglChooseConfig(eglDevice, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false); } if(null==res) { throw new GLException("Graphics configuration failed [direct caps, eglGetConfig/chooser and fixed-caps(1-3)]"); } if(ownEGLDisplay) { - ((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL - EGLDisplayUtil.eglTerminate(eglDisplay); + ((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL + eglDevice.close(); } return res; } - static EGLGraphicsConfiguration eglChooseConfig(long eglDisplay, + + static EGLGraphicsConfiguration eglChooseConfig(EGLGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID, boolean forceTransparentFlag) { + final long eglDisplay = device.getHandle(); final GLProfile glp = capsChosen.getGLProfile(); - final boolean onscreen = capsChosen.isOnscreen(); - final boolean usePBuffer = capsChosen.isPBuffer(); - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); - List/*<EGLGLCapabilities>*/ availableCaps = null; + final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen); + List<GLCapabilitiesImmutable> availableCaps = null; int recommendedIndex = -1; long recommendedEGLConfig = -1; IntBuffer numConfigs = Buffers.newDirectIntBuffer(1); @@ -327,35 +342,58 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(0 == numConfigs.get(0)) { throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: Get maxConfigs (eglGetConfigs) no configs"); } + final int numEGLConfigs = numConfigs.get(0); if (DEBUG) { - System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig maxConfigs: "+numConfigs.get(0)); - System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglDisplay "+toHexString(eglDisplay)+", "+capsChosen+", nativeVisualID "+toHexString(nativeVisualID)); + System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglChooseConfig eglDisplay "+toHexString(eglDisplay)+ + ", nativeVisualID "+toHexString(nativeVisualID)+ + ", capsChosen "+capsChosen+", winbits "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrmask).toString()+ + ", fboAvail "+GLContext.isFBOAvailable(device, glp)+ + ", device "+device+", "+device.getUniqueID()+ + ", numEGLConfigs "+numEGLConfigs); } - final IntBuffer attrs = Buffers.newDirectIntBuffer(EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen)); + final IntBuffer attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen); PointerBuffer configs = PointerBuffer.allocateDirect(numConfigs.get(0)); - // 1st choice: get GLCapabilities based on users GLCapabilities + // 1st choice: get GLCapabilities based on users GLCapabilities // setting recommendedIndex as preferred choice // skipped if nativeVisualID is given - if( VisualIDHolder.VID_UNDEFINED != nativeVisualID || !EGL.eglChooseConfig(eglDisplay, attrs, configs, configs.capacity(), numConfigs) ) { + final boolean hasEGLChosenCaps; + if( VisualIDHolder.VID_UNDEFINED == nativeVisualID ) { + if( !EGL.eglChooseConfig(eglDisplay, attrs, configs, configs.capacity(), numConfigs) ) { + if(DEBUG) { + System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: false"); + } + numConfigs.put(0, 0); + hasEGLChosenCaps = false; + } else { + hasEGLChosenCaps = numConfigs.get(0)>0; + } + } else { if(DEBUG) { - System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: false"); + System.err.println("EGLGraphicsConfiguration.eglChooseConfig: Skipped due to given visualID: "+toHexString(nativeVisualID)); } - } else if (numConfigs.get(0) > 0) { - availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag); + hasEGLChosenCaps = false; + } + final boolean useRecommendedIndex = hasEGLChosenCaps && !forceTransparentFlag && capsChosen.isBackgroundOpaque(); // only use recommended idx if not translucent + final boolean skipCapsChooser = null == chooser && useRecommendedIndex; // fast path: skip choosing if using recommended idx and null chooser is used + if( hasEGLChosenCaps ) { + availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), winattrmask, forceTransparentFlag, skipCapsChooser /* onlyFirsValid */); if(availableCaps.size() > 0) { recommendedEGLConfig = configs.get(0); recommendedIndex = 0; if (DEBUG) { System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: recommended fbcfg " + toHexString(recommendedEGLConfig) + ", idx " + recommendedIndex); + System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 useRecommendedIndex "+useRecommendedIndex+", skipCapsChooser "+skipCapsChooser); System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 fbcfg caps " + availableCaps.get(recommendedIndex)); } } else if (DEBUG) { System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: no caps for recommended fbcfg " + toHexString(configs.get(0))); + System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 useRecommendedIndex "+useRecommendedIndex+", skipCapsChooser "+skipCapsChooser); } } else if (DEBUG) { System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 eglChooseConfig: no configs"); + System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #1 useRecommendedIndex "+useRecommendedIndex+", skipCapsChooser "+skipCapsChooser); } // 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available @@ -368,7 +406,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: #2 Get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError())); } if (numConfigs.get(0) > 0) { - availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag); + availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), winattrmask, forceTransparentFlag, false /* onlyFirsValid */); } } @@ -376,10 +414,12 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(DEBUG) { // FIXME: this happens on a ATI PC Emulation .. System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #2 Graphics configuration 1st choice and 2nd choice failed - no configs"); + availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag, false /* onlyFirsValid */); + printCaps("AllCaps", availableCaps, System.err); } return null; } - + if(DEBUG) { System.err.println("EGLGraphicsConfiguration.eglChooseConfig: got configs: "+availableCaps.size()); for(int i=0; i<availableCaps.size(); i++) { @@ -387,11 +427,16 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact } } - if( VisualIDHolder.VID_UNDEFINED != nativeVisualID ) { - List/*<EGLGLCapabilities>*/ removedCaps = new ArrayList(); + if( VisualIDHolder.VID_UNDEFINED != nativeVisualID ) { // implies !hasEGLChosenCaps + List<GLCapabilitiesImmutable> removedCaps = new ArrayList<GLCapabilitiesImmutable>(); for(int i=0; i<availableCaps.size(); ) { - VisualIDHolder vidh = (VisualIDHolder) availableCaps.get(i); - if(vidh.getVisualID(VIDType.NATIVE) != nativeVisualID) { + final GLCapabilitiesImmutable aCap = availableCaps.get(i); + if(aCap.getVisualID(VIDType.NATIVE) != nativeVisualID) { + if(DEBUG) { System.err.println("Remove["+i+"] (mismatch VisualID): "+aCap); } + removedCaps.add(availableCaps.remove(i)); + } else if( 0 == aCap.getDepthBits() && 0 < capsChosen.getDepthBits() ) { + // Hack for HiSilicon/Vivante/Immersion.16 Renderer .. + if(DEBUG) { System.err.println("Remove["+i+"] (mismatch depth-bits): "+aCap); } removedCaps.add(availableCaps.remove(i)); } else { i++; @@ -404,10 +449,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact } } else if(DEBUG) { System.err.println("EGLGraphicsConfiguration.eglChooseConfig: post filter nativeVisualID "+toHexString(nativeVisualID)+" got configs: "+availableCaps.size()); + for(int i=0; i<availableCaps.size(); i++) { + System.err.println(i+": "+availableCaps.get(i)); + } } } - final int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex); + final int chosenIndex; + if( skipCapsChooser && 0 <= recommendedIndex ) { + chosenIndex = recommendedIndex; + } else { + chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex); + } if ( 0 > chosenIndex ) { if (DEBUG) { System.err.println("EGLGraphicsConfiguration.eglChooseConfig: #2 chooseCapabilities failed"); @@ -415,46 +468,32 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact return null; } final EGLGLCapabilities chosenCaps = (EGLGLCapabilities) availableCaps.get(chosenIndex); + final EGLGraphicsConfiguration res = new EGLGraphicsConfiguration(absScreen, chosenCaps, capsRequested, chooser); if (DEBUG) { - System.err.println("EGLGraphicsConfiguration.eglChooseConfig: X chosen :"+chosenIndex+", eglConfig: "+toHexString(chosenCaps.getEGLConfig())+", "+chosenCaps); + System.err.println("EGLGraphicsConfiguration.eglChooseConfig: X chosen :"+chosenIndex+", eglConfig: "+toHexString(chosenCaps.getEGLConfig())+": "+res); } - return new EGLGraphicsConfiguration(absScreen, chosenCaps, capsRequested, chooser); + return res; } - static List/*<GLCapabilitiesImmutable>*/ eglConfigs2GLCaps(GLProfile glp, long eglDisplay, PointerBuffer configs, int num, int winattrmask, boolean forceTransparentFlag) { - ArrayList caps = new ArrayList(num); + static List<GLCapabilitiesImmutable> eglConfigs2GLCaps(EGLGraphicsDevice device, GLProfile glp, PointerBuffer configs, int num, int winattrmask, boolean forceTransparentFlag, boolean onlyFirstValid) { + final GLRendererQuirks defaultQuirks = GLRendererQuirks.getStickyDeviceQuirks( GLDrawableFactory.getEGLFactory().getDefaultDevice() ); + List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(num); for(int i=0; i<num; i++) { - EGLGraphicsConfiguration.EGLConfig2Capabilities(caps, glp, eglDisplay, configs.get(i), winattrmask, forceTransparentFlag); + final GLCapabilitiesImmutable caps = EGLGraphicsConfiguration.EGLConfig2Capabilities(defaultQuirks, device, glp, configs.get(i), winattrmask, forceTransparentFlag); + if(null != caps) { + bucket.add(caps); + if(onlyFirstValid) { + break; + } + } } - return caps; + return bucket; } - static void printCaps(String prefix, List/*GLCapabilitiesImmutable*/ caps, PrintStream out) { + static void printCaps(String prefix, List<GLCapabilitiesImmutable> caps, PrintStream out) { for(int i=0; i<caps.size(); i++) { out.println(prefix+"["+i+"] "+caps.get(i)); } } - - static EGLGraphicsConfiguration createOffscreenGraphicsConfiguration(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser) { - if(capsChosen.isOnscreen()) { - throw new GLException("Error: Onscreen set: "+capsChosen); - } - - if(capsChosen.getDoubleBuffered()) { - // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN - GLCapabilities caps2 = (GLCapabilities) capsChosen.cloneMutable(); - caps2.setDoubleBuffered(false); - capsChosen = caps2; - } - - DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); - EGLGraphicsConfiguration eglConfig = chooseGraphicsConfigurationStatic(capsChosen, capsReq, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); - if (null == eglConfig) { - throw new GLException("Couldn't create EGLGraphicsConfiguration from "+screen); - } else if(DEBUG) { - System.err.println("Chosen eglConfig: "+eglConfig); - } - return eglConfig; - } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java deleted file mode 100644 index dd0a3db3a..000000000 --- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * 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.*; -import javax.media.opengl.*; -import jogamp.opengl.*; -import com.jogamp.gluegen.runtime.ProcAddressTable; -import java.nio.*; -import java.util.*; - -public class EGLOnscreenContext extends EGLContext { - public EGLOnscreenContext(EGLOnscreenDrawable drawable, GLContext shareWith) { - super(drawable, shareWith); - } - - public void bindPbufferToTexture() { - throw new GLException("Should not call this"); - } - - public void releasePbufferFromTexture() { - throw new GLException("Should not call this"); - } - -} - diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java index 42f067b29..065f80dcb 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2010 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -29,11 +29,11 @@ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * + * * You acknowledge that this software is not designed or intended for use * in the design, construction, operation or maintenance of any nuclear * facility. - * + * * Sun gratefully acknowledges that this software was originally authored * and developed by Kenneth Bradley Russell and Christopher John Kline. */ @@ -48,12 +48,14 @@ public class EGLOnscreenDrawable extends EGLDrawable { super(factory, component); } + @Override public GLContext createContext(GLContext shareWith) { - return new EGLOnscreenContext(this, shareWith); + return new EGLContext(this, shareWith); } - protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { - return EGL.eglCreateWindowSurface(eglDpy, eglNativeCfg, surfaceHandle, null); + @Override + protected long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle) { + return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), config.getNativeConfig(), nativeSurfaceHandle, null); } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java deleted file mode 100644 index 2cad7daac..000000000 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * 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.*; -import javax.media.opengl.*; -import jogamp.opengl.*; -import com.jogamp.gluegen.runtime.ProcAddressTable; -import java.nio.*; -import java.util.*; - -public class EGLPbufferContext extends EGLContext { - public EGLPbufferContext(EGLPbufferDrawable drawable, GLContext shareWith) { - super(drawable, shareWith); - } - - public int getFloatingPointMode() { - return 0; // FIXME ?? - } - - public void bindPbufferToTexture() { - throw new GLException("Not yet implemented"); - } - - public void releasePbufferFromTexture() { - throw new GLException("Not yet implemented"); - } -} - diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java index 28a23d294..45e39f5d1 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2010 JogAmp Community. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A @@ -29,64 +29,35 @@ * 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.AbstractGraphicsConfiguration; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.SurfaceChangeable; -import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; -import javax.media.opengl.GLException; public class EGLPbufferDrawable extends EGLDrawable { - private int texFormat; protected static final boolean useTexture = false; // No yet .. protected EGLPbufferDrawable(EGLDrawableFactory factory, NativeSurface target) { super(factory, target); } - protected void destroyImpl() { - setRealized(false); - } - - protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { - final AbstractGraphicsConfiguration config = getNativeSurface().getGraphicsConfiguration(); - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); - - if(useTexture) { - texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; - } else { - texFormat = EGL.EGL_NO_TEXTURE; - } - - if (DEBUG) { - System.out.println("Pbuffer config: " + config); - } - - NativeSurface nw = getNativeSurface(); - int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(nw.getWidth(), nw.getHeight(), texFormat); - long surf = EGL.eglCreatePbufferSurface(eglDpy, eglNativeCfg, attrs, 0); - if (EGL.EGL_NO_SURFACE==surf) { - throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+nw.getWidth()+"x"+nw.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } else if(DEBUG) { - System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf)); - } - ((SurfaceChangeable)nw).setSurfaceHandle(surf); - return surf; + @Override + protected long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle) { + return EGLDrawableFactory.createPBufferSurfaceImpl(config, width, height, false); } + @Override public GLContext createContext(GLContext shareWith) { - return new EGLPbufferContext(this, shareWith); + return new EGLContext(this, shareWith); } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java new file mode 100644 index 000000000..5b911576e --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java @@ -0,0 +1,217 @@ +package jogamp.opengl.egl; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; +import javax.media.nativewindow.VisualIDHolder.VIDType; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLException; + +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; + +/** + * <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 EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize { + protected static final boolean DEBUG = EGLDrawableFactory.DEBUG; + private final NativeSurface upstreamSurface; + private final UpstreamSurfaceHook.MutableSize upstreamSurfaceHookMutableSize; + + public EGLUpstreamSurfaceHook(NativeSurface upstream) { + upstreamSurface = upstream; + if(upstreamSurface instanceof ProxySurface) { + final UpstreamSurfaceHook ush = ((ProxySurface)upstreamSurface).getUpstreamSurfaceHook(); + if(ush instanceof UpstreamSurfaceHook.MutableSize) { + // offscreen NativeSurface w/ MutableSize (default) + upstreamSurfaceHookMutableSize = (UpstreamSurfaceHook.MutableSize) ush; + } else { + upstreamSurfaceHookMutableSize = null; + } + } else { + upstreamSurfaceHookMutableSize = null; + } + } + + public final NativeSurface getUpstreamSurface() { return upstreamSurface; } + + static String getThreadName() { return Thread.currentThread().getName(); } + + @Override + public final void setSize(int width, int height) { + if(null != upstreamSurfaceHookMutableSize) { + upstreamSurfaceHookMutableSize.setSize(width, height); + } + } + + @Override + public final void create(ProxySurface surface) { + final String dbgPrefix; + if(DEBUG) { + dbgPrefix = getThreadName() + ": EGLUpstreamSurfaceHook.create( up "+upstreamSurface.getClass().getSimpleName()+" -> this "+surface.getClass().getSimpleName()+" ): "; + System.err.println(dbgPrefix+this); + } else { + dbgPrefix = null; + } + + if(upstreamSurface instanceof ProxySurface) { + // propagate createNotify(..) so upstreamSurface will be created + ((ProxySurface)upstreamSurface).createNotify(); + } + + // lock upstreamSurface, so it can be used in case EGLDisplay is derived from it! + if(NativeSurface.LOCK_SURFACE_NOT_READY >= upstreamSurface.lockSurface()) { + throw new GLException("Could not lock: "+upstreamSurface); + } + try { + evalUpstreamSurface(dbgPrefix, surface); + } finally { + upstreamSurface.unlockSurface(); + } + } + + private final void evalUpstreamSurface(String dbgPrefix, ProxySurface surface) { + // + // evaluate nature of upstreamSurface, may create EGL instances if required + // + + boolean isEGLSurfaceValid = true; // assume yes + + final EGLGraphicsDevice eglDevice; + final AbstractGraphicsConfiguration aConfig; + { + final AbstractGraphicsConfiguration surfaceConfig = surface.getGraphicsConfiguration(); + final AbstractGraphicsDevice surfaceDevice = null != surfaceConfig ? surfaceConfig.getScreen().getDevice() : null; + if(DEBUG) { + System.err.println(dbgPrefix+"SurfaceDevice: "+surfaceDevice.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(surfaceDevice.hashCode())+", "+surfaceDevice); + System.err.println(dbgPrefix+"SurfaceConfig: "+surfaceConfig.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(surfaceConfig.hashCode())+", "+surfaceConfig); + } + + final AbstractGraphicsConfiguration upstreamConfig = upstreamSurface.getGraphicsConfiguration(); + final AbstractGraphicsDevice upstreamDevice = upstreamConfig.getScreen().getDevice(); + if(DEBUG) { + System.err.println(dbgPrefix+"UpstreamDevice: "+upstreamDevice.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(upstreamDevice.hashCode())+", "+upstreamDevice); + System.err.println(dbgPrefix+"UpstreamConfig: "+upstreamConfig.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(upstreamConfig.hashCode())+", "+upstreamConfig); + } + + if( surfaceDevice instanceof EGLGraphicsDevice ) { + eglDevice = (EGLGraphicsDevice) surfaceDevice; + aConfig = surfaceConfig; + if(DEBUG) { + System.err.println(dbgPrefix+"Reusing this eglDevice: "+eglDevice+", using this config "+aConfig.getClass().getSimpleName()+" "+aConfig); + } + if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) { + eglDevice.open(); + isEGLSurfaceValid = false; + surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + } else if( upstreamDevice instanceof EGLGraphicsDevice ) { + eglDevice = (EGLGraphicsDevice) upstreamDevice; + aConfig = upstreamConfig; + if(DEBUG) { + System.err.println(dbgPrefix+"Reusing upstream eglDevice: "+eglDevice+", using upstream config "+aConfig.getClass().getSimpleName()+" "+aConfig); + } + if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) { + eglDevice.open(); + isEGLSurfaceValid = false; + surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + } else { + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface); + eglDevice.open(); + aConfig = upstreamConfig; + isEGLSurfaceValid = false; + surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + } + + final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); + final EGLGraphicsConfiguration eglConfig; + if( aConfig instanceof EGLGraphicsConfiguration ) { + // Config is already in EGL type - reuse .. + final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); + if( !isEGLSurfaceValid || !EGLGraphicsConfiguration.isEGLConfigValid(eglDevice.getHandle(), capsChosen.getEGLConfig()) ) { + // 'refresh' the native EGLConfig handle + capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); + if( 0 == capsChosen.getEGLConfig() ) { + throw new GLException("Refreshing native EGLConfig handle failed with error "+EGLContext.toHexString(EGL.eglGetError())+": "+eglDevice+", "+capsChosen+" of "+aConfig); + } + final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); + eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); + if(DEBUG) { + System.err.println(dbgPrefix+"Refreshing eglConfig: "+eglConfig); + } + isEGLSurfaceValid = false; + } else { + eglConfig = (EGLGraphicsConfiguration) aConfig; + if(DEBUG) { + System.err.println(dbgPrefix+"Reusing eglConfig: "+eglConfig); + } + } + } else { + final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); + eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false /* forceTransparencyFlag */); + + if (null == eglConfig) { + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); + } else if(DEBUG) { + System.err.println(dbgPrefix+"Chosen eglConfig: "+eglConfig); + } + isEGLSurfaceValid = false; + } + surface.setGraphicsConfiguration(eglConfig); + + if(isEGLSurfaceValid) { + isEGLSurfaceValid = EGLDrawable.isValidEGLSurface(eglDevice.getHandle(), upstreamSurface.getSurfaceHandle()); + } + if(isEGLSurfaceValid) { + surface.setSurfaceHandle(upstreamSurface.getSurfaceHandle()); + surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + if(DEBUG) { + System.err.println(dbgPrefix+"Fin: Already valid EGL surface - use as-is: "+upstreamSurface); + } + } else { + surface.setSurfaceHandle(EGL.EGL_NO_SURFACE); + surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); // create/destroy in EGLDrawable + if(DEBUG) { + System.err.println(dbgPrefix+"Fin: EGL surface n/a - TBD: "+upstreamSurface); + } + } + } + + @Override + public final void destroy(ProxySurface surface) { + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLUpstreamSurfaceHook.destroy("+surface.getClass().getSimpleName()+"): "+this); + } + surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + if(upstreamSurface instanceof ProxySurface) { + ((ProxySurface)upstreamSurface).destroyNotify(); + } + } + + @Override + public final int getWidth(ProxySurface s) { + return upstreamSurface.getWidth(); + } + + @Override + public final int getHeight(ProxySurface s) { + return upstreamSurface.getHeight(); + } + + @Override + public String toString() { + final String us_s = null != upstreamSurface ? ( upstreamSurface.getClass().getName() + ": 0x" + Long.toHexString(upstreamSurface.getSurfaceHandle()) ) : "nil"; + return "EGLUpstreamSurfaceHook[ "+ upstreamSurface.getWidth() + "x" + upstreamSurface.getHeight() + ", " + us_s+ "]"; + } + +} diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java new file mode 100644 index 000000000..e6d43d957 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java @@ -0,0 +1,34 @@ +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(NativeSurface surface) { + if(surface instanceof EGLWrappedSurface) { + return (EGLWrappedSurface)surface; + } + return new EGLWrappedSurface(surface); + } + + public EGLWrappedSurface(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); + } + } + + @Override + public final NativeSurface getUpstreamSurface() { + return ((EGLUpstreamSurfaceHook)super.getUpstreamSurfaceHook()).getUpstreamSurface(); + } +} |