summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/jogamp/opengl')
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java54
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java184
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java18
3 files changed, 167 insertions, 89 deletions
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 417dbd011..652fc6ba9 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1548,7 +1548,9 @@ public abstract class GLContextImpl extends GLContext {
final VersionNumberString vendorVersion = GLVersionNumber.createVendorVersion(glVersion);
- setRendererQuirks(adevice, reqGLVersion.getMajor(), reqGLVersion.getMinor(), reqCtxProfileBits, major, minor, ctxProfileBits, vendorVersion, withinGLVersionsMapping);
+ setRendererQuirks(adevice, getDrawableImpl().getFactoryImpl(),
+ reqGLVersion.getMajor(), reqGLVersion.getMinor(), reqCtxProfileBits,
+ major, minor, ctxProfileBits, vendorVersion, withinGLVersionsMapping);
if( strictMatch && glRendererQuirks.exist(GLRendererQuirks.GLNonCompliant) ) {
if(DEBUG) {
@@ -1665,7 +1667,7 @@ public abstract class GLContextImpl extends GLContext {
return true;
}
- private final void setRendererQuirks(final AbstractGraphicsDevice adevice,
+ private final void setRendererQuirks(final AbstractGraphicsDevice adevice, final GLDrawableFactoryImpl factory,
int reqMajor, int reqMinor, int reqCTP,
int major, int minor, int ctp, final VersionNumberString vendorVersion,
boolean withinGLVersionsMapping) {
@@ -1688,16 +1690,26 @@ public abstract class GLContextImpl extends GLContext {
// General Quirks
//
if( esCtx ) {
- final int quirk = GLRendererQuirks.GLES3ViaEGLES2Config;
- if( GLRendererQuirks.existStickyDeviceQuirk( GLDrawableFactory.getEGLFactory().getDefaultDevice(), GLRendererQuirks.GLES3ViaEGLES2Config) ) {
- // Merge default sticky quirk!
+ if( 2 == reqMajor && 2 < major ) {
+ final int quirk = GLRendererQuirks.GLES3ViaEGLES2Config;
if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Default EGL Device");
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: ES req "+reqMajor+" and 2 < "+major);
}
quirks[i++] = quirk;
- } else if( 2 == reqMajor && 2 < major ) {
+ if( withinGLVersionsMapping ) {
+ // Thread safe due to single threaded initialization!
+ GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1);
+ } else {
+ // FIXME: Remove when moving EGL/ES to ARB ctx creation
+ synchronized(GLContextImpl.class) {
+ GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1);
+ }
+ }
+ }
+ if( isX11 && isDriverNVIDIAGeForce && Platform.CPUFamily.X86 == Platform.getCPUFamily() ) {
+ final int quirk = GLRendererQuirks.SingletonEGLDisplayOnly;
if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: ES req "+reqMajor+" and 2 < "+major);
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: ES, X11, CPUFamily AMD/Intel, [Vendor "+glVendor+" or Renderer "+glRenderer+"]");
}
quirks[i++] = quirk;
if( withinGLVersionsMapping ) {
@@ -1794,14 +1806,14 @@ public abstract class GLContextImpl extends GLContext {
if( glRenderer.contains("PowerVR") ) {
final int quirk = GLRendererQuirks.NoSetSwapInterval;
if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer);
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + ", Renderer " + glRenderer);
}
quirks[i++] = quirk;
}
if( glRenderer.contains("Immersion.16") ) {
final int quirk = GLRendererQuirks.GLSharedContextBuggy;
if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer);
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + ", Renderer " + glRenderer);
}
quirks[i++] = quirk;
}
@@ -1906,9 +1918,27 @@ public abstract class GLContextImpl extends GLContext {
}
glRendererQuirks = new GLRendererQuirks(quirks, 0, i);
- GLRendererQuirks.pushStickyDeviceQuirks(adevice, glRendererQuirks); // Thread safe due to single threaded initialization!
if(DEBUG) {
- System.err.println("Quirks local: "+glRendererQuirks);
+ System.err.println("Quirks local.0: "+glRendererQuirks);
+ }
+ {
+ // Merge sticky quirks, thread safe due to single threaded initialization!
+ GLRendererQuirks.pushStickyDeviceQuirks(adevice, glRendererQuirks);
+
+ final AbstractGraphicsDevice factoryDefaultDevice = factory.getDefaultDevice();
+ if( !GLRendererQuirks.areSameStickyDevice(factoryDefaultDevice, adevice) ) {
+ GLRendererQuirks.pushStickyDeviceQuirks(factoryDefaultDevice, glRendererQuirks);
+ }
+ if( esCtx ) {
+ final AbstractGraphicsDevice eglFactoryDefaultDevice = GLDrawableFactory.getEGLFactory().getDefaultDevice();
+ if( !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, adevice) &&
+ !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, factoryDefaultDevice) ) {
+ GLRendererQuirks.pushStickyDeviceQuirks(eglFactoryDefaultDevice, glRendererQuirks);
+ }
+ }
+ }
+ if(DEBUG) {
+ System.err.println("Quirks local.X: "+glRendererQuirks);
System.err.println("Quirks sticky on "+adevice+": "+GLRendererQuirks.getStickyDeviceQuirks(adevice));
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
index a1899e032..c5f76f667 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java
@@ -49,57 +49,120 @@ import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
* and <code>eglTerminate(..)</code> is issued only for the last call.
* <p>
* This class is required, due to implementation bugs within EGL where {@link EGL#eglTerminate(long)}
- * does not mark the resource for deletion when still in use, bug releases them immediatly.
+ * does not mark the resource for deletion when still in use, bug releases them immediately.
* </p>
*/
public class EGLDisplayUtil {
- protected static final boolean DEBUG = Debug.debug("EGLDisplayUtil");
+ private static final boolean DEBUG = Debug.debug("EGLDisplayUtil");
+ private static boolean useSingletonEGLDisplay = false;
+ private static EGLDisplayRef singletonEGLDisplay = null;
- private static class DpyCounter {
+ private static class EGLDisplayRef {
final long eglDisplay;
final Throwable createdStack;
- int refCount;
+ int initRefCount;
- private DpyCounter(long eglDisplay) {
+ /**
+ * Returns an already opened {@link EGLDisplayRef} or opens a new {@link EGLDisplayRef}.
+ * <p>
+ * Opened {@link EGLDisplayRef}s are mapped against their <code>eglDisplay</code> handle.
+ * </p>
+ * <p>
+ * Method utilizes {@link EGLDisplayRef}'s reference counter, i.e. increases it.
+ * </p>
+ * <p>
+ * An {@link EGLDisplayRef} is <i>opened</i> via {@link EGL#eglInitialize(long, IntBuffer, IntBuffer)}.
+ * </p>
+ */
+ static EGLDisplayRef getOrCreateOpened(final long eglDisplay, final IntBuffer major, final IntBuffer minor) {
+ EGLDisplayRef o = (EGLDisplayRef) openEGLDisplays.get(eglDisplay);
+ if( null == o ) {
+ if( EGL.eglInitialize(eglDisplay, major, minor) ) {
+ final EGLDisplayRef n = new EGLDisplayRef(eglDisplay);
+ openEGLDisplays.put(eglDisplay, n);
+ n.initRefCount++;
+ if( null == singletonEGLDisplay ) {
+ singletonEGLDisplay = n;
+ }
+ return n;
+ } else {
+ return null;
+ }
+ } else {
+ o.initRefCount++;
+ return o;
+ }
+ }
+
+ /**
+ * Closes an already opened {@link EGLDisplayRef}.
+ * <p>
+ * Method decreases a reference counter and closes the {@link EGLDisplayRef} if it reaches zero.
+ * </p>
+ * <p>
+ * An {@link EGLDisplayRef} is <i>closed</i> via {@link EGL#eglTerminate(long)}.
+ * </p>
+ */
+ static EGLDisplayRef closeOpened(final long eglDisplay, final boolean[] res) {
+ final EGLDisplayRef o = (EGLDisplayRef) openEGLDisplays.get(eglDisplay);
+ res[0] = true;
+ if( null != o ) {
+ if( 0 < o.initRefCount ) { // no negative refCount
+ o.initRefCount--;
+ if( 0 == o.initRefCount ) {
+ res[0] = EGL.eglTerminate(eglDisplay);
+ if( o == singletonEGLDisplay ) {
+ singletonEGLDisplay = null;
+ }
+ }
+ }
+ if( 0 >= o.initRefCount ) {
+ openEGLDisplays.remove(eglDisplay);
+ }
+ }
+ return o;
+ }
+
+ private EGLDisplayRef(long eglDisplay) {
this.eglDisplay = eglDisplay;
- this.refCount = 0;
+ this.initRefCount = 0;
this.createdStack = DEBUG ? new Throwable() : null;
}
@Override
public String toString() {
- return "EGLDisplay[0x"+Long.toHexString(eglDisplay)+": refCnt "+refCount+"]";
+ return "EGLDisplayRef[0x"+Long.toHexString(eglDisplay)+": refCnt "+initRefCount+"]";
}
}
- static final LongObjectHashMap eglDisplayCounter;
+ private static final LongObjectHashMap openEGLDisplays;
static {
- eglDisplayCounter = new LongObjectHashMap();
- eglDisplayCounter.setKeyNotFoundValue(null);
+ openEGLDisplays = new LongObjectHashMap();
+ openEGLDisplays.setKeyNotFoundValue(null);
}
/**
* @return number of unclosed EGL Displays.<br>
*/
public static int shutdown(boolean verbose) {
- if(DEBUG || verbose || eglDisplayCounter.size() > 0 ) {
- System.err.println("EGLDisplayUtil.EGLDisplays: Shutdown (open: "+eglDisplayCounter.size()+")");
+ if(DEBUG || verbose || openEGLDisplays.size() > 0 ) {
+ System.err.println("EGLDisplayUtil.EGLDisplays: Shutdown (open: "+openEGLDisplays.size()+")");
if(DEBUG) {
Thread.dumpStack();
}
- if( eglDisplayCounter.size() > 0) {
+ if( openEGLDisplays.size() > 0) {
dumpOpenDisplayConnections();
}
}
- return eglDisplayCounter.size();
+ return openEGLDisplays.size();
}
public static void dumpOpenDisplayConnections() {
- System.err.println("EGLDisplayUtil: Open EGL Display Connections: "+eglDisplayCounter.size());
+ System.err.println("EGLDisplayUtil: Open EGL Display Connections: "+openEGLDisplays.size());
int i=0;
- for(Iterator<LongObjectHashMap.Entry> iter = eglDisplayCounter.iterator(); iter.hasNext(); i++) {
+ for(Iterator<LongObjectHashMap.Entry> iter = openEGLDisplays.iterator(); iter.hasNext(); i++) {
final LongObjectHashMap.Entry e = iter.next();
- final DpyCounter v = (DpyCounter) e.value;
+ final EGLDisplayRef v = (EGLDisplayRef) e.value;
System.err.println("EGLDisplayUtil: Open["+i+"]: 0x"+Long.toHexString(e.key)+": "+v);
if(null != v.createdStack) {
v.createdStack.printStackTrace();
@@ -107,12 +170,22 @@ public class EGLDisplayUtil {
}
}
- public static long eglGetDisplay(long nativeDisplay_id) {
+ /* pp */ static synchronized void setSingletonEGLDisplayOnly(boolean v) { useSingletonEGLDisplay = v; }
+
+ private static synchronized long eglGetDisplay(long nativeDisplay_id) {
+ if( useSingletonEGLDisplay && null != singletonEGLDisplay ) {
+ if(DEBUG) {
+ System.err.println("EGLDisplayUtil.eglGetDisplay.s: eglDisplay("+EGLContext.toHexString(nativeDisplay_id)+"): "+
+ EGLContext.toHexString(singletonEGLDisplay.eglDisplay)+
+ ", "+((EGL.EGL_NO_DISPLAY != singletonEGLDisplay.eglDisplay)?"OK":"Failed")+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")");
+ }
+ return singletonEGLDisplay.eglDisplay;
+ }
final long eglDisplay = EGL.eglGetDisplay(nativeDisplay_id);
if(DEBUG) {
- System.err.println("EGLDisplayUtil.eglGetDisplay(): eglDisplay("+EGLContext.toHexString(nativeDisplay_id)+"): "+
+ System.err.println("EGLDisplayUtil.eglGetDisplay.X: eglDisplay("+EGLContext.toHexString(nativeDisplay_id)+"): "+
EGLContext.toHexString(eglDisplay)+
- ", "+((EGL.EGL_NO_DISPLAY != eglDisplay)?"OK":"Failed"));
+ ", "+((EGL.EGL_NO_DISPLAY != eglDisplay)?"OK":"Failed")+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")");
}
return eglDisplay;
}
@@ -125,39 +198,16 @@ public class EGLDisplayUtil {
*
* @see EGL#eglInitialize(long, IntBuffer, IntBuffer)
*/
- public static synchronized boolean eglInitialize(long eglDisplay, IntBuffer major, IntBuffer minor) {
+ private static synchronized boolean eglInitialize(long eglDisplay, IntBuffer major, IntBuffer minor) {
if( EGL.EGL_NO_DISPLAY == eglDisplay) {
return false;
}
- final int refCnt;
- final DpyCounter d;
- {
- DpyCounter _d = (DpyCounter) eglDisplayCounter.get(eglDisplay);
- if(null == _d) {
- _d = new DpyCounter(eglDisplay);
- refCnt = 1; // 1st init
- } else {
- refCnt = _d.refCount + 1;
- }
- d = _d;
- }
- final boolean res;
- if(1==refCnt) { // only initialize once
- res = EGL.eglInitialize(eglDisplay, major, minor);
- } else {
- res = true;
- }
- if(res) { // update refCount and map if successfully initialized, only
- d.refCount = refCnt;
- if(1 == refCnt) {
- eglDisplayCounter.put(eglDisplay, d);
- }
- }
+ final EGLDisplayRef d = EGLDisplayRef.getOrCreateOpened(eglDisplay, major, minor);
if(DEBUG) {
- System.err.println("EGLDisplayUtil.eglInitialize("+EGLContext.toHexString(eglDisplay)+" ...): #"+refCnt+", "+d+" = "+res);
+ System.err.println("EGLDisplayUtil.eglInitialize("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+(null != d)+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")");
// Thread.dumpStack();
}
- return res;
+ return null != d;
}
/**
@@ -172,14 +222,14 @@ public class EGLDisplayUtil {
* @see #eglGetDisplay(long)
* @see #eglInitialize(long, IntBuffer, IntBuffer)
*/
- public static synchronized int eglGetDisplayAndInitialize(long nativeDisplayID, long[] eglDisplay, int[] eglErr, IntBuffer major, IntBuffer minor) {
+ private static synchronized int eglGetDisplayAndInitialize(long nativeDisplayID, long[] eglDisplay, int[] eglErr, IntBuffer major, IntBuffer minor) {
eglDisplay[0] = EGL.EGL_NO_DISPLAY;
- final long _eglDisplay = EGLDisplayUtil.eglGetDisplay( nativeDisplayID );
+ final long _eglDisplay = eglGetDisplay( nativeDisplayID );
if ( EGL.EGL_NO_DISPLAY == _eglDisplay ) {
eglErr[0] = EGL.eglGetError();
return EGL.EGL_BAD_DISPLAY;
}
- if ( !EGLDisplayUtil.eglInitialize( _eglDisplay, major, minor) ) {
+ if ( !eglInitialize( _eglDisplay, major, minor) ) {
eglErr[0] = EGL.eglGetError();
return EGL.EGL_NOT_INITIALIZED;
}
@@ -197,7 +247,7 @@ public class EGLDisplayUtil {
* @return the initialized EGL display ID
* @throws GLException if not successful
*/
- public static synchronized long eglGetDisplayAndInitialize(long[] nativeDisplayID) {
+ private static synchronized long eglGetDisplayAndInitialize(long[] nativeDisplayID) {
final long[] eglDisplay = new long[1];
final int[] eglError = new int[1];
int eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(nativeDisplayID[0], eglDisplay, eglError, null, null);
@@ -221,40 +271,20 @@ public class EGLDisplayUtil {
* @param eglDisplay the EGL display handle
* @return true if the eglDisplay is valid and it's reference counter becomes zero and {@link EGL#eglTerminate(long)} was successful, otherwise false
*/
- public static synchronized boolean eglTerminate(long eglDisplay) {
+ private static synchronized boolean eglTerminate(long eglDisplay) {
if( EGL.EGL_NO_DISPLAY == eglDisplay) {
return false;
}
- final boolean res;
- final int refCnt;
- final DpyCounter d;
- {
- DpyCounter _d = (DpyCounter) eglDisplayCounter.get(eglDisplay);
- if(null == _d) {
- _d = null;
- refCnt = -1; // n/a
- } else {
- refCnt = _d.refCount - 1; // 1 - 1 = 0 -> final terminate
- }
- d = _d;
- }
- if( 0 == refCnt ) { // no terminate if still in use or already terminated
- res = EGL.eglTerminate(eglDisplay);
- eglDisplayCounter.remove(eglDisplay);
- } else {
- if(0 < refCnt) { // no negative refCount
- d.refCount = refCnt;
- }
- res = true;
- }
+ final boolean[] res = new boolean[1];
+ final EGLDisplayRef d = EGLDisplayRef.closeOpened(eglDisplay, res);
if(DEBUG) {
- System.err.println("EGLDisplayUtil.eglTerminate("+EGLContext.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res);
+ System.err.println("EGLDisplayUtil.eglTerminate.X("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+res[0]+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")");
// Thread.dumpStack();
}
- return res;
+ return res[0];
}
- public static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() {
+ private static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() {
@Override
public long eglGetAndInitDisplay(long[] nativeDisplayID) {
return eglGetDisplayAndInitialize(nativeDisplayID);
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index 3651d71a9..65ce98e07 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -361,6 +361,13 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
return new ArrayList<GLCapabilitiesImmutable>(0);
}
+ private static void dumpEGLInfo(final String prefix, final long eglDisplay) {
+ final String eglVendor = EGL.eglQueryString(eglDisplay, EGL.EGL_VENDOR);
+ final String eglClientAPIs = EGL.eglQueryString(eglDisplay, EGL.EGL_CLIENT_APIS);
+ final String eglVersion = EGL.eglQueryString(eglDisplay, EGL.EGL_VERSION);
+ System.err.println(prefix+"EGL vendor "+eglVendor+", version "+eglVersion+", clientAPIs "+eglClientAPIs);
+ }
+
private boolean mapAvailableEGLESConfig(AbstractGraphicsDevice adevice, int[] esProfile,
boolean[] hasPBuffer, GLRendererQuirks[] rendererQuirks, int[] ctp) {
final String profileString;
@@ -404,6 +411,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
// 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.
defaultDevice.open();
+ if( DEBUG ) {
+ dumpEGLInfo("EGLDrawableFactory.mapAvailableEGLESConfig: ", defaultDevice.getHandle());
+ }
+
final GLCapabilitiesImmutable reqCapsPBuffer = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(reqCapsAny);
final List<GLCapabilitiesImmutable> availablePBufferCapsL = getAvailableEGLConfigs(defaultDevice, reqCapsPBuffer);
hasPBuffer[0] = availablePBufferCapsL.size() > 0;
@@ -475,6 +486,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
surface = upstreamSurface;
eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface);
eglDevice.open();
+ if( DEBUG ) {
+ dumpEGLInfo("EGLDrawableFactory.mapAvailableEGLESConfig: ", eglDevice.getHandle());
+ }
hasPBuffer[0] = true;
}
@@ -533,6 +547,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
}
}
+ if( null != rendererQuirks[0] && rendererQuirks[0].exist(GLRendererQuirks.SingletonEGLDisplayOnly) ) {
+ EGLDisplayUtil.setSingletonEGLDisplayOnly(true);
+ }
+
return success;
}