diff options
Diffstat (limited to 'src/jogl/classes/jogamp/opengl')
45 files changed, 1702 insertions, 1046 deletions
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java index 7e49b3464..f278f73ae 100644 --- a/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java +++ b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java @@ -34,6 +34,7 @@ import java.nio.IntBuffer; import javax.media.opengl.*; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.IntObjectHashMap; import com.jogamp.common.util.PropertyAccess; @@ -266,7 +267,7 @@ public class GLBufferObjectTracker { if( null == objOld ) { if (DEBUG) { System.err.printf("%s: %s.notifyBuffersDeleted()[%d/%d]: Buffer %d not tracked%n", warning, msgClazzName, i+1, count, bufferName); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return; } @@ -409,7 +410,7 @@ public class GLBufferObjectTracker { if ( 0 == addr ) { if( DEBUG ) { System.err.printf("%s.%s: %s MapBuffer null result for target 0x%X -> %d: %s, off %d, len %d, acc 0x%X%n", msgClazzName, msgMapBuffer, warning, target, bufferName, store, offset, length, access); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } // User shall handle the glError ! } else { @@ -442,14 +443,14 @@ public class GLBufferObjectTracker { if( 0 == bufferName ) { if (DEBUG) { System.err.printf("%s: %s.%s: Buffer for target 0x%X not bound%n", warning, msgClazzName, msgUnmapped, target); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } store = null; } else { store = (GLBufferStorageImpl) bufferName2StorageMap.get(bufferName); if( DEBUG && null == store ) { System.err.printf("%s: %s.%s: Buffer %d not tracked%n", warning, msgClazzName, msgUnmapped, bufferName); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } } final boolean res = dispatch.unmap(target, glProcAddress); @@ -459,7 +460,7 @@ public class GLBufferObjectTracker { if( DEBUG ) { System.err.printf("%s.%s %s target: 0x%X -> %d: %s%n", msgClazzName, msgUnmapped, res ? "OK" : "Failed", target, bufferName, store.toString(false)); if(!res) { - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } } return res; @@ -476,7 +477,7 @@ public class GLBufferObjectTracker { final GLBufferStorageImpl store = (GLBufferStorageImpl) bufferName2StorageMap.get(bufferName); if (DEBUG && null == store ) { System.err.printf("%s: %s.%s: Buffer %d not tracked%n", warning, msgClazzName, msgUnmapped, bufferName); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } final boolean res = dispatch.unmap(bufferName, glProcAddress); if( res && null != store ) { @@ -485,7 +486,7 @@ public class GLBufferObjectTracker { if (DEBUG) { System.err.printf("%s.%s %s %d: %s%n", msgClazzName, msgUnmapped, res ? "OK" : "Failed", bufferName, store.toString(false)); if(!res) { - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } } return res; @@ -505,7 +506,7 @@ public class GLBufferObjectTracker { public synchronized final void clear() { if (DEBUG) { System.err.printf("%s.clear() - Thread %s%n", msgClazzName, Thread.currentThread().getName()); - // Thread.dumpStack(); + // ExceptionUtils.dumpStackTrace(System.err); } bufferName2StorageMap.clear(); } diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 45a4f2426..44987bdec 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -48,6 +48,7 @@ import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.os.Platform; import com.jogamp.common.util.ReflectionUtil; @@ -64,6 +65,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.ProxySurface; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GL2ES3; @@ -118,6 +120,12 @@ public abstract class GLContextImpl extends GLContext { protected GLDrawableImpl drawable; protected GLDrawableImpl drawableRead; + /** + * If GL >= 3.0 (ES or desktop) and not having {@link GLRendererQuirks#NoSurfacelessCtx}, + * being evaluated if not surface-handle is null and not yet set at makeCurrent(..). + */ + private boolean surfacelessOK = false; + private boolean pixelDataEvaluated; private int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType; @@ -194,6 +202,7 @@ public abstract class GLContextImpl extends GLContext { boundFBOTarget[1] = 0; // read } + surfacelessOK = false; pixelDataEvaluated = false; super.resetStates(isInit); @@ -245,8 +254,9 @@ public abstract class GLContextImpl extends GLContext { if( drawable == readWrite && ( setWriteOnly || drawableRead == readWrite ) ) { return drawable; // no change. } - final GLDrawableImpl old = drawable; - if( isCreated() && null != old && old.isRealized() ) { + final GLDrawableImpl oldDrawableWrite = drawable; + final GLDrawableImpl oldDrawableRead = drawableRead; + if( isCreated() && null != oldDrawableWrite && oldDrawableWrite.isRealized() ) { if(!lockHeld) { makeCurrent(); } @@ -266,12 +276,36 @@ public abstract class GLContextImpl extends GLContext { drawableRetargeted |= null != drawable && readWrite != drawable; drawable = (GLDrawableImpl) readWrite ; if( isCreated() && null != drawable && drawable.isRealized() ) { - makeCurrent(true); // implicit: associateDrawable(true) + int res = CONTEXT_NOT_CURRENT; + GLException gle = null; + try { + res = makeCurrent(true); // implicit: associateDrawable(true) + } catch ( final GLException e ) { + gle = e; + } finally { + if( CONTEXT_NOT_CURRENT == res ) { + // Failure, recover and bail out w/ GLException + drawableRead = oldDrawableRead; + drawable = oldDrawableWrite; + if( drawable.isRealized() ) { + makeCurrent(true); // implicit: associateDrawable(true) + } + if( !lockHeld ) { + release(false); + } + final String msg = "Error: makeCurrent() failed with new drawable "+readWrite; + if( null != gle ) { + throw new GLException(msg, gle); + } else { + throw new GLException(msg); + } + } + } if( !lockHeld ) { release(false); } } - return old; + return oldDrawableWrite; } @Override @@ -305,7 +339,7 @@ public abstract class GLContextImpl extends GLContext { final String sgl1 = (null!=this.gl)?this.gl.getClass().getSimpleName()+", "+this.gl.toString():"<null>"; final String sgl2 = (null!=gl)?gl.getClass().getSimpleName()+", "+gl.toString():"<null>"; System.err.println("Info: setGL (OpenGL "+getGLVersion()+"): "+getThreadName()+", "+sgl1+" -> "+sgl2); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } this.gl = gl; return gl; @@ -383,7 +417,7 @@ public abstract class GLContextImpl extends GLContext { lastCtxReleaseStack = new Throwable(msg); if( TRACE_SWITCH ) { System.err.println(msg); - // Thread.dumpStack(); + // ExceptionUtils.dumpStackTrace(System.err, 0, 10); } } } @@ -419,7 +453,7 @@ public abstract class GLContextImpl extends GLContext { if ( DEBUG_TRACE_SWITCH ) { if ( lock.getHoldCount() > 2 ) { System.err.println(getThreadName() + ": GLContextImpl.destroy: Lock was hold more than once - makeCurrent/release imbalance: "+getTraceSwitchMsg()); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } } try { @@ -564,11 +598,23 @@ public abstract class GLContextImpl extends GLContext { int res = CONTEXT_NOT_CURRENT; try { if ( drawable.isRealized() ) { - if ( 0 == drawable.getHandle() ) { - throw new GLException("drawable has invalid handle: "+drawable); - } lock.lock(); try { + if ( 0 == drawable.getHandle() && !surfacelessOK ) { + if( DEBUG ) { + System.err.println(getThreadName() +": GLContext.makeCurrent: Surfaceless evaluate"); + } + if( hasRendererQuirk(GLRendererQuirks.NoSurfacelessCtx) ) { + throw new GLException(String.format("Surfaceless not supported due to quirk %s: %s", + GLRendererQuirks.toString(GLRendererQuirks.NoSurfacelessCtx), toString())); + } + // Allow probing if ProxySurface && OPT_UPSTREAM_SURFACELESS + final NativeSurface surface = drawable.getNativeSurface(); + if( !(surface instanceof ProxySurface) || + !((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS ) ) { + throw new GLException(String.format("non-surfaceless drawable has zero-handle: %s", drawable.toString())); + } + } // One context can only be current by one thread, // and one thread can only have one context current! final GLContext current = getCurrent(); @@ -618,6 +664,16 @@ public abstract class GLContextImpl extends GLContext { } if (res != CONTEXT_NOT_CURRENT) { // still locked! + if( 0 == drawable.getHandle() && !surfacelessOK ) { + if( hasRendererQuirk(GLRendererQuirks.NoSurfacelessCtx) ) { + throw new GLException(String.format("Surfaceless not supported due to quirk %s: %s", + GLRendererQuirks.toString(GLRendererQuirks.NoSurfacelessCtx), toString())); + } + if( DEBUG ) { + System.err.println(getThreadName() +": GLContext.makeCurrent: Surfaceless OK - validate"); + } + surfacelessOK = true; + } setCurrent(this); if(res == CONTEXT_CURRENT_NEW) { // check if the drawable's and the GL's GLProfile are equal @@ -698,12 +754,10 @@ public abstract class GLContextImpl extends GLContext { if( created && hasNoDefaultVAO() ) { final int[] tmp = new int[1]; final GL rootGL = gl.getRootGL(); - if( rootGL.isGL2ES3() ) { // FIXME remove if ES2 == ES3 later - final GL2ES3 gl2es3 = rootGL.getGL2ES3(); - gl2es3.glGenVertexArrays(1, tmp, 0); - defaultVAO = tmp[0]; - gl2es3.glBindVertexArray(defaultVAO); - } + final GL2ES3 gl2es3 = rootGL.getGL2ES3(); + gl2es3.glGenVertexArrays(1, tmp, 0); + defaultVAO = tmp[0]; + gl2es3.glBindVertexArray(defaultVAO); } } finally { if ( null != sharedMaster ) { @@ -712,7 +766,7 @@ public abstract class GLContextImpl extends GLContext { } if ( DEBUG_TRACE_SWITCH ) { System.err.println(getThreadName() + ": Create GL context "+(created?"OK":"FAILED")+": For " + getClass().getName()+" - "+getGLVersion()+" - "+getTraceSwitchMsg()); - // Thread.dumpStack(); + // ExceptionUtils.dumpStackTrace(System.err, 0, 10); } if(!created) { return CONTEXT_NOT_CURRENT; @@ -728,7 +782,7 @@ public abstract class GLContextImpl extends GLContext { if( 0 == ( ctxOptions & GLContext.CTX_PROFILE_ES) ) { // not ES profile final int reqMajor; final int reqProfile; - if( ctxVersion.compareTo(Version300) <= 0 ) { + if( ctxVersion.compareTo(Version3_0) <= 0 ) { reqMajor = 2; } else { reqMajor = ctxVersion.getMajor(); @@ -759,7 +813,7 @@ public abstract class GLContextImpl extends GLContext { GLContext.mapAvailableGLVersion(device, 3, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); } } - GLContext.setAvailableGLVersionsSet(device); + GLContext.setAvailableGLVersionsSet(device, true); if (DEBUG) { System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion()); @@ -879,6 +933,9 @@ public abstract class GLContextImpl extends GLContext { GLContext.getAvailableGLVersionsSet(device)); } + final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final GLProfile glp = glCaps.getGLProfile(); + if ( !GLContext.getAvailableGLVersionsSet(device) ) { if(!mapGLVersions(device)) { // none of the ARB context creation calls was successful, bail out @@ -886,12 +943,11 @@ public abstract class GLContextImpl extends GLContext { } } - final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); final int[] reqMajorCTP = new int[] { 0, 0 }; - GLContext.getRequestMajorAndCompat(glCaps.getGLProfile(), reqMajorCTP); + GLContext.getRequestMajorAndCompat(glp, reqMajorCTP); if(DEBUG) { - System.err.println(getThreadName() + ": createContextARB: Requested "+GLContext.getGLVersion(reqMajorCTP[0], 0, reqMajorCTP[0], null)); + System.err.println(getThreadName() + ": createContextARB: Requested "+glp+" -> "+GLContext.getGLVersion(reqMajorCTP[0], 0, reqMajorCTP[1], null)); } final int _major[] = { 0 }; final int _minor[] = { 0 }; @@ -1023,7 +1079,7 @@ public abstract class GLContextImpl extends GLContext { } if(success) { // only claim GL versions set [and hence detected] if ARB context creation was successful - GLContext.setAvailableGLVersionsSet(device); + GLContext.setAvailableGLVersionsSet(device, true); if(DEBUG) { final long t1 = System.nanoTime(); System.err.println("GLContextImpl.mapGLVersions: "+device+", profileAliasing: "+PROFILE_ALIASING+", total "+(t1-t0)/1e6 +"ms"); @@ -1051,17 +1107,23 @@ public abstract class GLContextImpl extends GLContext { int majorMin, minorMin; final int major[] = new int[1]; final int minor[] = new int[1]; - if( 4 == reqMajor ) { - majorMax=4; minorMax=GLContext.getMaxMinor(ctp, majorMax); - majorMin=4; minorMin=0; - } else if( 3 == reqMajor ) { - majorMax=3; minorMax=GLContext.getMaxMinor(ctp, majorMax); - majorMin=3; minorMin=1; - } else /* if( glp.isGL2() ) */ { - // our minimum desktop OpenGL runtime requirements are 1.1, - // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts - majorMax=3; minorMax=0; - majorMin=2; minorMin=0; + + if( CTX_PROFILE_ES == reqProfile ) { + majorMax=reqMajor; minorMax=GLContext.getMaxMinor(ctp, majorMax); + majorMin=reqMajor; minorMin=0; + } else { + if( 4 == reqMajor ) { + majorMax=4; minorMax=GLContext.getMaxMinor(ctp, majorMax); + majorMin=4; minorMin=0; + } else if( 3 == reqMajor ) { + majorMax=3; minorMax=GLContext.getMaxMinor(ctp, majorMax); + majorMin=3; minorMin=1; + } else /* if( glp.isGL2() ) */ { + // our minimum desktop OpenGL runtime requirements are 1.1, + // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts + majorMax=3; minorMax=0; + majorMin=2; minorMin=0; + } } _context = createContextARBVersions(0, true, ctp, /* max */ majorMax, minorMax, @@ -1181,16 +1243,19 @@ public abstract class GLContextImpl extends GLContext { // Helpers for various context implementations // - private Object createInstance(final GLProfile glp, final boolean glObject, final Object[] cstrArgs) { + private final Object createInstance(final GLProfile glp, final boolean glObject, final Object[] cstrArgs) { return ReflectionUtil.createInstance(glp.getGLCtor(glObject), cstrArgs); } - private boolean verifyInstance(final GLProfile glp, final String suffix, final Object instance) { + private final boolean verifyInstance(final GLProfile glp, final String suffix, final Object instance) { return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix); } - /** Create the GL for this context. */ - protected GL createGL(final GLProfile glp) { + /** + * Create the GL instance for this context, + * requires valid {@link #getGLProcAddressTable()} result! + */ + private final GL createGL(final GLProfile glp) { final GL gl = (GL) createInstance(glp, true, new Object[] { glp, this } ); /* FIXME: refactor dependence on Java 2D / JOGL bridge @@ -1219,6 +1284,8 @@ public abstract class GLContextImpl extends GLContext { } if( null != finalizeInit ) { ReflectionUtil.callMethod(gl, finalizeInit, new Object[]{ }); + } else { + throw new InternalError("Missing 'void finalizeInit(ProcAddressTable)' in "+gl.getClass().getName()); } } @@ -1296,7 +1363,7 @@ public abstract class GLContextImpl extends GLContext { if(0 == _glGetString) { System.err.println("Error: Entry point to 'glGetString' is NULL."); if(DEBUG) { - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return false; } else { @@ -1304,7 +1371,7 @@ public abstract class GLContextImpl extends GLContext { if(null == _glVendor) { if(DEBUG) { System.err.println("Warning: GL_VENDOR is NULL."); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return false; } @@ -1314,7 +1381,7 @@ public abstract class GLContextImpl extends GLContext { if(null == _glRenderer) { if(DEBUG) { System.err.println("Warning: GL_RENDERER is NULL."); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return false; } @@ -1326,7 +1393,7 @@ public abstract class GLContextImpl extends GLContext { // FIXME if(DEBUG) { System.err.println("Warning: GL_VERSION is NULL."); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return false; } @@ -1370,7 +1437,7 @@ public abstract class GLContextImpl extends GLContext { if( 0 == _glGetIntegerv ) { System.err.println("Error: Entry point to 'glGetIntegerv' is NULL."); if(DEBUG) { - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return false; } else { @@ -1396,8 +1463,8 @@ public abstract class GLContextImpl extends GLContext { * * @param force force the setting, even if is already being set. * This might be useful if you change the OpenGL implementation. - * @param major OpenGL major version - * @param minor OpenGL minor version + * @param major requested OpenGL major version + * @param minor requested OpenGL minor version * @param ctxProfileBits OpenGL context profile and option bits, see {@link javax.media.opengl.GLContext#CTX_OPTION_ANY} * @param strictMatch if <code>true</code> the ctx must * <ul> @@ -1418,7 +1485,7 @@ public abstract class GLContextImpl extends GLContext { */ protected final boolean setGLFunctionAvailability(final boolean force, int major, int minor, int ctxProfileBits, final boolean strictMatch, final boolean withinGLVersionsMapping) { - if(null!=this.gl && null!=glProcAddressTable && !force) { + if( null != this.gl && null != glProcAddressTable && !force ) { return true; // already done and not forced } @@ -1426,11 +1493,6 @@ public abstract class GLContextImpl extends GLContext { throw new GLException("Invalid GL Version Request "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); } - if(null==this.gl || !verifyInstance(gl.getGLProfile(), "Impl", this.gl)) { - setGL( createGL( drawable.getGLProfile() ) ); - } - updateGLXProcAddressTable(); - final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); final int reqCtxProfileBits = ctxProfileBits; @@ -1501,7 +1563,7 @@ public abstract class GLContextImpl extends GLContext { // - _and_ a valid int version was fetched, // otherwise cont. w/ version-string method -> 3.0 > Version || Version > MAX! // - if ( ( major >= 3 || hasGLVersionByString.compareTo(Version300) >= 0 ) && + if ( ( major >= 3 || hasGLVersionByString.compareTo(Version3_0) >= 0 ) && GLContext.isValidGLVersion(ctxProfileBits, hasGLVersionByInt.getMajor(), hasGLVersionByInt.getMinor()) ) { // Strict Match (GLVersionMapping): // Relaxed match for versions ( !isES && major < 3 ) requests, last resort! @@ -1622,54 +1684,67 @@ public abstract class GLContextImpl extends GLContext { System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)); } + updateGLXProcAddressTable(); + // // UpdateGLProcAddressTable functionality + // _and_ setup GL instance, which ctor requires valid getGLProcAddressTable() result! // - ProcAddressTable table = null; - synchronized(mappedContextTypeObjectLock) { - table = mappedGLProcAddress.get( contextFQN ); - if(null != table && !verifyInstance(gl.getGLProfile(), "ProcAddressTable", table)) { - throw new InternalError("GLContext GL ProcAddressTable mapped key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ - ") -> "+ table.getClass().getName()+" not matching "+gl.getGLProfile().getGLImplBaseClassName()); - } - } - if(null != table) { - glProcAddressTable = table; - if(DEBUG) { - System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+") -> "+toHexString(table.hashCode())); - } - } else { - glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), false, - new Object[] { new GLProcAddressResolver() } ); - resetProcAddressTable(getGLProcAddressTable()); + { + final GLProfile glp = drawable.getGLProfile(); + + ProcAddressTable table = null; synchronized(mappedContextTypeObjectLock) { - mappedGLProcAddress.put(contextFQN, getGLProcAddressTable()); + table = mappedGLProcAddress.get( contextFQN ); + if(null != table && !verifyInstance(glp, "ProcAddressTable", table)) { + throw new InternalError("GLContext GL ProcAddressTable mapped key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ") -> "+ table.getClass().getName()+" not matching "+glp.getGLImplBaseClassName()); + } + } + if(null != table) { + glProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+toHexString(getGLProcAddressTable().hashCode())); + System.err.println(getThreadName() + ": GLContext GL ProcAddressTable reusing key("+contextFQN+") -> "+toHexString(table.hashCode())); + } + } else { + glProcAddressTable = (ProcAddressTable) createInstance(glp, false, + new Object[] { new GLProcAddressResolver() } ); + resetProcAddressTable( glProcAddressTable ); + synchronized(mappedContextTypeObjectLock) { + mappedGLProcAddress.put(contextFQN, glProcAddressTable); + if(DEBUG) { + System.err.println(getThreadName() + ": GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+toHexString(glProcAddressTable.hashCode())); + } } } + + if( null == this.gl || !verifyInstance(glp, "Impl", this.gl) ) { + setGL( createGL( glp ) ); + } } // // Update ExtensionAvailabilityCache // - ExtensionAvailabilityCache eCache; - synchronized(mappedContextTypeObjectLock) { - eCache = mappedExtensionAvailabilityCache.get( contextFQN ); - } - if(null != eCache) { - extensionAvailability = eCache; - if(DEBUG) { - System.err.println(getThreadName() + ": GLContext GL ExtensionAvailabilityCache reusing key("+contextFQN+") -> "+toHexString(eCache.hashCode()) + " - entries: "+eCache.getTotalExtensionCount()); - } - } else { - extensionAvailability = new ExtensionAvailabilityCache(); - setContextVersion(major, minor, ctxProfileBits, vendorVersion, false); // pre-set of GL version, required for extension cache usage - extensionAvailability.reset(this); + { + ExtensionAvailabilityCache eCache; synchronized(mappedContextTypeObjectLock) { - mappedExtensionAvailabilityCache.put(contextFQN, extensionAvailability); + eCache = mappedExtensionAvailabilityCache.get( contextFQN ); + } + if(null != eCache) { + extensionAvailability = eCache; if(DEBUG) { - System.err.println(getThreadName() + ": GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+toHexString(extensionAvailability.hashCode()) + " - entries: "+extensionAvailability.getTotalExtensionCount()); + System.err.println(getThreadName() + ": GLContext GL ExtensionAvailabilityCache reusing key("+contextFQN+") -> "+toHexString(eCache.hashCode()) + " - entries: "+eCache.getTotalExtensionCount()); + } + } else { + extensionAvailability = new ExtensionAvailabilityCache(); + setContextVersion(major, minor, ctxProfileBits, vendorVersion, false); // pre-set of GL version, required for extension cache usage + extensionAvailability.reset(this); + synchronized(mappedContextTypeObjectLock) { + mappedExtensionAvailabilityCache.put(contextFQN, extensionAvailability); + if(DEBUG) { + System.err.println(getThreadName() + ": GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+toHexString(extensionAvailability.hashCode()) + " - entries: "+extensionAvailability.getTotalExtensionCount()); + } } } } @@ -1770,6 +1845,22 @@ public abstract class GLContextImpl extends GLContext { } } } + if( GLProfile.disableSurfacelessContext ) { + final int quirk = GLRendererQuirks.NoSurfacelessCtx; + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: disabled"); + } + quirks.addQuirk( quirk ); + if( withinGLVersionsMapping ) { + // Thread safe due to single threaded initialization! + GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); + } else { + // FIXME: Remove when moving EGL/ES to ARB ctx creation + synchronized(GLContextImpl.class) { + GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); + } + } + } // // OS related quirks @@ -1892,7 +1983,7 @@ public abstract class GLContextImpl extends GLContext { // final int quirk = GLRendererQuirks.DontCloseX11Display; if( glRenderer.contains(MesaSP) ) { - if ( glRenderer.contains("X11") && vendorVersion.compareTo(Version800) < 0 ) { + if ( glRenderer.contains("X11") && vendorVersion.compareTo(Version8_0) < 0 ) { if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]"); } @@ -2298,9 +2389,6 @@ public abstract class GLContextImpl extends GLContext { } switch(target) { case GL.GL_FRAMEBUFFER: - boundFBOTarget[0] = framebufferName; // draw - boundFBOTarget[1] = framebufferName; // read - break; case GL2ES3.GL_DRAW_FRAMEBUFFER: boundFBOTarget[0] = framebufferName; // draw break; diff --git a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java index 7519d568b..e682431a9 100644 --- a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java +++ b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java @@ -33,13 +33,13 @@ import java.util.ArrayList; import javax.media.nativewindow.NativeWindowException; import javax.media.opengl.GL2ES2; -import javax.media.opengl.GL2GL3; import javax.media.opengl.GLDebugListener; import javax.media.opengl.GLDebugMessage; import javax.media.opengl.GLException; import jogamp.common.os.PlatformPropsImpl; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.os.Platform; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.opengl.GLExtensions; @@ -308,7 +308,7 @@ public class GLDebugMessageHandler { public void messageSent(final GLDebugMessage event) { System.err.println(event); if(threadDump) { - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } } } diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index b51f290e9..ee984b74a 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -67,6 +67,7 @@ import javax.media.opengl.GLFBODrawable; import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLProfile; +import com.jogamp.common.ExceptionUtils; import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.nativewindow.DelegatedUpstreamSurfaceHookWithSurfaceSize; import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; @@ -128,16 +129,16 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected final boolean createSharedResourceImpl(final AbstractGraphicsDevice device) { final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device ); if(null!=sr) { - return sr.isValid(); + return sr.isAvailable(); } return false; } @Override - public final GLRendererQuirks getRendererQuirks(final AbstractGraphicsDevice device) { + public final GLRendererQuirks getRendererQuirks(final AbstractGraphicsDevice device, final GLProfile glp) { final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device ); if(null!=sr) { - return sr.getRendererQuirks(); + return sr.getRendererQuirks(glp); } return null; } @@ -195,7 +196,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { System.err.println("chosenCapsMod: "+chosenCapsMod); System.err.println("OffscreenLayerSurface: **** "+ols); System.err.println("Target: **** "+target); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } if( ! ( target instanceof MutableSurface ) ) { throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target); @@ -271,9 +272,9 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { @Override public final GLOffscreenAutoDrawable createOffscreenAutoDrawable(final AbstractGraphicsDevice deviceReq, - final GLCapabilitiesImmutable capsRequested, - final GLCapabilitiesChooser chooser, - final int width, final int height) { + final GLCapabilitiesImmutable capsRequested, + final GLCapabilitiesChooser chooser, + final int width, final int height) { final GLDrawable drawable = createOffscreenDrawable( deviceReq, capsRequested, chooser, width, height ); try { drawable.setRealized(true); @@ -306,24 +307,32 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { @Override public final GLDrawable createOffscreenDrawable(final AbstractGraphicsDevice deviceReq, - final GLCapabilitiesImmutable capsRequested, - final GLCapabilitiesChooser chooser, - final int width, final int height) { + final GLCapabilitiesImmutable capsRequested, + final GLCapabilitiesChooser chooser, + final int width, final int height) { if(width<=0 || height<=0) { throw new GLException("initial size must be positive (were (" + width + " x " + height + "))"); } - final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); - if(null == device) { + final SharedResourceRunner.Resource sr = getOrCreateSharedResource( deviceReq ); + if( null == sr ) { throw new GLException("No shared device for requested: "+deviceReq); } - + final AbstractGraphicsDevice device = sr.getDevice(); final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, this, device); if( capsChosen.isFBO() ) { // Use minimum GLCapabilities for the dummy surface w/ same profile - final ProxySurface dummySurface = createDummySurfaceImpl(device, true, new GLCapabilities(capsChosen.getGLProfile()), capsRequested, null, width, height); - final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface); - return new GLFBODrawableImpl.ResizeableImpl(this, dummyDrawable, dummySurface, capsChosen, 0); + final GLProfile glp = capsChosen.getGLProfile(); + final GLCapabilitiesImmutable glCapsMin = new GLCapabilities(glp); + final GLRendererQuirks glrq = sr.getRendererQuirks(glp); + final ProxySurface surface; + if( null != glrq && !glrq.exist(GLRendererQuirks.NoSurfacelessCtx) ) { + surface = createSurfacelessImpl(device, true, glCapsMin, capsRequested, null, width, height); + } else { + surface = createDummySurfaceImpl(device, true, glCapsMin, capsRequested, null, width, height); + } + final GLDrawableImpl drawable = createOnscreenDrawableImpl(surface); + return new GLFBODrawableImpl.ResizeableImpl(this, drawable, surface, capsChosen, 0); } return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, new UpstreamSurfaceHookMutableSize(width, height) ) ); @@ -380,8 +389,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook); /** - * A dummy surface is not visible on screen and will not be used to render directly to, - * it maybe on- or offscreen. + * A dummy surface is not visible on screen, it may be on- or offscreen. * <p> * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. * It also allows creation of framebuffer objects which are used for rendering or using a shared GLContext w/o actually rendering to a usable framebuffer. @@ -409,8 +417,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } /** - * A dummy surface is not visible on screen and will not be used to render directly to, - * it maybe on- or offscreen. + * A dummy surface is not visible on screen and may be on- or offscreen. * <p> * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. * It also allows creation of framebuffer objects which are used for rendering or using a shared GLContext w/o actually rendering to a usable framebuffer. @@ -430,6 +437,27 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice, GLCapabilitiesImmutable chosenCaps, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height); + /** + * A surfaceless {@link ProxySurface} is a non-existing surface and will not be used as a render target. + * <p> + * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} w/o default framebuffer to query information. + * It also allows creation of framebuffer objects which are used for rendering or using a shared GLContext w/o actually rendering to a usable framebuffer. + * </p> + * @param device a valid platform dependent target device. + * @param createNewDevice if <code>true</code> a new device instance is created using <code>device</code> details, + * otherwise <code>device</code> instance is used as-is. + * @param chosenCaps + * @param requestedCaps + * @param chooser the custom chooser, may be null for default + * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()}, not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()}, not the actual dummy surface height, + * The latter is platform specific and small + * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}. + */ + public abstract ProxySurface createSurfacelessImpl(AbstractGraphicsDevice device, boolean createNewDevice, + GLCapabilitiesImmutable chosenCaps, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height); + //--------------------------------------------------------------------------- // // ProxySurface (Wrapped pre-existing native surface) construction diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index 3847b4042..6982418a9 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -355,7 +355,7 @@ public class GLDrawableHelper { } if( DEBUG && ( 0>=newWidth || 0>=newHeight) ) { System.err.println("WARNING: Odd size detected: "+newWidth+"x"+newHeight+", using safe size 1x1. Drawable "+drawable); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } if( 0 >= newWidth ) { newWidth = 1; validateSize=false; } if( 0 >= newHeight ) { newHeight = 1; validateSize=false; } @@ -734,7 +734,7 @@ public class GLDrawableHelper { final int glerr0 = drawable.getGL().glGetError(); if( GL.GL_NO_ERROR != glerr0 ) { System.err.println("Info: GLDrawableHelper.reshape: pre-exisiting GL error 0x"+Integer.toHexString(glerr0)); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } } drawable.getGL().glViewport(x, y, width, height); diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index 544aaf064..7cd887fee 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -51,6 +51,8 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import com.jogamp.common.ExceptionUtils; + public abstract class GLDrawableImpl implements GLDrawable { protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG; @@ -176,7 +178,7 @@ public abstract class GLDrawableImpl implements GLDrawable { final boolean isProxySurface = surface instanceof ProxySurface; if(DEBUG) { System.err.println(getThreadName() + ": setRealized: drawable "+getClass().getSimpleName()+", surface "+surface.getClass().getSimpleName()+", isProxySurface "+isProxySurface+": "+realized+" -> "+realizedArg); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } final AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice(); if(realizedArg) { diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java index 991a351e6..98d1cea71 100644 --- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java @@ -11,6 +11,7 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLFBODrawable; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.VersionUtil; import com.jogamp.nativewindow.MutableGraphicsConfiguration; @@ -104,7 +105,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { private final void setupFBO(final GL gl, final int idx, final int width, final int height, final int samples, final boolean useAlpha, final int depthBits, final int stencilBits, - final boolean useTexture, final boolean realUnbind) { + final boolean useTexture, final boolean setupViewportScissors, final boolean realUnbind) { final FBObject fbo = new FBObject(); fbos[idx] = fbo; @@ -155,6 +156,11 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { // Also remedy for Bug 1020, i.e. OSX/Nvidia's FBO needs to be cleared before blitting, // otherwise first MSAA frame lacks antialiasing. fbo.bind(gl); + if( setupViewportScissors ) { + // Surfaceless: Set initial viewport/scissors + gl.glViewport(0, 0, width, height); + gl.glScissor(0, 0, width, height); + } if( useDepth ) { gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); } else { @@ -171,7 +177,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { if( !initialized && !realize ) { if( DEBUG ) { System.err.println("GLFBODrawableImpl.initialize(): WARNING - Already unrealized!"); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return; // NOP, no exception for de-init twice or no init! } @@ -216,7 +222,9 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { for(int i=0; i<fbosN; i++) { setupFBO(gl, i, width, height, samples, useAlpha, - chosenFBOCaps.getDepthBits(), chosenFBOCaps.getStencilBits(), useTexture, fbosN-1==i); + chosenFBOCaps.getDepthBits(), chosenFBOCaps.getStencilBits(), useTexture, + 0==i && 0 == parent.getHandle() /* setupViewportScissors for surfaceless */, + fbosN-1==i /* unbind */); } fbos[0].formatToGLCapabilities(chosenFBOCaps); chosenFBOCaps.setDoubleBuffered( chosenFBOCaps.getDoubleBuffered() || samples > 0 ); @@ -233,7 +241,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { if(DEBUG) { System.err.println("GLFBODrawableImpl.initialize("+realize+"): "+this); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } } @@ -270,7 +278,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { // resetQuirk fallback fbos[idx].destroy(gl); final boolean useTexture = 0 != ( FBOMODE_USE_TEXTURE & fboModeBits ); - setupFBO(gl, idx, width, height, samples, useAlpha, depthBits, stencilBits, useTexture, true); + setupFBO(gl, idx, width, height, samples, useAlpha, depthBits, stencilBits, useTexture, false, true); } private final void reset(final GL gl, int newSamples) throws GLException { @@ -284,7 +292,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { final boolean ctxSwitch = null != curContext && curContext != ourContext; if(DEBUG) { System.err.println("GLFBODrawableImpl.reset(newSamples "+newSamples+"): BEGIN - ctxSwitch "+ctxSwitch+", "+this); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } Throwable tFBO = null; Throwable tGL = null; diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java index 1fb27cfcf..4d6de8d13 100644 --- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java +++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java @@ -204,7 +204,7 @@ public class GLGraphicsConfigurationUtil { final boolean fboAvailable = GLContext.isFBOAvailable(device, glp); final boolean pbufferAvailable = factory.canCreateGLPbuffer(device, glp); - final GLRendererQuirks glrq = factory.getRendererQuirks(device); + final GLRendererQuirks glrq = factory.getRendererQuirks(device, glp); final boolean bitmapAvailable; final boolean doubleBufferAvailable; diff --git a/src/jogl/classes/jogamp/opengl/ProjectFloat.java b/src/jogl/classes/jogamp/opengl/ProjectFloat.java index 5921eb9a9..235d3eb60 100644 --- a/src/jogl/classes/jogamp/opengl/ProjectFloat.java +++ b/src/jogl/classes/jogamp/opengl/ProjectFloat.java @@ -118,6 +118,7 @@ package jogamp.opengl; import java.nio.FloatBuffer; import java.nio.IntBuffer; +import javax.media.opengl.GLException; import javax.media.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.opengl.math.FloatUtil; @@ -169,8 +170,9 @@ public class ProjectFloat { * @param aspect * @param zNear * @param zFar + * @throws GLException with GL_INVALID_VALUE if zNear is <= 0, or zFar < 0, or if zNear == zFar. */ - public void gluPerspective(final GLMatrixFunc gl, final float fovy_deg, final float aspect, final float zNear, final float zFar) { + public void gluPerspective(final GLMatrixFunc gl, final float fovy_deg, final float aspect, final float zNear, final float zFar) throws GLException { gl.glMultMatrixf(FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy_deg * FloatUtil.PI / 180.0f, aspect, zNear, zFar), 0); } diff --git a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java index 93a4eb32e..bf8891a25 100644 --- a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java +++ b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java @@ -30,21 +30,24 @@ package jogamp.opengl; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; + import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.opengl.GLProfile; +import com.jogamp.common.ExceptionUtils; import com.jogamp.opengl.GLRendererQuirks; public class SharedResourceRunner implements Runnable { protected static final boolean DEBUG = GLDrawableImpl.DEBUG; public static interface Resource { - boolean isValid(); + boolean isAvailable(); AbstractGraphicsDevice getDevice(); AbstractGraphicsScreen getScreen(); GLDrawableImpl getDrawable(); GLContextImpl getContext(); - GLRendererQuirks getRendererQuirks(); + GLRendererQuirks getRendererQuirks(GLProfile glp); } public static interface Implementation { @@ -52,19 +55,19 @@ public class SharedResourceRunner implements Runnable { * <p> * Called within synchronized block. * </p> - * @param connection for creation a {@link AbstractGraphicsDevice} instance. + * @param device for creation a {@link AbstractGraphicsDevice} instance. * @return <code>true</code> if the device supports all protocols required for the implementation, otherwise <code>false</code>. */ - boolean isDeviceSupported(String connection); + boolean isDeviceSupported(final AbstractGraphicsDevice device); /** * <p> * Called within synchronized block. * </p> - * @param connection for creation a {@link AbstractGraphicsDevice} instance. + * @param device for creation a {@link AbstractGraphicsDevice} instance. * @return A new shared resource instance */ - Resource createSharedResource(String connection); + Resource createSharedResource(final AbstractGraphicsDevice device); /** Called within synchronized block. */ void releaseSharedResource(Resource shared); @@ -72,9 +75,9 @@ public class SharedResourceRunner implements Runnable { void clear(); /** Called within synchronized block. */ - Resource mapPut(String connection, Resource resource); + Resource mapPut(final AbstractGraphicsDevice device, final Resource resource); /** Called within synchronized block. */ - Resource mapGet(String connection); + Resource mapGet(final AbstractGraphicsDevice device); /** Called within synchronized block. */ Collection<Resource> mapValues(); } @@ -86,17 +89,17 @@ public class SharedResourceRunner implements Runnable { boolean running; boolean ready; boolean shouldRelease; - String initConnection; - String releaseConnection; + AbstractGraphicsDevice initDevice; + AbstractGraphicsDevice releaseDevice; - private boolean getDeviceTried(final String connection) { // synchronized call - return devicesTried.contains(connection); + private boolean getDeviceTried(final AbstractGraphicsDevice device) { // synchronized call + return devicesTried.contains(device.getConnection()); } - private void addDeviceTried(final String connection) { // synchronized call - devicesTried.add(connection); + private void addDeviceTried(final AbstractGraphicsDevice device) { // synchronized call + devicesTried.add(device.getConnection()); } - private void removeDeviceTried(final String connection) { // synchronized call - devicesTried.remove(connection); + private void removeDeviceTried(final AbstractGraphicsDevice device) { // synchronized call + devicesTried.remove(device.getConnection()); } public SharedResourceRunner(final Implementation impl) { @@ -110,8 +113,8 @@ public class SharedResourceRunner implements Runnable { ready = false; running = false; shouldRelease = false; - initConnection = null; - releaseConnection = null; + initDevice = null; + releaseDevice = null; } /** @@ -176,20 +179,20 @@ public class SharedResourceRunner implements Runnable { if(null != device) { synchronized (this) { start(); - final String connection = device.getConnection(); - sr = impl.mapGet(connection); + sr = impl.mapGet(device); if (null == sr) { - if ( !getDeviceTried(connection) ) { - addDeviceTried(connection); + if ( !getDeviceTried(device) ) { + addDeviceTried(device); if (DEBUG) { - System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": trying - "+getThreadName()); + System.err.println("SharedResourceRunner.getOrCreateShared() " + device + ": trying - "+getThreadName()); + ExceptionUtils.dumpStack(System.err); } - if ( impl.isDeviceSupported(connection) ) { - doAndWait(connection, null); - sr = impl.mapGet(connection); + if ( impl.isDeviceSupported(device) ) { + doAndWait(device, null); + sr = impl.mapGet(device); } if (DEBUG) { - System.err.println("SharedResourceRunner.getOrCreateShared() " + connection + ": "+ ( ( null != sr ) ? "success" : "failed" ) +" - "+getThreadName()); + System.err.println("SharedResourceRunner.getOrCreateShared() " + device + ": "+ ( ( null != sr ) ? "success" : "failed" ) +" - "+getThreadName()); } } } @@ -202,16 +205,15 @@ public class SharedResourceRunner implements Runnable { SharedResourceRunner.Resource sr = null; if(null != device) { synchronized (this) { - final String connection = device.getConnection(); - sr = impl.mapGet(connection); + sr = impl.mapGet(device); if (null != sr) { - removeDeviceTried(connection); + removeDeviceTried(device); if (DEBUG) { - System.err.println("SharedResourceRunner.releaseShared() " + connection + ": trying - "+getThreadName()); + System.err.println("SharedResourceRunner.releaseShared() " + device + ": trying - "+getThreadName()); } - doAndWait(null, connection); + doAndWait(null, device); if (DEBUG) { - System.err.println("SharedResourceRunner.releaseShared() " + connection + ": done - "+getThreadName()); + System.err.println("SharedResourceRunner.releaseShared() " + device + ": done - "+getThreadName()); } } } @@ -219,13 +221,13 @@ public class SharedResourceRunner implements Runnable { return sr; } - private final void doAndWait(final String initConnection, final String releaseConnection) { + private final void doAndWait(final AbstractGraphicsDevice initDevice, final AbstractGraphicsDevice releaseDevice) { synchronized (this) { // wait until thread becomes ready to init new device, // pass the device and release the sync final String threadName = getThreadName(); if (DEBUG) { - System.err.println("SharedResourceRunner.doAndWait() START init: " + initConnection + ", release: "+releaseConnection+" - "+threadName); + System.err.println("SharedResourceRunner.doAndWait() START init: " + initDevice + ", release: "+releaseDevice+" - "+threadName); } while (!ready && running) { try { @@ -233,20 +235,20 @@ public class SharedResourceRunner implements Runnable { } catch (final InterruptedException ex) { } } if (DEBUG) { - System.err.println("SharedResourceRunner.doAndWait() set command: " + initConnection + ", release: "+releaseConnection+" - "+threadName); + System.err.println("SharedResourceRunner.doAndWait() set command: " + initDevice + ", release: "+releaseDevice+" - "+threadName); } - this.initConnection = initConnection; - this.releaseConnection = releaseConnection; + this.initDevice = initDevice; + this.releaseDevice = releaseDevice; this.notifyAll(); // wait until thread has init/released the device - while ( running && ( !ready || null != this.initConnection || null != this.releaseConnection ) ) { + while ( running && ( !ready || null != this.initDevice || null != this.releaseDevice ) ) { try { this.wait(); } catch (final InterruptedException ex) { } } if (DEBUG) { - System.err.println("SharedResourceRunner.initializeAndWait END init: " + initConnection + ", release: "+releaseConnection+" - "+threadName); + System.err.println("SharedResourceRunner.initializeAndWait END init: " + initDevice + ", release: "+releaseDevice+" - "+threadName); } } // done @@ -283,40 +285,40 @@ public class SharedResourceRunner implements Runnable { if (!shouldRelease) { if (DEBUG) { - System.err.println("SharedResourceRunner.run(): WOKE UP for device connection init: " + initConnection + - ", release: " + releaseConnection + " - " + threadName); + System.err.println("SharedResourceRunner.run(): WOKE UP for device connection init: " + initDevice + + ", release: " + releaseDevice + " - " + threadName); } - if(null != initConnection) { + if(null != initDevice) { if (DEBUG) { - System.err.println("SharedResourceRunner.run(): create Shared for: " + initConnection + " - " + threadName); + System.err.println("SharedResourceRunner.run(): create Shared for: " + initDevice + " - " + threadName); } Resource sr = null; try { - sr = impl.createSharedResource(initConnection); + sr = impl.createSharedResource(initDevice); } catch (final Exception e) { e.printStackTrace(); } if (null != sr) { - impl.mapPut(initConnection, sr); + impl.mapPut(initDevice, sr); } } - if(null != releaseConnection) { + if(null != releaseDevice) { if (DEBUG) { - System.err.println("SharedResourceRunner.run(): release Shared for: " + releaseConnection + " - " + threadName); + System.err.println("SharedResourceRunner.run(): release Shared for: " + releaseDevice + " - " + threadName); } - final Resource sr = impl.mapGet(releaseConnection); + final Resource sr = impl.mapGet(releaseDevice); if (null != sr) { try { impl.releaseSharedResource(sr); - impl.mapPut(releaseConnection, null); + impl.mapPut(releaseDevice, null); } catch (final Exception e) { e.printStackTrace(); } } } } - initConnection = null; - releaseConnection = null; + initDevice = null; + releaseDevice = null; } if (DEBUG) { diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java index a5f5b4702..b6fa68600 100644 --- a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java +++ b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java @@ -46,6 +46,7 @@ import java.util.Map.Entry; import javax.imageio.ImageIO; import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.PixelFormat; import javax.media.opengl.GL; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilitiesImmutable; @@ -288,8 +289,9 @@ public class AWTTilePainter { final int tWidth = renderer.getParam(TileRenderer.TR_TILE_WIDTH); final int tHeight = renderer.getParam(TileRenderer.TR_TILE_HEIGHT); final AWTGLPixelBufferProvider printBufferProvider = new AWTGLPixelBufferProvider( true /* allowRowStride */ ); - final GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, componentCount); - tBuffer = printBufferProvider.allocate(gl, pixelAttribs, tWidth, tHeight, 1, true, 0); + final PixelFormat.Composition hostPixelComp = printBufferProvider.getHostPixelComp(gl.getGLProfile(), componentCount); + final GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, componentCount, true); + tBuffer = printBufferProvider.allocate(gl, hostPixelComp, pixelAttribs, true, tWidth, tHeight, 1, 0); renderer.setTileBuffer(tBuffer); if( flipVertical ) { vFlipImage = new BufferedImage(tBuffer.width, tBuffer.height, tBuffer.image.getType()); diff --git a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java index 8c6091273..245b6a945 100644 --- a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java @@ -28,9 +28,12 @@ package jogamp.opengl.egl; -import java.util.*; +import java.util.ArrayList; +import java.util.List; -import jogamp.opengl.*; +import com.jogamp.opengl.egl.EGL; + +import jogamp.opengl.GLDynamicLibraryBundleInfo; /** * Implementation of the DynamicLookupHelper for Desktop ES2 (AMD, ..) @@ -56,7 +59,7 @@ public final class DesktopES2DynamicLibraryBundleInfo extends GLDynamicLibraryBu @Override public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) { - return EGL.eglGetProcAddress(toolGetProcAddressHandle, funcName); + return EGLContext.eglGetProcAddress(toolGetProcAddressHandle, funcName); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index 964401244..b3c848012 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -50,20 +50,31 @@ import javax.media.opengl.GLProfile; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.egl.EGLExtImpl; +import jogamp.opengl.egl.EGLExtProcAddressTable; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; import com.jogamp.opengl.GLRendererQuirks; +import com.jogamp.opengl.egl.EGL; +import com.jogamp.opengl.egl.EGLExt; public class EGLContext extends GLContextImpl { - private boolean eglQueryStringInitialized; - private boolean eglQueryStringAvailable; - private EGLExt _eglExt; // Table that holds the addresses of the native C-language entry points for // EGL extension functions. private EGLExtProcAddressTable eglExtProcAddressTable; + private EGLExtImpl eglExtImpl; + + static final int CTX_PROFILE_COMPAT = GLContext.CTX_PROFILE_COMPAT; + static final int CTX_PROFILE_CORE = GLContext.CTX_PROFILE_CORE; + static final int CTX_PROFILE_ES = GLContext.CTX_PROFILE_ES; + + public static String getGLProfile(final int major, final int minor, final int ctp) throws GLException { + return GLContext.getGLProfile(major, minor, ctp); + } EGLContext(final GLDrawableImpl drawable, final GLContext shareWith) { @@ -72,10 +83,8 @@ public class EGLContext extends GLContextImpl { @Override protected void resetStates(final boolean isInit) { - eglQueryStringInitialized = false; - eglQueryStringAvailable = false; eglExtProcAddressTable = null; - // no inner state _eglExt = null; + eglExtImpl = null; super.resetStates(isInit); } @@ -84,11 +93,8 @@ public class EGLContext extends GLContextImpl { return getEGLExt(); } - public EGLExt getEGLExt() { - if (_eglExt == null) { - _eglExt = new EGLExtImpl(this); - } - return _eglExt; + public final EGLExt getEGLExt() { + return eglExtImpl; } @Override @@ -96,10 +102,6 @@ public class EGLContext extends GLContextImpl { return eglExtProcAddressTable; } - public final EGLExtProcAddressTable getEGLExtProcAddressTable() { - return eglExtProcAddressTable; - } - @Override protected Map<String, String> getFunctionNameMap() { return null; } @@ -140,11 +142,6 @@ public class EGLContext extends GLContextImpl { } @Override - protected long createContextARBImpl(final long share, final boolean direct, final int ctp, final int major, final int minor) { - return 0; // FIXME - } - - @Override protected void destroyContextARBImpl(final long _context) { if (!EGL.eglDestroyContext(drawable.getNativeSurface().getDisplayHandle(), _context)) { final int eglError = EGL.eglGetError(); @@ -155,14 +152,35 @@ public class EGLContext extends GLContextImpl { } } + private static final int ctx_attribs_idx_major = 0; + private static final int ctx_attribs_rom[] = { + /* 0 */ EGLExt.EGL_CONTEXT_MAJOR_VERSION_KHR, 0, // alias of EGL.EGL_CONTEXT_CLIENT_VERSION + /* 2 */ EGL.EGL_NONE, EGL.EGL_NONE, // EGLExt.EGL_CONTEXT_MINOR_VERSION_KHR + /* 4 */ EGL.EGL_NONE, EGL.EGL_NONE, // EGLExt.EGL_CONTEXT_FLAGS_KHR + /* 6 */ EGL.EGL_NONE, EGL.EGL_NONE, // EGLExt.EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR + /* 8 */ EGL.EGL_NONE, EGL.EGL_NONE, // EGLExt.EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR + /* 10 */ EGL.EGL_NONE + }; + @Override - protected boolean createImpl(final long shareWithHandle) throws GLException { + protected long createContextARBImpl(final long share, final boolean direct, final int ctp, final int reqMajor, final int reqMinor) { final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); - final long eglDisplay = config.getScreen().getDevice().getHandle(); - final GLProfile glProfile = drawable.getGLProfile(); + final EGLGraphicsDevice device = (EGLGraphicsDevice) config.getScreen().getDevice(); + final long eglDisplay = device.getHandle(); final long eglConfig = config.getNativeConfig(); - // 0 == EGL.EGL_NO_CONTEXT; - + final EGLDrawableFactory factory = (EGLDrawableFactory) drawable.getFactoryImpl(); + + final boolean useKHRCreateContext = !GLProfile.disableOpenGLARBContext && factory.hasDefaultDeviceKHRCreateContext(); + final boolean ctDesktopGL = 0 == ( GLContext.CTX_PROFILE_ES & ctp ); + final boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; + final boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; + final boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; + + if(DEBUG) { + System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: Start "+getGLVersion(reqMajor, reqMinor, ctp, "@creation") + + ", useKHRCreateContext "+useKHRCreateContext + + ", device "+device); + } if ( 0 == eglDisplay ) { throw new GLException("Error: attempted to create an OpenGL context without a display connection"); } @@ -170,72 +188,150 @@ public class EGLContext extends GLContextImpl { throw new GLException("Error: attempted to create an OpenGL context without a graphics configuration"); } + if( !useKHRCreateContext && ctDesktopGL ) { + if(DEBUG) { + System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: DesktopGL not avail "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")); + } + return 0; // n/a + } try { // might be unavailable on EGL < 1.2 - if( !EGL.eglBindAPI(EGL.EGL_OPENGL_ES_API) ) { - throw new GLException("Caught: eglBindAPI to ES failed , error "+toHexString(EGL.eglGetError())); + if( !EGL.eglBindAPI( ctDesktopGL ? EGL.EGL_OPENGL_API : EGL.EGL_OPENGL_ES_API) ) { + throw new GLException("Caught: eglBindAPI to "+(ctDesktopGL ? "ES" : "GL")+" failed , error "+toHexString(EGL.eglGetError())+" - "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")); } } catch (final GLException glex) { if (DEBUG) { - glex.printStackTrace(); + ExceptionUtils.dumpThrowable("", glex); } } - // Cannot check extension 'EGL_KHR_create_context' before having one current! + final int useMajor; + if( reqMajor >= 3 && + GLRendererQuirks.existStickyDeviceQuirk( GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) { + useMajor = 2; + } else { + useMajor = reqMajor; + } + + final IntBuffer attribs = Buffers.newDirectIntBuffer(ctx_attribs_rom); + if( useKHRCreateContext ) { + attribs.put(ctx_attribs_idx_major + 1, useMajor); - final IntBuffer contextAttrsNIO; - final int contextVersionReq, contextVersionAttr; - { - if ( glProfile.usesNativeGLES3() ) { - contextVersionReq = 3; - if( GLRendererQuirks.existStickyDeviceQuirk( GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) { - contextVersionAttr = 2; + int index = ctx_attribs_idx_major + 2; + + /** if( ctDesktopGL && reqMinor >= 0 ) { // FIXME: No minor version probing for ES currently! + attribs.put(index + 0, EGLExt.EGL_CONTEXT_MINOR_VERSION_KHR); + attribs.put(index + 1, reqMinor); + index += 2; + } */ + + if( ctDesktopGL && ( useMajor > 3 || useMajor == 3 && reqMinor >= 2 ) ) { + attribs.put(index + 0, EGLExt.EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR); + if( ctBwdCompat ) { + attribs.put(index + 1, EGLExt.EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR); } else { - contextVersionAttr = 3; + attribs.put(index + 1, EGLExt.EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR); + } + index += 2; + } + int flags = 0; + if( ctDesktopGL && useMajor >= 3 && !ctBwdCompat && ctFwdCompat ) { + flags |= EGLExt.EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; + } + if( ctDebug ) { + flags |= EGLExt.EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; + } + // TODO: flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR + if( 0 != flags ) { + attribs.put(index + 0, EGLExt.EGL_CONTEXT_FLAGS_KHR); + attribs.put(index + 1, flags); + index += 2; + } + if(DEBUG) { + System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: attrs.1: major "+useMajor+", flags "+toHexString(flags)+", index "+index); + } + } else { + attribs.put(ctx_attribs_idx_major + 1, useMajor); + if(DEBUG) { + System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: attrs.2: major "+useMajor); + } + } + + long ctx=0; + try { + ctx = EGL.eglCreateContext(eglDisplay, eglConfig, share, attribs); + } catch (final RuntimeException re) { + if(DEBUG) { + System.err.println(getThreadName()+": Info: EGLContext.createContextARBImpl glXCreateContextAttribsARB failed with "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")); + ExceptionUtils.dumpThrowable("", re); + } + } + + if(0!=ctx) { + if (!EGL.eglMakeCurrent(eglDisplay, drawable.getHandle(), drawableRead.getHandle(), ctx)) { + if(DEBUG) { + System.err.println(getThreadName()+": EGLContext.createContextARBImpl couldn't make current "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")+" - error "+toHexString(EGL.eglGetError())); } + // release & destroy + EGL.eglMakeCurrent(eglDisplay, EGL.EGL_NO_SURFACE, EGL.EGL_NO_SURFACE, EGL.EGL_NO_CONTEXT); + EGL.eglDestroyContext(eglDisplay, ctx); + ctx = 0; + } else if (DEBUG) { + System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: OK "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")+", share "+share+", direct "+direct); + } + } else if (DEBUG) { + System.err.println(getThreadName() + ": EGLContext.createContextARBImpl: NO "+getGLVersion(reqMajor, reqMinor, ctp, "@creation")+" - error "+toHexString(EGL.eglGetError())); + } + + return ctx; + } + + @Override + protected boolean createImpl(final long shareWithHandle) throws GLException { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); + final AbstractGraphicsDevice device = config.getScreen().getDevice(); + final boolean availableGLVersionsSet = GLContext.getAvailableGLVersionsSet(device); + + if( !GLProfile.disableOpenGLARBContext && availableGLVersionsSet ) { + contextHandle = createContextARB(shareWithHandle, true); + if( 0 == contextHandle ) { + throw new GLException(getThreadName()+": Unable to create temp OpenGL context(0) on eglDevice "+device+ + ", eglConfig "+config+", "+drawable.getGLProfile()+", shareWith "+toHexString(shareWithHandle)+", error "+toHexString(EGL.eglGetError())); + } + } else { + final GLProfile glProfile = drawable.getGLProfile(); + final int reqMajor; + if ( glProfile.usesNativeGLES3() ) { + reqMajor = 3; } else if ( glProfile.usesNativeGLES2() ) { - contextVersionReq = 2; - contextVersionAttr = 2; + reqMajor = 2; } else if ( glProfile.usesNativeGLES1() ) { - contextVersionReq = 1; - contextVersionAttr = 1; + reqMajor = 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); - if (contextHandle == 0) { - throw new GLException("Error creating OpenGL context: eglDisplay "+toHexString(eglDisplay)+ - ", eglConfig "+config+", "+glProfile+", shareWith "+toHexString(shareWithHandle)+", error "+toHexString(EGL.eglGetError())); + final int ctp = GLContext.CTX_PROFILE_ES | getContextCreationFlags(); + contextHandle = createContextARBImpl(shareWithHandle, true, ctp, reqMajor, 0); + if( 0 == contextHandle ) { + throw new GLException(getThreadName()+": Unable to create temp OpenGL context(1) on eglDevice "+device+ + ", eglConfig "+config+", "+drawable.getGLProfile()+", shareWith "+toHexString(shareWithHandle)+", error "+toHexString(EGL.eglGetError())); + } + if( !setGLFunctionAvailability(true, reqMajor, 0, ctp, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { + 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; + throw new InternalError("setGLFunctionAvailability !strictMatch failed"); + } } if (DEBUG) { - System.err.println(getThreadName() + ": Created OpenGL context 0x" + + System.err.println(getThreadName() + ": EGLContext.createImpl: Created OpenGL context 0x" + 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(eglDisplay, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { - throw new GLException("Error making context " + - toHexString(contextHandle) + " current: error code " + toHexString(EGL.eglGetError())); - } - 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; - } + return true; } @Override @@ -246,8 +342,6 @@ public class EGLContext extends GLContextImpl { if (DEBUG) { System.err.println(getThreadName() + ": Initializing EGLextension address table: "+key); } - eglQueryStringInitialized = false; - eglQueryStringAvailable = false; ProcAddressTable table = null; synchronized(mappedContextTypeObjectLock) { @@ -258,31 +352,52 @@ public class EGLContext extends GLContextImpl { if(DEBUG) { System.err.println(getThreadName() + ": GLContext EGL ProcAddressTable reusing key("+key+") -> "+toHexString(table.hashCode())); } + if( null == eglExtImpl || eglExtImpl.getProcAdressTable() != eglExtProcAddressTable ) { + eglExtImpl = new EGLExtImpl(this, eglExtProcAddressTable); + } } else { eglExtProcAddressTable = new EGLExtProcAddressTable(new GLProcAddressResolver()); - resetProcAddressTable(getEGLExtProcAddressTable()); + resetProcAddressTable(eglExtProcAddressTable); synchronized(mappedContextTypeObjectLock) { - mappedGLXProcAddress.put(key, getEGLExtProcAddressTable()); + mappedGLXProcAddress.put(key, eglExtProcAddressTable); if(DEBUG) { - System.err.println(getThreadName() + ": GLContext EGL ProcAddressTable mapping key("+key+") -> "+toHexString(getEGLExtProcAddressTable().hashCode())); + System.err.println(getThreadName() + ": GLContext EGL ProcAddressTable mapping key("+key+") -> "+toHexString(eglExtProcAddressTable.hashCode())); } } + eglExtImpl = new EGLExtImpl(this, eglExtProcAddressTable); } } @Override protected final StringBuilder getPlatformExtensionsStringImpl() { + final EGLGraphicsDevice device = (EGLGraphicsDevice) drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); + return getPlatformExtensionsStringImpl(device); + } + final static StringBuilder getPlatformExtensionsStringImpl(final EGLGraphicsDevice device) { final StringBuilder sb = new StringBuilder(); - if (!eglQueryStringInitialized) { - eglQueryStringAvailable = getDrawableImpl().getGLDynamicLookupHelper().isFunctionAvailable("eglQueryString"); - eglQueryStringInitialized = true; - } - if (eglQueryStringAvailable) { - final String ret = EGL.eglQueryString(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_EXTENSIONS); + device.lock(); + try{ + final long handle = device.getHandle(); if (DEBUG) { - System.err.println("EGL extensions: " + ret); + System.err.println("EGL PlatformExtensions: Device "+device); + EGLDrawableFactory.dumpEGLInfo("EGL PlatformExtensions: ", handle); } - sb.append(ret); + if( device.getEGLVersion().compareTo(Version1_5) >= 0 ) { + final String ret = EGL.eglQueryString(EGL.EGL_NO_DISPLAY, EGL.EGL_EXTENSIONS); + if (DEBUG) { + System.err.println("EGL extensions (Client): " + ret); + } + sb.append(ret).append(" "); + } + if( 0 != handle ) { + final String ret = EGL.eglQueryString(handle, EGL.EGL_EXTENSIONS); + if (DEBUG) { + System.err.println("EGL extensions (Server): " + ret); + } + sb.append(ret).append(" "); + } + } finally { + device.unlock(); } return sb; } @@ -295,6 +410,16 @@ public class EGLContext extends GLContextImpl { return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval); } + static long eglGetProcAddress(final long eglGetProcAddressHandle, final String procname) + { + if (0 == eglGetProcAddressHandle) { + throw new GLException("Passed null pointer for method \"eglGetProcAddress\""); + } + return dispatch_eglGetProcAddress0(procname, eglGetProcAddressHandle); + } + /** Entry point to C language function: <code> __EGLFuncPtr eglGetProcAddress(const char * procname) </code> <br>Part of <code>EGL_VERSION_1_X</code> */ + static private native long dispatch_eglGetProcAddress0(String procname, long procAddress); + // // Accessible .. // @@ -343,8 +468,8 @@ public class EGLContext extends GLContextImpl { protected static boolean getAvailableGLVersionsSet(final AbstractGraphicsDevice device) { return GLContext.getAvailableGLVersionsSet(device); } - protected static void setAvailableGLVersionsSet(final AbstractGraphicsDevice device) { - GLContext.setAvailableGLVersionsSet(device); + protected static void setAvailableGLVersionsSet(final AbstractGraphicsDevice device, final boolean set) { + GLContext.setAvailableGLVersionsSet(device, set); } protected static String toHexString(final int hex) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java index 9499c70f4..199b20464 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java @@ -39,8 +39,11 @@ import javax.media.opengl.GLException; import jogamp.opengl.Debug; +import com.jogamp.common.ExceptionUtils; +import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.LongObjectHashMap; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.egl.EGL; /** * This implementation provides recursive calls to @@ -148,7 +151,7 @@ public class EGLDisplayUtil { if(DEBUG || verbose || openEGLDisplays.size() > 0 ) { System.err.println("EGLDisplayUtil.EGLDisplays: Shutdown (open: "+openEGLDisplays.size()+")"); if(DEBUG) { - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } if( openEGLDisplays.size() > 0) { dumpOpenDisplayConnections(); @@ -198,17 +201,30 @@ public class EGLDisplayUtil { * * @see EGL#eglInitialize(long, IntBuffer, IntBuffer) */ - private static synchronized boolean eglInitialize(final long eglDisplay, final IntBuffer major, final IntBuffer minor) { + private static synchronized boolean eglInitialize(final long eglDisplay, final int[] major, final int[] minor) { if( EGL.EGL_NO_DISPLAY == eglDisplay) { return false; } - final EGLDisplayRef d = EGLDisplayRef.getOrCreateOpened(eglDisplay, major, minor); + final EGLDisplayRef d = EGLDisplayRef.getOrCreateOpened(eglDisplay, _eglMajorVersion, _eglMinorVersion); + final int _major = _eglMajorVersion.get(0); + final int _minor = _eglMinorVersion.get(0); + if( null != major && null != minor ) { + if( null != d ) { + major[0] = _major; + minor[0] = _minor; + } else { + major[0] = 0; + minor[0] = 0; + } + } if(DEBUG) { - System.err.println("EGLDisplayUtil.eglInitialize("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+(null != d)+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")"); + System.err.println("EGLDisplayUtil.eglInitialize("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+(null != d)+", eglVersion "+_major+"."+_minor+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")"); // Thread.dumpStack(); } return null != d; } + private static final IntBuffer _eglMajorVersion = Buffers.newDirectIntBuffer(1); + private static final IntBuffer _eglMinorVersion = Buffers.newDirectIntBuffer(1); /** * @param nativeDisplayID @@ -222,7 +238,7 @@ public class EGLDisplayUtil { * @see #eglGetDisplay(long) * @see #eglInitialize(long, IntBuffer, IntBuffer) */ - private static synchronized int eglGetDisplayAndInitialize(final long nativeDisplayID, final long[] eglDisplay, final int[] eglErr, final IntBuffer major, final IntBuffer minor) { + private static synchronized int eglGetDisplayAndInitialize(final long nativeDisplayID, final long[] eglDisplay, final int[] eglErr, final int[] major, final int[] minor) { eglDisplay[0] = EGL.EGL_NO_DISPLAY; final long _eglDisplay = eglGetDisplay( nativeDisplayID ); if ( EGL.EGL_NO_DISPLAY == _eglDisplay ) { @@ -244,13 +260,15 @@ public class EGLDisplayUtil { * * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails incl fallback * @param nativeDisplayID in/out array of size 1, passing the requested nativeVisualID, may return a different revised nativeVisualID handle + * @param major + * @param minor * @return the initialized EGL display ID * @throws GLException if not successful */ - private static synchronized long eglGetDisplayAndInitialize(final long[] nativeDisplayID) { + private static synchronized long eglGetDisplayAndInitialize(final long[] nativeDisplayID, final int[] major, final int[] minor) { final long[] eglDisplay = new long[1]; final int[] eglError = new int[1]; - int eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(nativeDisplayID[0], eglDisplay, eglError, null, null); + int eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(nativeDisplayID[0], eglDisplay, eglError, major, minor); if( EGL.EGL_SUCCESS == eglRes ) { return eglDisplay[0]; } @@ -258,7 +276,7 @@ public class EGLDisplayUtil { if(DEBUG) { System.err.println("EGLDisplayUtil.eglGetAndInitDisplay failed with native "+EGLContext.toHexString(nativeDisplayID[0])+", error "+EGLContext.toHexString(eglRes)+"/"+EGLContext.toHexString(eglError[0])+" - fallback!"); } - eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(EGL.EGL_DEFAULT_DISPLAY, eglDisplay, eglError, null, null); + eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(EGL.EGL_DEFAULT_DISPLAY, eglDisplay, eglError, major, minor); if( EGL.EGL_SUCCESS == eglRes ) { nativeDisplayID[0] = EGL.EGL_DEFAULT_DISPLAY; return eglDisplay[0]; @@ -286,8 +304,8 @@ public class EGLDisplayUtil { private static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() { @Override - public long eglGetAndInitDisplay(final long[] nativeDisplayID) { - return eglGetDisplayAndInitialize(nativeDisplayID); + public long eglGetAndInitDisplay(final long[] nativeDisplayID, final int[] major, final int[] minor) { + return eglGetDisplayAndInitialize(nativeDisplayID, major, minor); } @Override public void eglTerminate(final long eglDisplayHandle) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index bacf9f18e..5b080a183 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -36,114 +36,66 @@ package jogamp.opengl.egl; -import java.nio.IntBuffer; - -import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.ProxySurface; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; +import jogamp.nativewindow.ProxySurfaceImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; -import com.jogamp.common.nio.Buffers; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.egl.EGL; -public abstract class EGLDrawable extends GLDrawableImpl { +public class EGLDrawable extends GLDrawableImpl { + static boolean DEBUG = GLDrawableImpl.DEBUG; - protected EGLDrawable(final EGLDrawableFactory factory, final NativeSurface component) throws GLException { + protected EGLDrawable(final EGLDrawableFactory factory, final EGLSurface component) throws GLException { super(factory, component, false); } @Override - public abstract GLContext createContext(GLContext shareWith); - - protected abstract long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle); - - private final long createEGLSurface() { - final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; - final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) eglws.getGraphicsConfiguration(); - final NativeSurface upstreamSurface = eglws.getUpstreamSurface(); - - long eglSurface = createSurface(eglConfig, eglws.getSurfaceWidth(), eglws.getSurfaceHeight(), upstreamSurface.getSurfaceHandle()); - - int eglError0; - if (EGL.EGL_NO_SURFACE == eglSurface) { - eglError0 = EGL.eglGetError(); - if(EGL.EGL_BAD_NATIVE_WINDOW == eglError0) { - // Try window handle if available and differs (Windows HDC / HWND). - // ANGLE impl. required HWND on Windows. - if(upstreamSurface instanceof NativeWindow) { - final NativeWindow nw = (NativeWindow) upstreamSurface; - if(nw.getWindowHandle() != nw.getSurfaceHandle()) { - if(DEBUG) { - System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle"); - } - eglSurface = createSurface(eglConfig, eglws.getSurfaceWidth(), eglws.getSurfaceHeight(), nw.getWindowHandle()); - if (EGL.EGL_NO_SURFACE == eglSurface) { - eglError0 = EGL.eglGetError(); - } - } - } - } - } else { - eglError0 = EGL.EGL_SUCCESS; - } - if (EGL.EGL_NO_SURFACE == eglSurface) { - throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0)); - } - if(DEBUG) { - System.err.println(getThreadName() + ": createEGLSurface handle "+toHexString(eglSurface)); - } - return eglSurface; + public final GLContext createContext(final GLContext shareWith) { + return new EGLContext(this, shareWith); } @Override protected final void createHandle() { - final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + final EGLSurface eglSurf = (EGLSurface) surface; if(DEBUG) { - System.err.println(getThreadName() + ": createHandle of "+eglws); + System.err.println(getThreadName() + ": createHandle of "+eglSurf); + ProxySurfaceImpl.dumpHierarchy(System.err, eglSurf); } - if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { - if( EGL.EGL_NO_SURFACE != eglws.getSurfaceHandle() ) { - throw new InternalError("Set surface but claimed to be invalid: "+eglws); + if( eglSurf.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( EGL.EGL_NO_SURFACE != eglSurf.getSurfaceHandle() ) { + throw new InternalError("Set surface but claimed to be invalid: "+eglSurf); + } + if( !eglSurf.containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS ) ) { + eglSurf.setEGLSurfaceHandle(); } - eglws.setSurfaceHandle( createEGLSurface() ); - } else if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) { - throw new InternalError("Nil surface but claimed to be valid: "+eglws); + } else if( EGL.EGL_NO_SURFACE == eglSurf.getSurfaceHandle() ) { + throw new InternalError("Nil surface but claimed to be valid: "+eglSurf); } } @Override protected void destroyHandle() { - final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + final EGLSurface eglSurf = (EGLSurface) surface; + final long eglSurfHandle = eglSurf.getSurfaceHandle(); if(DEBUG) { - System.err.println(getThreadName() + ": destroyHandle of "+eglws); + System.err.println(getThreadName() + ": destroyHandle of "+eglSurf); } - if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) { - throw new InternalError("Nil surface but claimed to be valid: "+eglws); - } - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglws.getGraphicsConfiguration().getScreen().getDevice(); - if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { - EGL.eglDestroySurface(eglDevice.getHandle(), eglws.getSurfaceHandle()); - eglws.setSurfaceHandle(EGL.EGL_NO_SURFACE); - } - } - - protected static boolean isValidEGLSurface(final long eglDisplayHandle, final long surfaceHandle) { - if( 0 == surfaceHandle ) { - return false; + if( !eglSurf.containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_SURFACELESS ) && + EGL.EGL_NO_SURFACE == eglSurfHandle ) { + throw new InternalError("Nil surface but claimed to be valid: "+eglSurf); } - final IntBuffer val = Buffers.newDirectIntBuffer(1); - final boolean eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surfaceHandle, EGL.EGL_CONFIG_ID, val); - if( !eglSurfaceValid ) { - final int eglErr = EGL.eglGetError(); - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.isValidEGLSurface eglQuerySuface failed: error "+toHexString(eglErr)+", "+toHexString(surfaceHandle)); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglSurf.getGraphicsConfiguration().getScreen().getDevice(); + if( eglSurf.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( EGL.EGL_NO_SURFACE != eglSurfHandle ) { + EGL.eglDestroySurface(eglDevice.getHandle(), eglSurfHandle); + eglSurf.setSurfaceHandle(EGL.EGL_NO_SURFACE); } } - return eglSurfaceValid; } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index 2edb22314..967bcb6da 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -40,7 +40,6 @@ 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; @@ -66,7 +65,6 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import jogamp.common.os.PlatformPropsImpl; -import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableFactoryImpl; @@ -75,13 +73,18 @@ import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.SharedResourceRunner; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; +import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.os.Platform; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.common.util.VersionNumber; +import com.jogamp.nativewindow.GenericUpstreamSurfacelessHook; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; import com.jogamp.opengl.GLRendererQuirks; +import com.jogamp.opengl.egl.EGL; public class EGLDrawableFactory extends GLDrawableFactoryImpl { protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG; // allow package access @@ -93,8 +96,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { QUERY_EGL_ES_NATIVE_TK = PropertyAccess.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); } + private static boolean eglDynamicLookupHelperInit = false; private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null; + private static GLDynamicLookupHelper eglGLnDynamicLookupHelper = null; private static final boolean isANGLE(final GLDynamicLookupHelper dl) { if(Platform.OSType.WINDOWS == PlatformPropsImpl.OS_TYPE) { @@ -112,50 +117,100 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { dl.isFunctionAvailable("glColorPointer"); } - public EGLDrawableFactory() { - super(); - - // Register our GraphicsConfigurationFactory implementations - // The act of constructing them causes them to be registered - EGLGraphicsConfigurationFactory.registerFactory(); + private static class EGLFeatures { + public final String vendor; + public final VersionNumber version; + public final boolean hasGLAPI; + public final boolean hasKHRCreateContext; + public final boolean hasKHRSurfaceless; - // Check for other underlying stuff .. - if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true)) { - hasX11 = true; - try { - ReflectionUtil.createInstance("jogamp.opengl.x11.glx.X11GLXGraphicsConfigurationFactory", EGLDrawableFactory.class.getClassLoader()); - } catch (final Exception jre) { /* n/a .. */ } + public EGLFeatures(final EGLGraphicsDevice device) { + final long eglDisplay = device.getHandle(); + vendor = EGL.eglQueryString(eglDisplay, EGL.EGL_VENDOR); + if(DEBUG) { + System.err.println("EGLFeatures on device "+device+", vendor "+vendor); + } + version = device.getEGLVersion(); + final boolean hasEGL_1_4 = version.compareTo(GLContext.Version1_4) >= 0; + final boolean hasEGL_1_5 = version.compareTo(GLContext.Version1_5) >= 0; + { + final String eglClientAPIStr = EGL.eglQueryString(eglDisplay, EGL.EGL_CLIENT_APIS); + final String[] eglClientAPIs = eglClientAPIStr.split("\\s"); + boolean _hasGLAPI = false; + for(int i=eglClientAPIs.length-1; i>=0; i--) { + _hasGLAPI = eglClientAPIs[i].equals("OpenGL"); + } + hasGLAPI = _hasGLAPI; + if(DEBUG) { + System.err.println(" Client APIs: "+eglClientAPIStr+"; has OpenGL "+hasGLAPI); + } + } + { + final String extensions = EGLContext.getPlatformExtensionsStringImpl(device).toString(); + if( hasEGL_1_5 ) { + // subsumed in EGL 1.5 + hasKHRCreateContext = true; + hasKHRSurfaceless = true; + } else { + if( hasEGL_1_4 ) { + hasKHRCreateContext = extensions.contains("EGL_KHR_create_context"); + } else { + hasKHRCreateContext = false; + } + hasKHRSurfaceless = extensions.contains("EGL_KHR_surfaceless_context"); + } + if(DEBUG) { + System.err.println(" Extensions: "+extensions); + System.err.println(" KHR_create_context: "+hasKHRCreateContext); + System.err.println(" KHR_surfaceless_context: "+hasKHRSurfaceless); + } + } + } + public final String toString() { + return "EGLFeatures[vendor "+vendor+", version "+version+ + ", has[GL-API "+hasGLAPI+", KHR[CreateContext "+hasKHRCreateContext+", Surfaceless "+hasKHRSurfaceless+"]]]"; } + } + + static class EGLAcc extends EGL { + protected static boolean resetProcAddressTable(final DynamicLookupHelper lookup) { + return EGL.resetProcAddressTable(lookup); + } + } + static final String eglInitializeFuncName = "eglInitialize"; - // 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. + public EGLDrawableFactory() { + super(); synchronized(EGLDrawableFactory.class) { - final boolean hasDesktopES2 = null != eglES2DynamicLookupHelper; + if( eglDynamicLookupHelperInit ) { + return; + } + eglDynamicLookupHelperInit = true; - if(!hasDesktopES2 && null==eglES1DynamicLookupHelper) { - GLDynamicLookupHelper tmp=null; + // Check for other underlying stuff .. + if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true)) { + hasX11 = true; try { - tmp = new GLDynamicLookupHelper(new EGLES1DynamicLibraryBundleInfo()); - } catch (final GLException gle) { - if(DEBUG) { - gle.printStackTrace(); - } - } - if(null!=tmp && tmp.isLibComplete()) { - eglES1DynamicLookupHelper = tmp; - EGL.resetProcAddressTable(eglES1DynamicLookupHelper); - final boolean isANGLEES1 = isANGLE(eglES1DynamicLookupHelper); - isANGLE |= isANGLEES1; - if (DEBUG || GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: EGL ES1 - OK, isANGLE: "+isANGLEES1); - } - } else if (DEBUG || GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: EGL ES1 - NOPE (ES1 lib)"); - } + ReflectionUtil.createInstance("jogamp.opengl.x11.glx.X11GLXGraphicsConfigurationFactory", EGLDrawableFactory.class.getClassLoader()); + } catch (final Exception jre) { /* n/a .. */ } } - if(!hasDesktopES2 && null==eglES2DynamicLookupHelper) { + + /** + * 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. + * + * Since EGL is designed to be static + * we validate the function address of 'eglInitialize' + * with all EGL/ES and EGL/GL combinations. + * In case this address doesn't match the primary tuple EGL/ES2 + * the profile is skipped! + */ + boolean eglTableReset = false; + long eglInitializeAddress = 0; + // Setup: eglES2DynamicLookupHelper[, eglES1DynamicLookupHelper] + { GLDynamicLookupHelper tmp=null; try { tmp = new GLDynamicLookupHelper(new EGLES2DynamicLibraryBundleInfo()); @@ -164,9 +219,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { gle.printStackTrace(); } } - if(null!=tmp && tmp.isLibComplete()) { + if( null != tmp && tmp.isLibComplete() && true == ( eglTableReset = EGLAcc.resetProcAddressTable(tmp) ) ) { + eglInitializeAddress = tmp.dynamicLookupFunction(eglInitializeFuncName); eglES2DynamicLookupHelper = tmp; - EGL.resetProcAddressTable(eglES2DynamicLookupHelper); final boolean includesES1 = null == eglES1DynamicLookupHelper && includesES1(eglES2DynamicLookupHelper); if(includesES1) { eglES1DynamicLookupHelper = tmp; @@ -174,7 +229,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { final boolean isANGLEES2 = isANGLE(eglES2DynamicLookupHelper); isANGLE |= isANGLEES2; if (DEBUG || GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: EGL ES2 - OK (includesES1 "+includesES1+", isANGLE: "+isANGLEES2+")"); + System.err.println("Info: EGLDrawableFactory: EGL ES2 - OK (includesES1 "+includesES1+", isANGLE: "+isANGLEES2+", eglInitialize 0x"+Long.toHexString(eglInitializeAddress)+")"); if(includesES1) { System.err.println("Info: EGLDrawableFactory: EGL ES1 - OK (ES2 lib)"); } @@ -183,7 +238,85 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { System.err.println("Info: EGLDrawableFactory: EGL ES2 - NOPE"); } } - if( null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper ) { + // Setup: eglES1DynamicLookupHelper + if( null == eglES1DynamicLookupHelper ) { + GLDynamicLookupHelper tmp=null; + try { + tmp = new GLDynamicLookupHelper(new EGLES1DynamicLibraryBundleInfo()); + } catch (final GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + if( null != tmp && tmp.isLibComplete() ) { + final boolean ok; + final long _eglInitializeAddress; + if( !eglTableReset ) { + if( true == ( eglTableReset = EGLAcc.resetProcAddressTable(tmp) ) ) { + _eglInitializeAddress = tmp.dynamicLookupFunction(eglInitializeFuncName); + eglInitializeAddress = _eglInitializeAddress; + ok = true; + } else { + _eglInitializeAddress = 0; + ok = false; + } + } else { + _eglInitializeAddress = tmp.dynamicLookupFunction(eglInitializeFuncName); + ok = _eglInitializeAddress == eglInitializeAddress; + } + if( ok ) { + eglES1DynamicLookupHelper = tmp; + final boolean isANGLEES1 = isANGLE(eglES1DynamicLookupHelper); + isANGLE |= isANGLEES1; + if (DEBUG || GLProfile.DEBUG) { + System.err.println("Info: EGLDrawableFactory: EGL ES1 - OK (isANGLE: "+isANGLEES1+", eglTableReset "+eglTableReset+", eglInitialize 0x"+Long.toHexString(_eglInitializeAddress)+")"); + } + } else if (DEBUG || GLProfile.DEBUG) { + System.err.println("Info: EGLDrawableFactory: EGL ES1 - NOPE (ES1 proc, eglTableReset "+eglTableReset+", eglInitialize 0x"+Long.toHexString(_eglInitializeAddress)+")"); + } + } else if (DEBUG || GLProfile.DEBUG) { + System.err.println("Info: EGLDrawableFactory: EGL ES1 - NOPE (ES1 lib)"); + } + } + // Setup: eglGLnDynamicLookupHelper + if( null == eglGLnDynamicLookupHelper ) { + GLDynamicLookupHelper tmp=null; + try { + tmp = new GLDynamicLookupHelper(new EGLGLnDynamicLibraryBundleInfo()); + } catch (final GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + if( null != tmp && tmp.isLibComplete() ) { + final boolean ok; + final long _eglInitializeAddress; + if( !eglTableReset ) { + if( true == ( eglTableReset = EGLAcc.resetProcAddressTable(tmp) ) ) { + _eglInitializeAddress = tmp.dynamicLookupFunction(eglInitializeFuncName); + eglInitializeAddress = _eglInitializeAddress; + ok = true; + } else { + _eglInitializeAddress = 0; + ok = false; + } + } else { + _eglInitializeAddress = tmp.dynamicLookupFunction(eglInitializeFuncName); + ok = _eglInitializeAddress == eglInitializeAddress; + } + if( ok ) { + eglGLnDynamicLookupHelper = tmp; + if (DEBUG || GLProfile.DEBUG) { + System.err.println("Info: EGLDrawableFactory: EGL GLn - OK (eglTableReset "+eglTableReset+", eglInitialize 0x"+Long.toHexString(_eglInitializeAddress)+")"); + } + } else if (DEBUG || GLProfile.DEBUG) { + System.err.println("Info: EGLDrawableFactory: EGL GLn - NOPE (GLn proc, eglTableReset "+eglTableReset+", eglInitialize 0x"+Long.toHexString(_eglInitializeAddress)+")"); + } + } else if (DEBUG || GLProfile.DEBUG) { + System.err.println("Info: EGLDrawableFactory: EGL GLn - NOPE (GLn lib)"); + } + } + if( null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper || null != eglGLnDynamicLookupHelper ) { if(isANGLE && !GLProfile.enableANGLE) { if(DEBUG || GLProfile.DEBUG) { System.err.println("Info: EGLDrawableFactory.init - EGL/ES2 ANGLE disabled"); @@ -192,13 +325,22 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { 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>(); + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + EGLGraphicsConfigurationFactory.registerFactory(); + + sharedMap = new HashMap<String, SharedResourceRunner.Resource>(); + // 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); + + // Init shared resources off thread + // Will be released via ShutdownHook + sharedResourceRunner = new SharedResourceRunner(new SharedResourceImplementation()); + sharedResourceRunner.start(); } } - } + } // synchronized(EGLDrawableFactory.class) } @Override @@ -212,26 +354,15 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if( DEBUG ) { System.err.println("EGLDrawableFactory.shutdown"); } + if(null != sharedResourceRunner) { + sharedResourceRunner.stop(); + sharedResourceRunner = null; + } if(null != sharedMap) { - if(DEBUG) { - dumpMap(); - } - final Collection<SharedResource> srl = sharedMap.values(); - for(final Iterator<SharedResource> sri = srl.iterator(); sri.hasNext(); ) { - final SharedResource sr = sri.next(); - if(DEBUG) { - 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; @@ -247,6 +378,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { // eglES2DynamicLookupHelper.destroy(); eglES2DynamicLookupHelper = null; } + if(null != eglGLnDynamicLookupHelper) { + // eglGLDynamicLookupHelper.destroy(); + eglGLnDynamicLookupHelper = null; + } EGLGraphicsConfigurationFactory.unregisterFactory(); EGLDisplayUtil.shutdown(DEBUG); } @@ -258,65 +393,59 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { final Set<String> keys = sharedMap.keySet(); for(final Iterator<String> keyI = keys.iterator(); keyI.hasNext(); i++) { final String key = keyI.next(); - final 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)+"]]"); + final SharedResource sr = (SharedResource) sharedMap.get(key); + System.err.println("EGLDrawableFactory.map["+i+"] "+key+" -> "+sr.getDevice()+", avail "+sr.isAvailable+ + "gln [quirks "+sr.rendererQuirksGLn+", ctp "+EGLContext.getGLVersion(3, 0, sr.ctpGLn, null)+"], "+ + "es1 [quirks "+sr.rendererQuirksES1+", ctp "+EGLContext.getGLVersion(1, 0, sr.ctpES1, null)+"], "+ + "es2/3 [quirks "+sr.rendererQuirksES3ES2+", ctp "+EGLContext.getGLVersion(2, 0, sr.ctpES3ES2, null)+"]"); } ; } } - 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; + private EGLGraphicsDevice defaultDevice = null; + private EGLFeatures defaultDeviceEGLFeatures; + private SharedResourceRunner sharedResourceRunner; + private HashMap<String /* uniqueKey */, SharedResourceRunner.Resource> sharedMap; static class SharedResource implements SharedResourceRunner.Resource { - private final EGLGraphicsDevice device; + private EGLGraphicsDevice device; // 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(final EGLGraphicsDevice dev, - final boolean wasContextES1Created, final boolean hasPBufferES1, final GLRendererQuirks rendererQuirksES1, final int ctpES1, - final boolean wasContextES2Created, final boolean wasContextES3Created, - final boolean hasPBufferES3ES2, final GLRendererQuirks rendererQuirksES3ES2, final int ctpES3ES2) { + final boolean isAvailable; + final GLRendererQuirks rendererQuirksGLn; + final GLRendererQuirks rendererQuirksES1; + final GLRendererQuirks rendererQuirksES3ES2; + final int ctpGLn; + final int ctpES1; + final int ctpES3ES2; + + SharedResource(final EGLGraphicsDevice dev, final boolean isAvailable, + final GLRendererQuirks rendererQuirksGLn, final int ctpGLn, + final GLRendererQuirks rendererQuirksES1, final int ctpES1, + final GLRendererQuirks rendererQuirksES3ES2, final int ctpES3ES2) { this.device = dev; - // this.contextES1 = ctxES1; - this.wasES1ContextCreated = wasContextES1Created; - this.hasPBufferES1= hasPBufferES1; + this.isAvailable = isAvailable; + + this.rendererQuirksGLn = rendererQuirksGLn; + this.ctpGLn = ctpGLn; + 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; } + @Override - public final boolean isValid() { - return wasES1ContextCreated || wasES2ContextCreated || wasES3ContextCreated; + public final boolean isAvailable() { + return isAvailable; } @Override public final EGLGraphicsDevice getDevice() { return device; } - // final EGLContext getContextES1() { return contextES1; } - // final EGLContext getContextES2() { return contextES2; } - // final EGLContext getContextES3() { return contextES3; } @Override public AbstractGraphicsScreen getScreen() { @@ -331,368 +460,424 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return null; } @Override - public GLRendererQuirks getRendererQuirks() { - return null != rendererQuirksES3ES2 ? rendererQuirksES3ES2 : rendererQuirksES1 ; + public GLRendererQuirks getRendererQuirks(final GLProfile glp) { + if( null == glp ) { + if( null != rendererQuirksES3ES2 ) { + return rendererQuirksES3ES2; + } else if( null != rendererQuirksES1 ) { + return rendererQuirksES1; + } else { + return rendererQuirksGLn; + } + } else if( !glp.isGLES() ) { + return rendererQuirksGLn; + } else if( glp.isGLES1() ) { + return rendererQuirksES1; + } else { + return rendererQuirksES3ES2; + } } - } - - @Override - public final AbstractGraphicsDevice getDefaultDevice() { - return defaultDevice; - } + } - @Override - public final boolean getIsDeviceCompatible(final AbstractGraphicsDevice device) { - // via mappings (X11/WGL/.. -> EGL) we shall be able to handle all types. - return null != sharedMap ; // null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper; - } + class SharedResourceImplementation implements SharedResourceRunner.Implementation { + @Override + public void clear() { + sharedMap.clear(); + } + @Override + public SharedResourceRunner.Resource mapPut(final AbstractGraphicsDevice device, final SharedResourceRunner.Resource resource) { + return sharedMap.put(device.getConnection(), resource); + } + @Override + public SharedResourceRunner.Resource mapGet(final AbstractGraphicsDevice device) { + return sharedMap.get(device.getConnection()); + } + @Override + public Collection<SharedResourceRunner.Resource> mapValues() { + return sharedMap.values(); + } - private static List<GLCapabilitiesImmutable> getAvailableEGLConfigs(final EGLGraphicsDevice eglDisplay, final 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())); + @Override + public boolean isDeviceSupported(final AbstractGraphicsDevice device) { + return null != sharedMap; // null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper } - 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 */); + + @Override + public SharedResourceRunner.Resource createSharedResource(final AbstractGraphicsDevice adevice) { + adevice.lock(); + try { + return createEGLSharedResourceImpl(adevice); + } catch (final Throwable t) { + throw new GLException("EGLGLXDrawableFactory - Could not initialize shared resources for "+adevice, t); + } finally { + adevice.unlock(); } } - 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(final AbstractGraphicsDevice adevice, final int[] esProfile, - final boolean[] hasPBuffer, final GLRendererQuirks[] rendererQuirks, final 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[0]); - } - if ( !GLProfile.isAvailable(adevice, profileString) ) { - if( DEBUG ) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" n/a on "+adevice); + private SharedResource createEGLSharedResourceImpl(final AbstractGraphicsDevice adevice) { + final GLRendererQuirks[] rendererQuirksES1 = new GLRendererQuirks[] { null }; + final GLRendererQuirks[] rendererQuirksES3ES2 = new GLRendererQuirks[] { null }; + final GLRendererQuirks[] rendererQuirksGLn = new GLRendererQuirks[] { null }; + final int[] ctpES1 = new int[] { EGLContext.CTX_PROFILE_ES }; + final int[] ctpES3ES2 = new int[] { EGLContext.CTX_PROFILE_ES }; + final int[] ctpGLn = new int[] { EGLContext.CTX_PROFILE_CORE }; + + if (DEBUG) { + System.err.println("EGLDrawableFactory.createShared(): device "+adevice); } - 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[0]+" ), "+ - "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"); + + boolean madeCurrentES1 = false; + boolean madeCurrentES2 = false; + boolean madeCurrentES3 = false; + boolean madeCurrentGLn = false; + + if( null != eglGLnDynamicLookupHelper ) { + // OpenGL 3.1 core -> GL3 + final int[] major = { 3 }; + final int[] minor = { 1 }; // FIXME: No minor version probing for ES currently! + madeCurrentGLn = mapAvailableEGLESConfig(adevice, major, minor, + ctpGLn, rendererQuirksGLn) && 0 != major[0]; + } else { + madeCurrentGLn = false; + } + if( null != eglES1DynamicLookupHelper ) { + final int[] major = { 1 }; + final int[] minor = { 0 }; + madeCurrentES1 = mapAvailableEGLESConfig(adevice, major, minor, + ctpES1, rendererQuirksES1) && 1 == major[0]; + } else { + madeCurrentES1 = false; + } + if( null != eglES2DynamicLookupHelper ) { + // ES3 Query + final int[] major = { 3 }; + final int[] minor = { 0 }; + madeCurrentES3 = mapAvailableEGLESConfig(adevice, major, minor, + ctpES3ES2, rendererQuirksES3ES2) && 3 == major[0]; + if( !madeCurrentES3 ) { + // ES2 Query, may result in ES3 + major[0] = 2; + if( mapAvailableEGLESConfig(adevice, major, minor, + ctpES3ES2, rendererQuirksES3ES2) ) + { + switch( major[0] ) { + case 2: madeCurrentES2 = true; break; + case 3: madeCurrentES3 = true; break; + default: throw new InternalError("XXXX Got "+major[0]); } } } + } + + if( !EGLContext.getAvailableGLVersionsSet(adevice) ) { + // Even though we override the non EGL native mapping intentionally, + // avoid exception due to double 'set' - careful exception of the rule. + EGLContext.setAvailableGLVersionsSet(adevice, true); + } + if( hasX11 ) { + handleDontCloseX11DisplayQuirk(rendererQuirksES1[0]); + handleDontCloseX11DisplayQuirk(rendererQuirksES3ES2[0]); + } + final SharedResource sr = new SharedResource(defaultDevice, + madeCurrentGLn || madeCurrentES1 || madeCurrentES2 || madeCurrentES3, + rendererQuirksGLn[0], ctpGLn[0], + rendererQuirksES1[0], ctpES1[0], + rendererQuirksES3ES2[0], ctpES3ES2[0]); + + 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 GLn: " + madeCurrentGLn + ", quirks "+rendererQuirksGLn[0]); + System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1 + ", quirks "+rendererQuirksES1[0]); + System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2 + ", quirks "+rendererQuirksES3ES2[0]); + System.err.println("EGLDrawableFactory.createShared: context ES3: " + madeCurrentES3 + ", quirks "+rendererQuirksES3ES2[0]); + dumpMap(); + } + return sr; + } + + private void handleDontCloseX11DisplayQuirk(final GLRendererQuirks quirks) { + if( null != quirks && quirks.exist( GLRendererQuirks.DontCloseX11Display ) ) { + jogamp.nativewindow.x11.X11Util.markAllDisplaysUnclosable(); + } + } + + private boolean mapAvailableEGLESConfig(final AbstractGraphicsDevice adevice, + final int[] majorVersion, final int[] minorVersion, + final int[] ctxProfile, final GLRendererQuirks[] rendererQuirks) { + final String profileString = EGLContext.getGLProfile(majorVersion[0], minorVersion[0], ctxProfile[0]); + + if ( !GLProfile.isAvailable(adevice, profileString) ) { if( DEBUG ) { - dumpEGLInfo("EGLDrawableFactory.mapAvailableEGLESConfig: ", defaultDevice.getHandle()); + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" n/a on "+adevice); } + 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; + // FIXME || adevice instanceof EGLGraphicsDevice ; + if( DEBUG ) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" ( "+majorVersion[0]+" ), "+ + "mapsADeviceToDefaultDevice "+mapsADeviceToDefaultDevice+ + " (QUERY_EGL_ES_NATIVE_TK "+QUERY_EGL_ES_NATIVE_TK+", initDefaultDevice "+initDefaultDevice+", hasDesktopFactory "+(null != desktopFactory)+ + ", isEGLGraphicsDevice "+(adevice instanceof EGLGraphicsDevice)+")"); + } - 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; + boolean hasPBuffer; + EGLGraphicsDevice eglDevice = null; + EGLFeatures eglFeatures = null; + NativeSurface surface = null; + ProxySurface upstreamSurface = null; // X11, GLX, .. + ProxySurface downstreamSurface = null; // EGL + boolean allowsSurfacelessCtx = false; + 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(); + defaultDeviceEGLFeatures = new EGLFeatures(defaultDevice); + + // Probe for GLRendererQuirks.SingletonEGLDisplayOnly + final long secondEGLDisplay = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); + if ( EGL.EGL_NO_DISPLAY == secondEGLDisplay ) { + final int quirk = GLRendererQuirks.SingletonEGLDisplayOnly; + GLRendererQuirks.addStickyDeviceQuirk(adevice, quirk); + EGLDisplayUtil.setSingletonEGLDisplayOnly(true); + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Second eglGetDisplay(EGL_DEFAULT_DISPLAY) failed"); } - rendererQuirks[0] = defaultSharedResource.rendererQuirksES1; - ctp[0] = defaultSharedResource.ctpES1; - break; + } } - if( null != rendererQuirks[0] ) { - GLRendererQuirks.addStickyDeviceQuirks(adevice, rendererQuirks[0]); + eglDevice = defaultDevice; // reuse + eglFeatures = defaultDeviceEGLFeatures; + if( DEBUG ) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig.0: "+eglFeatures); } - 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; + if( !glp.isGLES() && !eglFeatures.hasGLAPI ) { + if(DEBUG) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig() OpenGL API not supported (1)"); + } + } else { + final GLCapabilitiesImmutable reqCapsPBuffer = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(reqCapsAny); + final List<GLCapabilitiesImmutable> availablePBufferCapsL = getAvailableEGLConfigs(eglDevice, reqCapsPBuffer); + hasPBuffer = availablePBufferCapsL.size() > 0; + + // attempt to created the default shared resources .. + if( hasPBuffer ) { + // 2nd case create defaultDevice shared resource using pbuffer surface + downstreamSurface = createDummySurfaceImpl(eglDevice, 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(eglDevice, reqCapsAny); + if(capsAnyL.size() > 0) { + final GLCapabilitiesImmutable chosenCaps = capsAnyL.get(0); + EGLContext.mapStaticGLESVersion(eglDevice, chosenCaps); + success = true; + } + if(DEBUG) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig() no pbuffer config available, detected !pbuffer config: "+success); + EGLGraphicsConfigurationFactory.printCaps("!PBufferCaps", capsAnyL, System.err); + } + } } } 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(); - eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface); - eglDevice.open(); - if( DEBUG ) { - dumpEGLInfo("EGLDrawableFactory.mapAvailableEGLESConfig: ", eglDevice.getHandle()); + // 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(); + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface); + eglDevice.open(); + eglFeatures = new EGLFeatures(eglDevice); + if( DEBUG ) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig.1: "+eglFeatures); + } + if( !glp.isGLES() && !eglFeatures.hasGLAPI ) { + if(DEBUG) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig() OpenGL API not supported (2)"); + } + // disposed at finalized: eglDevice, upstreamSurface + } else { + hasPBuffer = true; + surface = upstreamSurface; + } } - hasPBuffer[0] = true; - surface = upstreamSurface; } - } - 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!"); + if(null != surface) { + GLDrawableImpl zeroDrawable = null; + final EGLDrawable drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface ); + drawable.setRealized(true); + final EGLContext context = (EGLContext) drawable.createContext(null); + if (null != context) { + try { + if( GLContext.CONTEXT_NOT_CURRENT != context.makeCurrent() ) { // could cause exception + // context.isCurrent() ! + final String glVersionString = context.getGL().glGetString(GL.GL_VERSION); + if(null != glVersionString) { + context.mapCurrentAvailableGLVersion(eglDevice); + if(eglDevice != adevice) { + context.mapCurrentAvailableGLVersion(adevice); + } + + if( eglFeatures.hasKHRSurfaceless && + !context.hasRendererQuirk(GLRendererQuirks.NoSurfacelessCtx) ) + { + try { + final ProxySurface zeroSurface = createSurfacelessImpl(eglDevice, true, reqCapsAny, reqCapsAny, null, 64, 64); + zeroDrawable = createOnscreenDrawableImpl(zeroSurface); + zeroDrawable.setRealized(true); + + // Since sharedContext is still current, + // will keep sharedContext current w/ zeroDrawable or throws GLException + context.setGLDrawable(zeroDrawable, false); + allowsSurfacelessCtx = true; // if setGLDrawable is successful, i.e. no GLException + + // no switch back, will be destroyed anyways + // context.setGLDrawable(drawable, false); + } catch (final Throwable t) { + if( DEBUG ) { + ExceptionUtils.dumpThrowable("", t); + } + } + } + if( !allowsSurfacelessCtx ) { + final int quirk = GLRendererQuirks.NoSurfacelessCtx; + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+" -> "+eglDevice+": cause: probe"); + } + final GLRendererQuirks glrq = context.getRendererQuirks(); + if( null != glrq ) { + glrq.addQuirk(quirk); + } + GLRendererQuirks.addStickyDeviceQuirk(eglDevice, quirk); + } + rendererQuirks[0] = context.getRendererQuirks(); + ctxProfile[0] = context.getContextOptions(); + majorVersion[0] = context.getGLVersionNumber().getMajor(); + minorVersion[0] = context.getGLVersionNumber().getMinor(); + success = true; + } else { + // Oops .. something is wrong + if(DEBUG) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!"); + } } } + } catch (final Throwable t) { + if (DEBUG) { + System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: INFO: context create/makeCurrent failed"); + t.printStackTrace(); + } + } finally { + if( context.isCreated() ) { + context.destroy(); + } } - } catch (final Throwable t) { - if (DEBUG) { - System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: INFO: context create/makeCurrent failed"); - t.printStackTrace(); - } - } finally { - context.destroy(); } + if( null != zeroDrawable ) { + zeroDrawable.setRealized(false); + } + drawable.setRealized(false); } - drawable.setRealized(false); - } - } catch (final Throwable t) { - if(DEBUG) { - System.err.println("Caught 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(); + } catch (final Throwable t) { + if(DEBUG) { + System.err.println("Caught exception on thread "+getThreadName()); + t.printStackTrace(); } - if(null != upstreamSurface) { - upstreamSurface.destroyNotify(); + success = false; + } finally { + if(null != downstreamSurface) { + downstreamSurface.destroyNotify(); } - } - } - return success; - } - - private final boolean needsToCreateSharedResource(final String key, final SharedResource[] existing) { - synchronized(sharedMap) { - final SharedResource sr = sharedMap.get(key); - if( null == sr ) { - final boolean createAttempted = sharedMapCreateAttempt.contains(key); - if(!createAttempted) { - sharedMapCreateAttempt.add(key); + if( defaultDevice != eglDevice ) { // don't close default device + if(null != eglDevice) { + eglDevice.close(); + } } - return !createAttempted; - } else { - if(null != existing) { - existing[0] = sr; + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); } - return false; } + return success; } - } - @Override - protected final SharedResource getOrCreateSharedResourceImpl(final AbstractGraphicsDevice adevice) { - if(null == sharedMap) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper - return null; - } - - if( needsToCreateSharedResource(defaultDevice.getUniqueID(), null) ) { + @Override + public void releaseSharedResource(final SharedResourceRunner.Resource shared) { + final SharedResource sr = (SharedResource) shared; if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: (defaultDevice): req. device: "+adevice+", defaultDevice "+defaultDevice); - Thread.dumpStack(); - } - if(null != defaultSharedResource) { - dumpMap(); - throw new InternalError("defaultSharedResource already exist: "+defaultSharedResource); + System.err.println("Shutdown Shared:"); + System.err.println("Device : " + sr.device); + ExceptionUtils.dumpStack(System.err); } - 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]; + if (null != sr.device) { + // may cause JVM SIGSEGV: + sr.device.close(); + sr.device = null; } - return createEGLSharedResourceImpl(adevice); } } - private SharedResource createEGLSharedResourceImpl(final AbstractGraphicsDevice adevice) { - final boolean madeCurrentES1; - final boolean[] hasPBufferES1 = new boolean[] { false }; - final boolean[] hasPBufferES3ES2 = new boolean[] { false }; - // EGLContext[] eglCtxES1 = new EGLContext[] { null }; - // EGLContext[] eglCtxES2 = new EGLContext[] { null }; - final GLRendererQuirks[] rendererQuirksES1 = new GLRendererQuirks[] { null }; - final GLRendererQuirks[] rendererQuirksES3ES2 = new GLRendererQuirks[] { null }; - final int[] ctpES1 = new int[] { -1 }; - final int[] ctpES3ES2 = new int[] { -1 }; + public final boolean hasDefaultDeviceKHRCreateContext() { + return defaultDeviceEGLFeatures.hasKHRCreateContext; + } + @Override + public final AbstractGraphicsDevice getDefaultDevice() { + return defaultDevice; + } - if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared(): device "+adevice); - } + @Override + public final boolean getIsDeviceCompatible(final AbstractGraphicsDevice device) { + // via mappings (X11/WGL/.. -> EGL) we shall be able to handle all types. + return null != sharedMap ; // null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper; + } - 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); + private static List<GLCapabilitiesImmutable> getAvailableEGLConfigs(final EGLGraphicsDevice eglDisplay, final 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( hasX11 ) { - handleDontCloseX11DisplayQuirk(rendererQuirksES1[0]); - handleDontCloseX11DisplayQuirk(rendererQuirksES3ES2[0]); + 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 */); + } } - final SharedResource sr = new SharedResource(defaultDevice, madeCurrentES1, hasPBufferES1[0], rendererQuirksES1[0], ctpES1[0], - madeCurrentES2, madeCurrentES3, hasPBufferES3ES2[0], rendererQuirksES3ES2[0], ctpES3ES2[0]); + return new ArrayList<GLCapabilitiesImmutable>(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; + 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 eglClientVersion = EGL.eglQueryString(EGL.EGL_NO_DISPLAY, EGL.EGL_VERSION); + final String eglServerVersion = EGL.eglQueryString(eglDisplay, EGL.EGL_VERSION); + System.err.println(prefix+"EGL vendor "+eglVendor+", version [client "+eglClientVersion+", server "+eglServerVersion+"], clientAPIs "+eglClientAPIs); } - private void handleDontCloseX11DisplayQuirk(final GLRendererQuirks quirks) { - if( null != quirks && quirks.exist( GLRendererQuirks.DontCloseX11Display ) ) { - jogamp.nativewindow.x11.X11Util.markAllDisplaysUnclosable(); - } + @Override + protected final SharedResource getOrCreateSharedResourceImpl(final AbstractGraphicsDevice adevice) { + return (SharedResource) sharedResourceRunner.getOrCreateShared(adevice); } @Override protected final Thread getSharedResourceThread() { - return null; + return sharedResourceRunner.start(); } public final boolean isANGLE() { @@ -706,7 +891,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } else if (1==esProfile) { return eglES1DynamicLookupHelper; } else { - throw new GLException("Unsupported: ES"+esProfile); + return eglGLnDynamicLookupHelper; } } @@ -723,7 +908,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - return new EGLOnscreenDrawable(this, EGLWrappedSurface.get(target)); + return new EGLDrawable(this, EGLSurface.get(target)); } @Override @@ -737,7 +922,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { throw new GLException("Non pbuffer not yet implemented"); } // PBuffer GLDrawable Creation - return new EGLPbufferDrawable(this, EGLWrappedSurface.get(target)); + return new EGLDrawable(this, EGLSurface.get(target)); } @Override @@ -747,28 +932,35 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return true; } - @Override - protected ProxySurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, - final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested, - final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstreamHook) { - final boolean ownDevice; + private final EGLGraphicsConfiguration evalConfig(final boolean[] ownDevice, final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested, + final GLCapabilitiesChooser chooser) { final EGLGraphicsDevice device; if( createNewDevice || ! (deviceReq instanceof EGLGraphicsDevice) ) { final long nativeDisplayID = ( deviceReq instanceof EGLGraphicsDevice) ? ( (EGLGraphicsDevice) deviceReq ).getNativeDisplayID() : deviceReq.getHandle() ; device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(nativeDisplayID, deviceReq.getConnection(), deviceReq.getUnitID()); device.open(); - ownDevice = true; + ownDevice[0] = true; } else { device = (EGLGraphicsDevice) deviceReq; - ownDevice = false; + ownDevice[0] = false; } final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } - return new WrappedSurface(config, 0, upstreamHook, ownDevice); + return config; + } + + @Override + protected final ProxySurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested, + final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstreamHook) { + final boolean[] ownDevice = { false }; + final EGLGraphicsConfiguration config = evalConfig(ownDevice, deviceReq, createNewDevice, capsChosen, capsRequested, chooser); + return EGLSurface.createWrapped(config, 0, upstreamHook, ownDevice[0]); } @Override @@ -778,6 +970,15 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new EGLDummyUpstreamSurfaceHook(width, height)); } + @Override + public final ProxySurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) { + chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps); + final boolean[] ownDevice = { false }; + final EGLGraphicsConfiguration config = evalConfig(ownDevice, deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser); + return EGLSurface.createSurfaceless(config, new GenericUpstreamSurfacelessHook(width, height), ownDevice[0]); + } + /** * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface. * It will also hold the resulting pbuffer surface handle. @@ -813,13 +1014,15 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) { + protected ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, + final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, + final UpstreamSurfaceHook upstream) { final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); device.open(); final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); - return new WrappedSurface(cfg, windowHandle, upstream, true); + return EGLSurface.createWrapped(cfg, windowHandle, upstream, true); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java index f00d7059d..0757bd98e 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java @@ -6,6 +6,7 @@ import javax.media.nativewindow.UpstreamSurfaceHook; import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.egl.EGL; /** Uses a PBuffer offscreen surface */ public class EGLDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java index 05dae0b9d..1b433cc30 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java @@ -28,13 +28,15 @@ package jogamp.opengl.egl; -import com.jogamp.common.os.AndroidVersion; -import com.jogamp.common.os.Platform; - -import java.util.*; +import java.util.ArrayList; +import java.util.List; import jogamp.common.os.PlatformPropsImpl; -import jogamp.opengl.*; +import jogamp.opengl.GLDynamicLibraryBundleInfo; + +import com.jogamp.common.os.AndroidVersion; +import com.jogamp.common.os.Platform; +import com.jogamp.opengl.egl.EGL; /** * Abstract implementation of the DynamicLookupHelper for EGL, @@ -43,7 +45,7 @@ import jogamp.opengl.*; * Currently two implementations exist, one for ES1 and one for ES3 and ES2. */ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo { - static final List<String> glueLibNames; + private static final List<String> glueLibNames; static { glueLibNames = new ArrayList<String>(); glueLibNames.add("jogl_mobile"); @@ -79,7 +81,7 @@ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundle @Override public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) { - return EGL.eglGetProcAddress(toolGetProcAddressHandle, funcName); + return EGLContext.eglGetProcAddress(toolGetProcAddressHandle, funcName); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java index 361ec26ff..3c7ee410a 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLES1DynamicLibraryBundleInfo.java @@ -28,7 +28,8 @@ package jogamp.opengl.egl; -import java.util.*; +import java.util.ArrayList; +import java.util.List; public final class EGLES1DynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo { protected EGLES1DynamicLibraryBundleInfo() { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java index 74738463f..d37efc455 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLES2DynamicLibraryBundleInfo.java @@ -28,7 +28,8 @@ package jogamp.opengl.egl; -import java.util.*; +import java.util.ArrayList; +import java.util.List; /** * <p> diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java index a8dd7d5c8..258765ba3 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java @@ -34,6 +34,8 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.egl.EGL; +import com.jogamp.opengl.egl.EGLExt; public class EGLGLCapabilities extends GLCapabilities { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGLnDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLGLnDynamicLibraryBundleInfo.java new file mode 100644 index 000000000..6a3a20100 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGLnDynamicLibraryBundleInfo.java @@ -0,0 +1,83 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.opengl.egl; + +import java.util.ArrayList; +import java.util.List; + +import com.jogamp.common.os.Platform; + +/** + * <p> + * Covering Desktop GL + * </p> + */ +public final class EGLGLnDynamicLibraryBundleInfo extends EGLDynamicLibraryBundleInfo { + private static final List<String> glueLibNames; + static { + glueLibNames = new ArrayList<String>(); + glueLibNames.add("jogl_desktop"); + } + + protected EGLGLnDynamicLibraryBundleInfo() { + super(); + } + + @Override + public final List<List<String>> getToolLibNames() { + final List<List<String>> libsList = new ArrayList<List<String>>(); + { + final List<String> libsGL = new ArrayList<String>(); + + final Platform.OSType osType = Platform.getOSType(); + if( Platform.OSType.MACOS == osType ) { + libsGL.add("/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"); + libsGL.add("GL"); + } else if( Platform.OSType.WINDOWS == Platform.getOSType() ) { + libsGL.add("OpenGL32"); + } else { + // this is the default lib name, according to the spec + libsGL.add("libGL.so.1"); + + // try this one as well, if spec fails + libsGL.add("libGL.so"); + + // last but not least .. the generic one + libsGL.add("GL"); + } + + libsList.add(libsGL); + } + libsList.add(getEGLLibNamesList()); + + return libsList; + } + +} + diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 1d90e63af..6f0d7ae4d 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -57,6 +57,8 @@ import com.jogamp.common.nio.PointerBuffer; import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; import com.jogamp.opengl.GLRendererQuirks; +import com.jogamp.opengl.egl.EGL; +import com.jogamp.opengl.egl.EGLExt; public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java index d4e5e7d62..4aa34ce4e 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java @@ -33,36 +33,37 @@ package jogamp.opengl.egl; +import java.io.PrintStream; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.NativeWindowFactory; 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.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import javax.media.opengl.GLDrawableFactory; + +import jogamp.opengl.GLGraphicsConfigurationFactory; +import jogamp.opengl.GLGraphicsConfigurationUtil; 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; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.io.PrintStream; -import java.nio.IntBuffer; +import com.jogamp.opengl.egl.EGL; /** Subclass of GraphicsConfigurationFactory used when non-AWT tookits diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java deleted file mode 100644 index 4c018fe25..000000000 --- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - * - * Sun gratefully acknowledges that this software was originally authored - * and developed by Kenneth Bradley Russell and Christopher John Kline. - */ - -package jogamp.opengl.egl; - -import javax.media.opengl.*; -import javax.media.nativewindow.*; - -public class EGLOnscreenDrawable extends EGLDrawable { - protected EGLOnscreenDrawable(final EGLDrawableFactory factory, final NativeSurface component) throws GLException { - super(factory, component); - } - - @Override - public GLContext createContext(final GLContext shareWith) { - return new EGLContext(this, shareWith); - } - - @Override - protected long createSurface(final EGLGraphicsConfiguration config, final int width, final int height, final long nativeSurfaceHandle) { - return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), config.getNativeConfig(), nativeSurfaceHandle, null); - } -} - diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java deleted file mode 100644 index 8842edbc0..000000000 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - * - * Sun gratefully acknowledges that this software was originally authored - * and developed by Kenneth Bradley Russell and Christopher John Kline. - */ - -package jogamp.opengl.egl; - -import javax.media.nativewindow.NativeSurface; -import javax.media.opengl.GLContext; - -public class EGLPbufferDrawable extends EGLDrawable { - protected static final boolean useTexture = false; // No yet .. - - protected EGLPbufferDrawable(final EGLDrawableFactory factory, final NativeSurface target) { - super(factory, target); - } - - @Override - protected long createSurface(final EGLGraphicsConfiguration config, final int width, final int height, final long nativeSurfaceHandle) { - return EGLDrawableFactory.createPBufferSurfaceImpl(config, width, height, false); - } - - @Override - public GLContext createContext(final GLContext shareWith) { - return new EGLContext(this, shareWith); - } -} - diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLSurface.java new file mode 100644 index 000000000..796a9e2c8 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLSurface.java @@ -0,0 +1,165 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.opengl.egl; + +import java.nio.IntBuffer; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLException; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.nativewindow.GenericUpstreamSurfacelessHook; +import com.jogamp.opengl.egl.EGL; + +import jogamp.nativewindow.ProxySurfaceImpl; +import jogamp.nativewindow.WrappedSurface; +import jogamp.opengl.GLDrawableImpl; + +/** + * <pre> + * EGLSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a + * EGLUpstreamSurfaceHook [ is_a -> UpstreamSurfaceHook.MutableSize -> UpstreamSurfaceHook ] has_a + * NativeSurface (e.g. native [X11, WGL, ..] surface, or WrappedSurface, ..) + * </pre> + */ +public class EGLSurface extends WrappedSurface { + static boolean DEBUG = EGLDrawable.DEBUG || ProxySurface.DEBUG; + + public static EGLSurface get(final NativeSurface surface) { + if(surface instanceof EGLSurface) { + return (EGLSurface)surface; + } + return new EGLSurface(surface); + } + private EGLSurface(final NativeSurface surface) { + super(surface.getGraphicsConfiguration(), EGL.EGL_NO_SURFACE, new EGLUpstreamSurfaceHook(surface), false /* tbd in UpstreamSurfaceHook */); + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLSurface.ctor().1: "+this); + ProxySurfaceImpl.dumpHierarchy(System.err, this); + } + } + + public static EGLSurface createWrapped(final EGLGraphicsConfiguration cfg, final long handle, + final UpstreamSurfaceHook upstream, final boolean ownsDevice) { + return new EGLSurface(cfg, handle, upstream, ownsDevice); + } + private EGLSurface(final EGLGraphicsConfiguration cfg, final long handle, + final UpstreamSurfaceHook upstream, final boolean ownsDevice) { + super(cfg, EGL.EGL_NO_SURFACE, new EGLUpstreamSurfaceHook(cfg, handle, upstream, ownsDevice), false /* tbd in UpstreamSurfaceHook */); + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLSurface.ctor().2: "+this); + ProxySurfaceImpl.dumpHierarchy(System.err, this); + } + } + + public static EGLSurface createSurfaceless(final EGLGraphicsConfiguration cfg, final GenericUpstreamSurfacelessHook upstream, final boolean ownsDevice) { + return new EGLSurface(cfg, upstream, ownsDevice); + } + private EGLSurface(final EGLGraphicsConfiguration cfg, final GenericUpstreamSurfacelessHook upstream, final boolean ownsDevice) { + super(cfg, EGL.EGL_NO_SURFACE, upstream, ownsDevice); + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLSurface.ctor().3: "+this); + ProxySurfaceImpl.dumpHierarchy(System.err, this); + } + } + + public void setEGLSurfaceHandle() throws GLException { + setSurfaceHandle( createEGLSurfaceHandle() ); + } + private long createEGLSurfaceHandle() throws GLException { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) getGraphicsConfiguration(); + final NativeSurface nativeSurface = getUpstreamSurface(); + final boolean isPBuffer = ((GLCapabilitiesImmutable) config.getChosenCapabilities()).isPBuffer(); + + long eglSurface = createEGLSurfaceHandle(isPBuffer, true /* useSurfaceHandle */, config, nativeSurface); + if ( EGL.EGL_NO_SURFACE == eglSurface ) { + final int eglError0 = EGL.eglGetError(); + if( EGL.EGL_BAD_NATIVE_WINDOW == eglError0 && !isPBuffer ) { + // Try window handle if available and differs (Windows HDC / HWND). + // ANGLE impl. required HWND on Windows. + if( hasUniqueNativeWindowHandle(nativeSurface) ) { + if(DEBUG) { + System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+config+", error "+GLDrawableImpl.toHexString(eglError0)+", retry w/ windowHandle"); + } + eglSurface = createEGLSurfaceHandle(isPBuffer, false /* useSurfaceHandle */, config, nativeSurface); + if (EGL.EGL_NO_SURFACE == eglSurface) { + throw new GLException("Creation of window surface w/ window handle failed: "+config+", "+this+", error "+GLDrawableImpl.toHexString(EGL.eglGetError())); + } + } else { + throw new GLException("Creation of window surface w/ surface handle failed (2): "+config+", "+this+", error "+GLDrawableImpl.toHexString(eglError0)); + } + } else { + throw new GLException("Creation of window surface w/ surface handle failed (1): "+config+", "+this+", error "+GLDrawableImpl.toHexString(eglError0)); + } + } + if(DEBUG) { + System.err.println(getThreadName() + ": createEGLSurface handle "+GLDrawableImpl.toHexString(eglSurface)); + } + return eglSurface; + } + private long createEGLSurfaceHandle(final boolean isPBuffer, final boolean useSurfaceHandle, + final EGLGraphicsConfiguration config, final NativeSurface nativeSurface) { + if( isPBuffer ) { + return EGLDrawableFactory.createPBufferSurfaceImpl(config, getSurfaceWidth(), getSurfaceHeight(), false); + } else { + if( useSurfaceHandle ) { + return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), + config.getNativeConfig(), + nativeSurface.getSurfaceHandle(), null); + } else { + return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), + config.getNativeConfig(), + ((NativeWindow)nativeSurface).getWindowHandle(), null); + } + } + } + private static boolean hasUniqueNativeWindowHandle(final NativeSurface nativeSurface) { + return nativeSurface instanceof NativeWindow && + ((NativeWindow)nativeSurface).getWindowHandle() != nativeSurface.getSurfaceHandle(); + } + static String getThreadName() { return Thread.currentThread().getName(); } + + public static boolean isValidEGLSurfaceHandle(final long eglDisplayHandle, final long eglSurfaceHandle) { + if( 0 == eglSurfaceHandle ) { + return false; + } + final IntBuffer val = Buffers.newDirectIntBuffer(1); + final boolean eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, eglSurfaceHandle, EGL.EGL_CONFIG_ID, val); + if( !eglSurfaceValid ) { + final int eglErr = EGL.eglGetError(); + if(DEBUG) { + System.err.println(getThreadName() + ": EGLSurface.isValidEGLSurfaceHandle eglQuerySuface failed: error "+GLDrawableImpl.toHexString(eglErr)+", "+GLDrawableImpl.toHexString(eglSurfaceHandle)); + } + } + return eglSurfaceValid; + } +} diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java index cc15f0cd6..92e13dc61 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java @@ -1,3 +1,30 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ package jogamp.opengl.egl; import javax.media.nativewindow.AbstractGraphicsConfiguration; @@ -11,13 +38,16 @@ import javax.media.nativewindow.VisualIDHolder.VIDType; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLException; +import jogamp.nativewindow.WrappedSurface; + import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.egl.EGL; /** * <pre> - * EGLWrappedSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a + * EGLSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a * EGLUpstreamSurfaceHook [ is_a -> UpstreamSurfaceHook.MutableSize -> UpstreamSurfaceHook ] has_a - * NativeSurface (e.g. native X11 surface) + * NativeSurface (e.g. native [X11, WGL, ..] surface, or WrappedSurface, ..) * </pre> */ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize { @@ -40,6 +70,11 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize { } } + public EGLUpstreamSurfaceHook(final EGLGraphicsConfiguration cfg, final long handle, + final UpstreamSurfaceHook upstream, final boolean ownsDevice) { + this( new WrappedSurface(cfg, handle, upstream, ownsDevice) ); + } + static String getThreadName() { return Thread.currentThread().getName(); } /** @@ -176,10 +211,10 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize { } surface.setGraphicsConfiguration(eglConfig); - if(isEGLSurfaceValid) { - isEGLSurfaceValid = EGLDrawable.isValidEGLSurface(eglDevice.getHandle(), upstreamSurface.getSurfaceHandle()); + if( isEGLSurfaceValid ) { + isEGLSurfaceValid = EGLSurface.isValidEGLSurfaceHandle(eglDevice.getHandle(), upstreamSurface.getSurfaceHandle()); } - if(isEGLSurfaceValid) { + if( isEGLSurfaceValid ) { surface.setSurfaceHandle(upstreamSurface.getSurfaceHandle()); surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); if(DEBUG) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java deleted file mode 100644 index 89024eed3..000000000 --- a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java +++ /dev/null @@ -1,30 +0,0 @@ -package jogamp.opengl.egl; - -import javax.media.nativewindow.NativeSurface; - -import jogamp.nativewindow.WrappedSurface; - -/** - * <pre> - * EGLWrappedSurface [ is_a -> WrappedSurface -> ProxySurfaceImpl -> ProxySurface -> MutableSurface -> NativeSurface] has_a - * EGLUpstreamSurfaceHook [ is_a -> UpstreamSurfaceHook.MutableSize -> UpstreamSurfaceHook ] has_a - * NativeSurface (i.e. native X11 surface) - * </pre> - */ -public class EGLWrappedSurface extends WrappedSurface { - - public static EGLWrappedSurface get(final NativeSurface surface) { - if(surface instanceof EGLWrappedSurface) { - return (EGLWrappedSurface)surface; - } - return new EGLWrappedSurface(surface); - } - - public EGLWrappedSurface(final NativeSurface surface) { - super(surface.getGraphicsConfiguration(), EGL.EGL_NO_SURFACE, new EGLUpstreamSurfaceHook(surface), false /* tbd in UpstreamSurfaceHook */); - if(EGLDrawableFactory.DEBUG) { - System.err.println("EGLWrappedSurface.ctor(): "+this); - } - } - -} diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java index 51d8ca6fe..d5a4d9a09 100644 --- a/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java +++ b/src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java @@ -257,7 +257,7 @@ public class Mipmap { public static void closestFit( final GL gl, final int target, final int width, final int height, final int internalFormat, final int format, final int type, final int[] newWidth, final int[] newHeight ) { // Use proxy textures if OpenGL GL2/GL3 version >= 1.1 - if( gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version110) >= 0 ) { + if( gl.isGL2GL3() && gl.getContext().getGLVersionNumber().compareTo(GLContext.Version1_1) >= 0 ) { int widthPowerOf2 = nearestPower( width ); int heightPowerOf2 = nearestPower( height ); final int[] proxyWidth = new int[1]; diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index 045abca4c..6cc696d16 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -74,6 +74,7 @@ import jogamp.opengl.SharedResourceRunner; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.nativewindow.GenericUpstreamSurfacelessHook; import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.opengl.GLExtensions; @@ -175,7 +176,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { this.hasAppleFloatPixels = hasAppletFloatPixels; } @Override - public final boolean isValid() { + public final boolean isAvailable() { return valid; } @Override @@ -197,7 +198,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { return null; } @Override - public GLRendererQuirks getRendererQuirks() { + public GLRendererQuirks getRendererQuirks(final GLProfile glp) { return glRendererQuirks; } } @@ -263,8 +264,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } try { - sharedContext.makeCurrent(); // could cause exception - isValid = sharedContext.isCurrent(); + isValid = GLContext.CONTEXT_NOT_CURRENT != sharedContext.makeCurrent(); // could cause exception if(isValid) { final GL gl = sharedContext.getGL(); hasNPOTTextures = gl.isNPOTTextureAvailable(); @@ -373,6 +373,13 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { } @Override + public final ProxySurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) { + chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new GenericUpstreamSurfacelessHook(width, height)); + } + + @Override protected ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) { final MacOSXGraphicsDevice device = new MacOSXGraphicsDevice(deviceReq.getUnitID()); final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java index 3ec40ffce..5cf4f36a1 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java @@ -28,8 +28,10 @@ package jogamp.opengl.macosx.cgl; -import jogamp.opengl.*; -import java.util.*; +import java.util.ArrayList; +import java.util.List; + +import jogamp.opengl.DesktopGLDynamicLibraryBundleInfo; public final class MacOSXCGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo { protected MacOSXCGLDynamicLibraryBundleInfo() { diff --git a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java index 003b9148e..562d4883d 100644 --- a/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java +++ b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java @@ -33,6 +33,7 @@ import java.util.Arrays; import jogamp.opengl.Debug; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.util.LFRingbuffer; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.Ringbuffer; @@ -262,7 +263,7 @@ public class ALAudioSink implements AudioSink { if( ALCConstants.ALC_NO_ERROR != alcErr ) { final String err = getThreadName()+": ALCError "+toHexString(alcErr)+" while makeCurrent. "+this; System.err.println(err); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); lock.unlock(); throw new RuntimeException(err); } @@ -270,7 +271,7 @@ public class ALAudioSink implements AudioSink { if( ALCConstants.ALC_NO_ERROR != alErr ) { if( DEBUG ) { System.err.println(getThreadName()+": Prev - ALError "+toHexString(alErr)+" @ makeCurrent. "+this); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } } } @@ -290,8 +291,7 @@ public class ALAudioSink implements AudioSink { alc.alcDestroyContext(context); } catch (final Throwable t) { if( DEBUG ) { - System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage()); - t.printStackTrace(); + ExceptionUtils.dumpThrowable("", t); } } context = null; @@ -652,7 +652,7 @@ public class ALAudioSink implements AudioSink { alBufferBytesQueued = 0; if(DEBUG_TRACE) { System.err.println("<< _FLUSH_ [al "+val[0]+", err "+toHexString(alErr)+"] <- "+shortString()+" @ "+getThreadName()); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } } diff --git a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java index f9df9153f..8e60b9cc7 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java @@ -33,13 +33,13 @@ import java.nio.IntBuffer; import javax.media.opengl.GL; import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.egl.EGL; +import com.jogamp.opengl.egl.EGLExt; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureSequence; -import jogamp.opengl.egl.EGL; import jogamp.opengl.egl.EGLContext; import jogamp.opengl.egl.EGLDrawable; -import jogamp.opengl.egl.EGLExt; public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl { final protected TextureType texType; diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java index 5baf9e543..74a051b77 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/OMXGLMediaPlayer.java @@ -33,9 +33,9 @@ import java.io.IOException; import javax.media.opengl.GL; import javax.media.opengl.GLException; +import com.jogamp.opengl.egl.EGL; import com.jogamp.opengl.util.texture.TextureSequence; -import jogamp.opengl.egl.EGL; import jogamp.opengl.util.av.EGLMediaPlayerImpl; /** diff --git a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java index e3e43b30c..8254f164c 100644 --- a/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java +++ b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java @@ -470,11 +470,11 @@ public class JPEGDecoder { } private final int readUInt8() throws IOException { - return bstream.readUInt8(true /* msbFirst */); + return bstream.readUInt8(); } private final int readUInt16() throws IOException { - return bstream.readUInt16(true /* msbFirst */, true /* bigEndian */); + return bstream.readUInt16(true /* bigEndian */); } private final int readNumber() throws IOException { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java index 33980d663..6b21c81be 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java @@ -316,6 +316,8 @@ public class WindowsWGLContext extends GLContextImpl { throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: "+GDI.GetLastError()); } if( !setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, null == sharedContext /* withinGLVersionsMapping */) ) { // use GL_VERSION + WGL.wglMakeCurrent(0, 0); // release temp context + WGL.wglDeleteContext(temp_ctx); throw new InternalError("setGLFunctionAvailability !strictMatch failed"); } WGL.wglMakeCurrent(0, 0); // release temp context @@ -368,7 +370,7 @@ public class WindowsWGLContext extends GLContextImpl { // otherwise context of similar profile but different creation method may not be share-able. WGL.wglMakeCurrent(0, 0); WGL.wglDeleteContext(temp_ctx); - throw new GLException(getThreadName()+": WindowsWGLContex.createContextImpl ctx !ARB but ARB is used, profile > GL2 requested (OpenGL >= 3.0.1). Requested: "+glCaps.getGLProfile()+", current: "+getGLVersion()); + throw new GLException(getThreadName()+": WindowsWGLContex.createContextImpl ctx !ARB but ARB is used, profile > GL2 requested (OpenGL >= 3.1). Requested: "+glCaps.getGLProfile()+", current: "+getGLVersion()); } if(DEBUG) { System.err.println("WindowsWGLContext.createContext ARB not used, fall back to !ARB context "+getGLVersion()); diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index fa052d784..8b67cc9ee 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -80,6 +80,7 @@ import jogamp.opengl.SharedResourceRunner; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.nativewindow.GenericUpstreamSurfacelessHook; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.GLRendererQuirks; @@ -275,7 +276,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - public final boolean isValid() { + public final boolean isAvailable() { return null != context; } @Override @@ -287,7 +288,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { @Override final public GLContextImpl getContext() { return context; } @Override - public GLRendererQuirks getRendererQuirks() { + public GLRendererQuirks getRendererQuirks(final GLProfile glp) { return null != context ? context.getRendererQuirks() : null; } @@ -303,12 +304,12 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { sharedMap.clear(); } @Override - public SharedResourceRunner.Resource mapPut(final String connection, final SharedResourceRunner.Resource resource) { - return sharedMap.put(connection, resource); + public SharedResourceRunner.Resource mapPut(final AbstractGraphicsDevice device, final SharedResourceRunner.Resource resource) { + return sharedMap.put(device.getConnection(), resource); } @Override - public SharedResourceRunner.Resource mapGet(final String connection) { - return sharedMap.get(connection); + public SharedResourceRunner.Resource mapGet(final AbstractGraphicsDevice device) { + return sharedMap.get(device.getConnection()); } @Override public Collection<SharedResourceRunner.Resource> mapValues() { @@ -318,13 +319,13 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - public boolean isDeviceSupported(final String connection) { + public boolean isDeviceSupported(final AbstractGraphicsDevice device) { return true; } @Override - public SharedResourceRunner.Resource createSharedResource(final String connection) { - final WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT); + public SharedResourceRunner.Resource createSharedResource(final AbstractGraphicsDevice device) { + final WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(device.getConnection(), device.getUnitID()); sharedDevice.lock(); try { final AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0); @@ -367,7 +368,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { hasARBPixelFormat, hasARBMultisample, hasARBPBuffer, hasARBReadDrawableAvailable); } catch (final Throwable t) { - throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+connection, t); + throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+device, t); } finally { sharedDevice.unlock(); } @@ -555,6 +556,13 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } @Override + public final ProxySurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) { + chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new GenericUpstreamSurfacelessHook(width, height)); + } + + @Override protected final ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) { final WindowsGraphicsDevice device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID()); final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java index 2285ae996..d13e4ddad 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java @@ -28,8 +28,10 @@ package jogamp.opengl.windows.wgl; -import jogamp.opengl.*; -import java.util.*; +import java.util.ArrayList; +import java.util.List; + +import jogamp.opengl.DesktopGLDynamicLibraryBundleInfo; public final class WindowsWGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo { protected WindowsWGLDynamicLibraryBundleInfo() { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java index 5785f8041..84b2ad719 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -48,6 +48,7 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.opengl.GLRendererQuirks; @@ -281,7 +282,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio System.err.println("GetPixelFormatAttribivARB: Failed - HDC 0x" + Long.toHexString(hdc) + ", value "+iresults.get(0)+ ", LastError: " + GDI.GetLastError()); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return 0; } @@ -290,7 +291,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio if(DEBUG) { System.err.println("GetPixelFormatAttribivARB: No formats - HDC 0x" + Long.toHexString(hdc) + ", LastError: " + GDI.GetLastError()); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } } return pfdIDCount; @@ -351,7 +352,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio iattributes, accelerationMode, null) ) { if (DEBUG) { System.err.println("wglChoosePixelFormatARB: GLCapabilities2AttribList failed: " + GDI.GetLastError()); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return null; } @@ -365,7 +366,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio pformatsTmp, numFormatsTmp) ) { if (DEBUG) { System.err.println("wglChoosePixelFormatARB: wglChoosePixelFormatARB failed: " + GDI.GetLastError()); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return null; } @@ -508,7 +509,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio caps.getAccumGreenBits() > 0 || caps.getAccumBlueBits() > 0 || caps.getAccumAlphaBits() > 0 ) { - final GLRendererQuirks sharedQuirks = sharedResource.getRendererQuirks(); + final GLRendererQuirks sharedQuirks = sharedResource.getRendererQuirks(null); if ( !usePBuffer || null==sharedQuirks || !sharedQuirks.exist(GLRendererQuirks.NoPBufferWithAccum) ) { iattributes.put(niattribs++, WGLExt.WGL_ACCUM_BITS_ARB); iattributes.put(niattribs++, ( caps.getAccumRedBits() + diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index ea9b86712..7c387827a 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -50,6 +50,7 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.opengl.GLRendererQuirks; @@ -131,7 +132,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat List<GLCapabilitiesImmutable> availableCaps = null; final GLContext sharedContext; - if ( factory.hasRendererQuirk(device, GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries) ) { + if ( factory.hasRendererQuirk(device, null, GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries) ) { sharedContext = sharedResource.getContext(); if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) { throw new GLException("Could not make Shared Context current: "+device); @@ -299,7 +300,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat final AbstractGraphicsDevice device = config.getScreen().getDevice(); final WindowsWGLDrawableFactory.SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResourceImpl(device); final GLContext sharedContext; - if ( factory.hasRendererQuirk(device, GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries) ) { + if ( factory.hasRendererQuirk(device, null, GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries) ) { sharedContext = sharedResource.getContext(); if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) { throw new GLException("Could not make Shared Context current: "+device); @@ -417,7 +418,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat if (null == pformats) { if (DEBUG) { System.err.println("updateGraphicsConfigurationARB: failed, return false"); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return false; } @@ -431,7 +432,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat if( null == availableCaps || 0 == availableCaps.size() ) { if (DEBUG) { System.err.println("updateGraphicsConfigurationARB: wglARBPFIDs2GLCapabilities failed with " + pformats.length + " pfd ids"); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return false; } @@ -453,7 +454,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat } if ( 0 > chosenIndex ) { if (DEBUG) { - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return false; } @@ -603,7 +604,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat if ( 0 > chosenIndex ) { if (DEBUG) { System.err.println("updateGraphicsConfigurationGDI: failed, return false"); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return false; } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index 9631dbb5b..4337eaf54 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -59,6 +59,7 @@ import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLXExtensions; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.VersionNumber; import com.jogamp.gluegen.runtime.ProcAddressTable; @@ -220,8 +221,6 @@ public class X11GLXContext extends GLContextImpl { final boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; final boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; - long ctx=0; - final IntBuffer attribs = Buffers.newDirectIntBuffer(ctx_arb_attribs_rom); attribs.put(ctx_arb_attribs_idx_major + 1, major); attribs.put(ctx_arb_attribs_idx_minor + 1, minor); @@ -249,6 +248,7 @@ public class X11GLXContext extends GLContextImpl { final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice device = config.getScreen().getDevice(); final long display = device.getHandle(); + long ctx=0; try { // critical path, a remote display might not support this command, @@ -258,8 +258,8 @@ public class X11GLXContext extends GLContextImpl { ctx = _glXExt.glXCreateContextAttribsARB(display, config.getFBConfig(), share, direct, attribs); } catch (final RuntimeException re) { if(DEBUG) { - final Throwable t = new Throwable(getThreadName()+": Info: X11GLXContext.createContextARBImpl glXCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re); - t.printStackTrace(); + System.err.println(getThreadName()+": Info: X11GLXContext.createContextARBImpl glXCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation")); + ExceptionUtils.dumpThrowable("", re); } } @@ -314,7 +314,10 @@ public class X11GLXContext extends GLContextImpl { throw new GLException(getThreadName()+": Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable); } if( !setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, null == sharedContext /* withinGLVersionsMapping */) ) { // use GL_VERSION - throw new InternalError("setGLFunctionAvailability !strictMatch failed"); + glXMakeContextCurrent(display, 0, 0, 0); // release temp context + GLX.glXDestroyContext(display, contextHandle); + contextHandle = 0; + throw new InternalError("setGLFunctionAvailability !strictMatch failed.1"); } isDirect = GLX.glXIsDirect(display, contextHandle); if (DEBUG) { @@ -345,7 +348,11 @@ public class X11GLXContext extends GLContextImpl { if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx) ) { throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, null == sharedContext /* withinGLVersionsMapping */); // use GL_VERSION + if( !setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, null == sharedContext /* withinGLVersionsMapping */) ) { // use GL_VERSION + glXMakeContextCurrent(display, 0, 0, 0); // release temp context + GLX.glXDestroyContext(display, temp_ctx); + throw new InternalError("setGLFunctionAvailability !strictMatch failed.2"); + } glXMakeContextCurrent(display, 0, 0, 0); // release temp context if( !createContextARBTried ) { // is*Available calls are valid since setGLFunctionAvailability(..) was called @@ -387,7 +394,7 @@ public class X11GLXContext extends GLContextImpl { // otherwise context of similar profile but different creation method may not be share-able. glXMakeContextCurrent(display, 0, 0, 0); GLX.glXDestroyContext(display, temp_ctx); - throw new GLException(getThreadName()+": X11GLXContext.createContextImpl ctx !ARB but ARB is used, profile > GL2 requested (OpenGL >= 3.0.1). Requested: "+glp+", current: "+getGLVersion()); + throw new GLException(getThreadName()+": X11GLXContext.createContextImpl ARB n/a but required, profile > GL2 requested (OpenGL >= 3.1). Requested: "+glp+", current: "+getGLVersion()); } if(DEBUG) { @@ -491,7 +498,7 @@ public class X11GLXContext extends GLContextImpl { x11Device.lock(); try{ if (DEBUG) { - System.err.println("GLX Version client version "+ GLXUtil.getClientVersionNumber()+ + System.err.println("GLX Version client "+ GLXUtil.getClientVersionNumber()+ ", server: "+ GLXUtil.getGLXServerVersionNumber(x11Device)); } if(((X11GLXDrawableFactory)drawable.getFactoryImpl()).isGLXVersionGreaterEqualOneOne(x11Device)) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index 60e4438d0..69d612da1 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -72,8 +72,10 @@ import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.SharedResourceRunner; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.VersionNumber; +import com.jogamp.nativewindow.GenericUpstreamSurfacelessHook; import com.jogamp.nativewindow.x11.X11GraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsScreen; import com.jogamp.opengl.GLRendererQuirks; @@ -183,7 +185,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { SharedResource(final X11GraphicsDevice dev, final X11GraphicsScreen scrn, final GLDrawableImpl draw, final GLContextImpl ctx, - final VersionNumber glXServerVer, final String glXServerVendor, final boolean glXServerMultisampleAvail) { + final VersionNumber glXServerVer, final String glXServerVendor, + final boolean glXServerMultisampleAvail) { device = dev; screen = scrn; drawable = draw; @@ -197,7 +200,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { glXMultisampleAvailable = glXServerMultisampleAvail; } @Override - public final boolean isValid() { + public final boolean isAvailable() { return null != context; } @Override @@ -209,7 +212,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { @Override final public GLContextImpl getContext() { return context; } @Override - public GLRendererQuirks getRendererQuirks() { + public GLRendererQuirks getRendererQuirks(final GLProfile glp) { return null != context ? context.getRendererQuirks() : null; } @@ -228,12 +231,12 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { sharedMap.clear(); } @Override - public SharedResourceRunner.Resource mapPut(final String connection, final SharedResourceRunner.Resource resource) { - return sharedMap.put(connection, resource); + public SharedResourceRunner.Resource mapPut(final AbstractGraphicsDevice device, final SharedResourceRunner.Resource resource) { + return sharedMap.put(device.getConnection(), resource); } @Override - public SharedResourceRunner.Resource mapGet(final String connection) { - return sharedMap.get(connection); + public SharedResourceRunner.Resource mapGet(final AbstractGraphicsDevice device) { + return sharedMap.get(device.getConnection()); } @Override public Collection<SharedResourceRunner.Resource> mapValues() { @@ -241,9 +244,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } @Override - public boolean isDeviceSupported(final String connection) { + public boolean isDeviceSupported(final AbstractGraphicsDevice device) { final boolean res; - final X11GraphicsDevice x11Device = new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */); + final X11GraphicsDevice x11Device = new X11GraphicsDevice(X11Util.openDisplay(device.getConnection()), device.getUnitID(), true /* owner */); x11Device.lock(); try { res = GLXUtil.isGLXAvailableOnServer(x11Device); @@ -258,51 +261,88 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } @Override - public SharedResourceRunner.Resource createSharedResource(final String connection) { - final X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */); - sharedDevice.lock(); + public SharedResourceRunner.Resource createSharedResource(final AbstractGraphicsDevice adevice) { + final X11GraphicsDevice x11Device = new X11GraphicsDevice(X11Util.openDisplay(adevice.getConnection()), adevice.getUnitID(), true /* owner */); + GLContextImpl context = null; + boolean contextIsCurrent = false; + x11Device.lock(); try { - final X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, sharedDevice.getDefaultScreen()); + final X11GraphicsScreen screen = new X11GraphicsScreen(x11Device, x11Device.getDefaultScreen()); - GLXUtil.initGLXClientDataSingleton(sharedDevice); - final String glXServerVendorName = GLX.glXQueryServerString(sharedDevice.getHandle(), 0, GLX.GLX_VENDOR); - final boolean glXServerMultisampleAvailable = GLXUtil.isMultisampleAvailable(GLX.glXQueryServerString(sharedDevice.getHandle(), 0, GLX.GLX_EXTENSIONS)); + GLXUtil.initGLXClientDataSingleton(x11Device); + final String glXServerVendorName = GLX.glXQueryServerString(x11Device.getHandle(), 0, GLX.GLX_VENDOR); + final boolean glXServerMultisampleAvailable = GLXUtil.isMultisampleAvailable(GLX.glXQueryServerString(x11Device.getHandle(), 0, GLX.GLX_EXTENSIONS)); - final GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false); + final GLProfile glp = GLProfile.get(x11Device, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false); if (null == glp) { - throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); + throw new GLException("Couldn't get default GLProfile for device: "+x11Device); } final GLCapabilitiesImmutable caps = new GLCapabilities(glp); - final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, caps, caps, null, 64, 64)); - sharedDrawable.setRealized(true); - final X11GLCapabilities chosenCaps = (X11GLCapabilities) sharedDrawable.getChosenGLCapabilities(); + final GLDrawableImpl drawable = createOnscreenDrawableImpl(createDummySurfaceImpl(x11Device, false, caps, caps, null, 64, 64)); + drawable.setRealized(true); + final X11GLCapabilities chosenCaps = (X11GLCapabilities) drawable.getChosenGLCapabilities(); final boolean glxForcedOneOne = !chosenCaps.hasFBConfig(); final VersionNumber glXServerVersion; if( glxForcedOneOne ) { glXServerVersion = versionOneOne; } else { - glXServerVersion = GLXUtil.getGLXServerVersionNumber(sharedDevice); + glXServerVersion = GLXUtil.getGLXServerVersionNumber(x11Device); } - final GLContextImpl sharedContext = (GLContextImpl) sharedDrawable.createContext(null); - if (null == sharedContext) { - throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable); + context = (GLContextImpl) drawable.createContext(null); + if (null == context) { + throw new GLException("Couldn't create shared context for drawable: "+drawable); } + contextIsCurrent = GLContext.CONTEXT_NOT_CURRENT != context.makeCurrent(); + + final boolean noSurfacelessCtxQuirk = context.hasRendererQuirk(GLRendererQuirks.NoSurfacelessCtx); + boolean allowsSurfacelessCtx = false; - boolean madeCurrent = false; - sharedContext.makeCurrent(); - try { - madeCurrent = sharedContext.isCurrent(); - } finally { - sharedContext.release(); + if( contextIsCurrent && + context.getGLVersionNumber().compareTo(GLContext.Version3_0) >= 0 && + !noSurfacelessCtxQuirk ) + { + GLDrawableImpl zeroDrawable = null; + try { + final ProxySurface zeroSurface = createSurfacelessImpl(x11Device, true, caps, caps, null, 64, 64); + zeroDrawable = createOnscreenDrawableImpl(zeroSurface); + zeroDrawable.setRealized(true); + + // Since sharedContext is still current, + // will keep sharedContext current w/ zeroDrawable or throws GLException + context.setGLDrawable(zeroDrawable, false); + allowsSurfacelessCtx = true; // if setGLDrawable is successful, i.e. no GLException + + // switch back + context.setGLDrawable(drawable, false); + } catch (final Throwable t) { + if( DEBUG ) { + ExceptionUtils.dumpThrowable("", t); + } + } finally { + if( null != zeroDrawable ) { + zeroDrawable.setRealized(false); + } + } } - if( sharedContext.hasRendererQuirk( GLRendererQuirks.DontCloseX11Display ) ) { + if( context.hasRendererQuirk( GLRendererQuirks.DontCloseX11Display ) ) { X11Util.markAllDisplaysUnclosable(); } + if( !noSurfacelessCtxQuirk && !allowsSurfacelessCtx ) { + final int quirk = GLRendererQuirks.NoSurfacelessCtx; + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+" -> "+x11Device+": cause: probe"); + } + final GLRendererQuirks glrq = context.getRendererQuirks(); + if( null != glrq ) { + glrq.addQuirk(quirk); + } + GLRendererQuirks.addStickyDeviceQuirk(x11Device, quirk); + } if (DEBUG) { - System.err.println("SharedDevice: " + sharedDevice); - System.err.println("SharedScreen: " + sharedScreen); - System.err.println("SharedContext: " + sharedContext + ", madeCurrent " + madeCurrent); + System.err.println("SharedDevice: " + x11Device); + System.err.println("SharedScreen: " + screen); + System.err.println("SharedContext: " + context + ", madeCurrent " + contextIsCurrent); System.err.println("GLX Server Vendor: " + glXServerVendorName); System.err.println("GLX Server Version: " + glXServerVersion + ", forced "+glxForcedOneOne); System.err.println("GLX Server Multisample: " + glXServerMultisampleAvailable); @@ -310,13 +350,16 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { System.err.println("GLX Client Version: " + GLXUtil.getClientVersionNumber()); System.err.println("GLX Client Multisample: " + GLXUtil.isClientMultisampleAvailable()); } - return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext, + return new SharedResource(x11Device, screen, drawable, context, glXServerVersion, glXServerVendorName, glXServerMultisampleAvailable && GLXUtil.isClientMultisampleAvailable()); } catch (final Throwable t) { - throw new GLException("X11GLXDrawableFactory - Could not initialize shared resources for "+connection, t); + throw new GLException("X11GLXDrawableFactory - Could not initialize shared resources for "+adevice, t); } finally { - sharedDevice.unlock(); + if ( contextIsCurrent ) { + context.release(); + } + x11Device.unlock(); } } @@ -329,7 +372,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { System.err.println("Screen : " + sr.screen); System.err.println("Drawable: " + sr.drawable); System.err.println("CTX : " + sr.context); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } if (null != sr.context) { @@ -524,6 +567,13 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } @Override + public final ProxySurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, + GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) { + chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new GenericUpstreamSurfacelessHook(width, height)); + } + + @Override protected final ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) { final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), true /* owner */); final X11GraphicsScreen screen = new X11GraphicsScreen(device, screenIdx); diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java index 0e91a6a65..bfe36dbc8 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java @@ -28,8 +28,10 @@ package jogamp.opengl.x11.glx; -import jogamp.opengl.*; -import java.util.*; +import java.util.ArrayList; +import java.util.List; + +import jogamp.opengl.DesktopGLDynamicLibraryBundleInfo; public final class X11GLXDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo { protected X11GLXDynamicLibraryBundleInfo() { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java index 44479acc0..caa336d5a 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -49,6 +49,7 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import com.jogamp.common.ExceptionUtils; import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.nativewindow.x11.X11GraphicsDevice; @@ -375,7 +376,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF if ( 0 > chosenIndex ) { if (DEBUG) { System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: failed, return null"); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return null; } @@ -472,7 +473,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF if ( 0 > chosenIndex ) { if (DEBUG) { System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: failed, return null"); - Thread.dumpStack(); + ExceptionUtils.dumpStack(System.err); } return null; } |