diff options
author | Sven Gothel <[email protected]> | 2010-11-14 09:04:45 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-11-14 09:04:45 +0100 |
commit | 83d3a3f2ea8dc328e621b3abbe671f46379c7e65 (patch) | |
tree | b7fafe2ef1610a6be0723316ae5bf5938b9f222d /src/jogl/classes/com/jogamp/opengl | |
parent | c3bfb82614e9fa0f8ea7169cd412a6f0c71973e0 (diff) |
JOGL: Complete eager and lazy mapping of GLProfiles in respect to multiple device.
AbstractGraphicsDevice's 'connection' and 'type' attribute is used as a unique key
to map GLProfiles and GLContext's major/profile -> major/minor/profile mapping.
Eager initialiaztion as well as lazy is supported to maintain a simple API.
This is currently tested on X11, where one app display NEWT/GL window and content
on the local and remote device.
See TestRemoteWindow01NEWT.java and TestRemoteGLWindows01NEWT.java
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl')
15 files changed, 796 insertions, 343 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java index 86fbece4f..ee9d36147 100644 --- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java +++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java @@ -57,8 +57,8 @@ public class JoglVersion extends JogampVersion { return jogampCommonVersionInfo; } - public StringBuffer getInfo(GL gl, StringBuffer sb) { - sb = super.getInfo(sb); + public StringBuffer toStringBuffer(GL gl, StringBuffer sb) { + sb = super.toStringBuffer(sb); getGLInfo(gl, sb); sb.append("-----------------------------------------------------------------------------------------------------"); @@ -67,12 +67,18 @@ public class JoglVersion extends JogampVersion { return sb; } + public String toString(GL gl) { + return toStringBuffer(gl, null).toString(); + } + public static StringBuffer getGLInfo(GL gl, StringBuffer sb) { if(null==sb) { sb = new StringBuffer(); } - sb.append(GLProfile.glAvailabilityToString()); + sb.append("Default Desktop ").append(GLProfile.getDefaultDesktopDevice().getConnection()).append(": ").append(GLProfile.glAvailabilityToString(GLProfile.getDefaultDesktopDevice())); + sb.append(Platform.getNewline()); + sb.append("Default EGL ").append(GLProfile.getDefaultEGLDevice().getConnection()).append(": ").append(GLProfile.glAvailabilityToString(GLProfile.getDefaultEGLDevice())); sb.append(Platform.getNewline()); sb.append("Swap Interval ").append(gl.getSwapInterval()); sb.append(Platform.getNewline()); @@ -93,7 +99,7 @@ public class JoglVersion extends JogampVersion { } public static void main(String args[]) { - System.err.println(JoglVersion.getInstance().getInfo(null)); + System.err.println(JoglVersion.getInstance()); } } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java index ca689ed81..6c15a2d92 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java @@ -41,20 +41,37 @@ package com.jogamp.opengl.impl; import com.jogamp.common.os.DynamicLookupHelper; -import java.nio.*; -import java.util.*; - -import javax.media.opengl.*; -import javax.media.nativewindow.*; -import com.jogamp.gluegen.runtime.*; -import com.jogamp.gluegen.runtime.opengl.*; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.gluegen.runtime.FunctionAddressResolver; +import com.jogamp.gluegen.runtime.ProcAddressTable; +import com.jogamp.gluegen.runtime.opengl.GLExtensionNames; +import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; public abstract class GLContextImpl extends GLContext { - protected GLContextLock lock = new GLContextLock(); protected static final boolean DEBUG = Debug.debug("GLContext"); protected static final boolean VERBOSE = Debug.verbose(); + protected GLContextLock lock = new GLContextLock(); + + /** + * Context full qualified name: display_type + display_connection + major + minor + ctp. + * This is the key for all cached ProcAddressTables, etc, to support multi display/device setups. + */ + protected String contextFQN; + // Cache of the functions that are available to be called at the current // moment in time protected ExtensionAvailabilityCache extensionAvailability; @@ -73,15 +90,25 @@ public abstract class GLContextImpl extends GLContext { protected GL gl; + protected static final Object mappedContextTypeObjectLock; + protected static final HashMap mappedExtensionAvailabilityCache; + protected static final HashMap mappedGLProcAddress; + protected static final HashMap mappedGLXProcAddress; + + static { + mappedContextTypeObjectLock = new Object(); + mappedExtensionAvailabilityCache = new HashMap(); + mappedGLProcAddress = new HashMap(); + mappedGLXProcAddress = new HashMap(); + } + public GLContextImpl(GLDrawableImpl drawable, GLDrawableImpl drawableRead, GLContext shareWith) { - extensionAvailability = new ExtensionAvailabilityCache(this); + super(); + if (shareWith != null) { GLContextShareSet.registerSharing(this, shareWith); } GLContextShareSet.registerForBufferObjectSharing(shareWith, this); - // This must occur after the above calls into the - // GLContextShareSet, which set up state needed by the GL object - setGL(createGL(drawable.getGLProfile())); this.drawable = drawable; setGLDrawableRead(drawableRead); @@ -91,6 +118,32 @@ public abstract class GLContextImpl extends GLContext { this(drawable, null, shareWith); } + protected void resetStates() { + // Because we don't know how many other contexts we might be + // sharing with (and it seems too complicated to implement the + // GLObjectTracker's ref/unref scheme for the buffer-related + // optimizations), simply clear the cache of known buffers' sizes + // when we destroy contexts + if (bufferSizeTracker != null) { + bufferSizeTracker.clearCachedBufferSizes(); + } + + if (bufferStateTracker != null) { + bufferStateTracker.clearBufferObjectState(); + } + + if (glStateTracker != null) { + glStateTracker.clearStates(false); + } + + extensionAvailability = null; + glProcAddressTable = null; + gl = null; + contextFQN = null; + + super.resetStates(); + } + public void setGLDrawableRead(GLDrawable read) { boolean lockHeld = lock.isHeld(); if(lockHeld) { @@ -185,24 +238,7 @@ public abstract class GLContextImpl extends GLContext { } } */ - - // Because we don't know how many other contexts we might be - // sharing with (and it seems too complicated to implement the - // GLObjectTracker's ref/unref scheme for the buffer-related - // optimizations), simply clear the cache of known buffers' sizes - // when we destroy contexts - if (bufferSizeTracker != null) { - bufferSizeTracker.clearCachedBufferSizes(); - } - if (bufferStateTracker != null) { - bufferStateTracker.clearBufferObjectState(); - } - - if (glStateTracker != null) { - glStateTracker.clearStates(false); - } - if (contextHandle != 0) { int lockRes = drawable.lockSurface(); if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { @@ -220,6 +256,8 @@ public abstract class GLContextImpl extends GLContext { } finally { lock.unlock(); } + + resetStates(); } protected abstract void destroyImpl() throws GLException; @@ -364,6 +402,8 @@ public abstract class GLContextImpl extends GLContext { } boolean newCreated = false; if (!isCreated()) { + GLProfile.initProfiles( + getGLDrawable().getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice()); newCreated = createImpl(); // may throws exception if fails! if (DEBUG) { if(newCreated) { @@ -401,6 +441,8 @@ public abstract class GLContextImpl extends GLContext { * The implementation shall verify this context with a * <code>MakeContextCurrent</code> call.<br> * + * The implementation shall leave the context current.<br> + * * @param share the shared context or null * @param direct flag if direct is requested * @param ctxOptionFlags <code>ARB_create_context</code> related, see references below @@ -444,6 +486,8 @@ public abstract class GLContextImpl extends GLContext { * This method will also query all available native OpenGL context when first called,<br> * usually the first call should happen with the shared GLContext of the DrawableFactory.<br> * + * The implementation makes the context current, if successful<br> + * * @see #makeCurrentImpl * @see #create * @see #createContextARB @@ -454,14 +498,16 @@ public abstract class GLContextImpl extends GLContext { int major[], int minor[], int ctp[]) { AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); GLProfile glp = glCaps.getGLProfile(); if (DEBUG) { - System.err.println(getThreadName() + ": !!! createContextARB: mappedVersionsAvailableSet "+ mappedVersionsAvailableSet); + System.err.println(getThreadName() + ": !!! createContextARB: mappedVersionsAvailableSet("+device.getConnection()+"): "+ + GLContext.getAvailableGLVersionsSet(device)); } - mapGLVersions(); + mapGLVersions(device); int reqMajor; if(glp.isGL4()) { @@ -471,47 +517,44 @@ public abstract class GLContextImpl extends GLContext { } else /* if (glp.isGL2()) */ { reqMajor=2; } + boolean compat = glp.isGL2(); // incl GL3bc and GL4bc - - int key = compose8bit(reqMajor, compat?CTX_PROFILE_COMPAT:CTX_PROFILE_CORE, 0, 0); - int val; - synchronized(mappedVersionsAvailableLock) { - val = mappedVersionsAvailable.get( key ); - } + int _major[] = { 0 }; + int _minor[] = { 0 }; + int _ctp[] = { 0 }; long _ctx = 0; - if(val>0) { - int _major = getComposed8bit(val, 1); - int _minor = getComposed8bit(val, 2); - int _ctp = getComposed8bit(val, 3); - _ctx = createContextARBImpl(share, direct, _ctp, _major, _minor); + if( GLContext.getAvailableGLVersion(device, reqMajor, compat?CTX_PROFILE_COMPAT:CTX_PROFILE_CORE, + _major, _minor, _ctp)) { + _ctx = createContextARBImpl(share, direct, _ctp[0], _major[0], _minor[0]); if(0!=_ctx) { - setGLFunctionAvailability(true, _major, _minor, _ctp); + setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0]); } } return _ctx; } - private void mapGLVersions() { - if (!mappedVersionsAvailableSet) { - synchronized (mappedVersionsAvailableLock) { - if (!mappedVersionsAvailableSet) { - createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 - createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc - createContextARBMapVersionsAvailable(3, false /* core */); // GL3 - createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc - createContextARBMapVersionsAvailable(4, false /* core */); // GL4 - mappedVersionsAvailableSet = true; - if (DEBUG) { - System.err.println(getThreadName() + ": !!! createContextARB: SET mappedVersionsAvailableSet " + mappedVersionsAvailableSet); - } - } + private final void mapGLVersions(AbstractGraphicsDevice device) { + if ( !GLContext.getAvailableGLVersionsSet(device) ) { + synchronized (GLContext.deviceVersionAvailable) { + createContextARBMapVersionsAvailable(4, false /* core */); // GL4 + createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc + createContextARBMapVersionsAvailable(3, false /* core */); // GL3 + createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc + createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 + GLContext.setAvailableGLVersionsSet(device); + } + } else { + if(DEBUG) { + System.err.println(getThreadName() + ": no mapping, all versions set "+device.getConnection()); } } } private final void createContextARBMapVersionsAvailable(int reqMajor, boolean compat) { + resetStates(); + long _context; int reqProfile = compat ? CTX_PROFILE_COMPAT : CTX_PROFILE_CORE ; int ctp = CTX_IS_ARB_CREATED | CTX_PROFILE_CORE | CTX_OPTION_ANY; // default @@ -570,11 +613,14 @@ public abstract class GLContextImpl extends GLContext { } } if(0!=_context) { - destroyContextARBImpl(_context); - mapVersionAvailable(reqMajor, reqProfile, major[0], minor[0], ctp); + AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, major[0], minor[0], ctp); setGLFunctionAvailability(true, major[0], minor[0], ctp); + destroyContextARBImpl(_context); + resetStates(); if (DEBUG) { - System.err.println(getThreadName() + ": !!! createContextARBMapVersionsAvailable HAVE: "+getGLVersionAvailable(reqMajor, reqProfile)); + System.err.println(getThreadName() + ": !!! createContextARBMapVersionsAvailable HAVE: "+ + GLContext.getAvailableGLVersionAsString(device, reqMajor, reqProfile)); } } else if (DEBUG) { System.err.println(getThreadName() + ": !!! createContextARBMapVersionsAvailable NOPE: "+reqMajor+"."+reqProfile); @@ -615,7 +661,7 @@ public abstract class GLContextImpl extends GLContext { * If major==0 && minor == 0 : Use GL_VERSION * Otherwise .. don't touch .. */ - protected final void setContextVersion(int major, int minor, int ctp) { + private final void setContextVersion(int major, int minor, int ctp) { if (0==ctp) { throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); } @@ -643,6 +689,13 @@ public abstract class GLContextImpl extends GLContext { if (version.isValid()) { ctxMajorVersion = version.getMajor(); ctxMinorVersion = version.getMinor(); + // We cannot promote a non ARB context to >= 3.1, + // reduce it to 3.0 then. + if ( ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) + && 0 == (ctxOptions & CTX_IS_ARB_CREATED) ) { + ctxMajorVersion = 3; + ctxMinorVersion = 0; + } ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, versionStr); return; } @@ -750,13 +803,17 @@ public abstract class GLContextImpl extends GLContext { * the cache of which GL functions are available for calling through this * context. See {@link #isFunctionAvailable(String)} for more information on * the definition of "available". + * <br> + * All ProcaddressTables are being determined, the GL version is being set + * and the extension cache is determined as well. * * @param force force the setting, even if is already being set. - * This might be usefull if you change the OpenGL implementation. + * This might be useful if you change the OpenGL implementation. * * @see #setContextVersion */ - protected void setGLFunctionAvailability(boolean force, int major, int minor, int ctp) { + + protected final void setGLFunctionAvailability(boolean force, int major, int minor, int ctp) { if(null!=this.gl && null!=glProcAddressTable && !force) { return; // already done and not forced } @@ -764,37 +821,34 @@ public abstract class GLContextImpl extends GLContext { setGL(createGL(getGLDrawable().getGLProfile())); } - updateGLProcAddressTable(major, minor, ctp); - } + AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + contextFQN = getContextFQN(adevice, major, minor, ctp); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Context FQN: "+contextFQN); + } - /** - * Updates the cache of which GL functions are available for calling through this - * context. See {@link #isFunctionAvailable(String)} for more information on - * the definition of "available". - * - * @see #setContextVersion - */ - protected void updateGLProcAddressTable(int major, int minor, int ctp) { + updateGLXProcAddressTable(major, minor, ctp); + + // + // UpdateGLProcAddressTable functionality + // if(null==this.gl) { throw new GLException("setGLFunctionAvailability not called yet"); } - if (DEBUG) { - System.err.println(getThreadName() + ": !!! Initializing OpenGL extension address table for " + this); - } - int key = compose8bit(major, minor, ctp, 0); ProcAddressTable table = null; - synchronized(mappedProcAddressLock) { - table = (ProcAddressTable) mappedGLProcAddress.get( key ); + synchronized(mappedContextTypeObjectLock) { + table = (ProcAddressTable) mappedGLProcAddress.get( contextFQN ); if(null != table && !verifyInstance(gl.getGLProfile(), "ProcAddressTable", table)) { - throw new InternalError("GLContext GL ProcAddressTable mapped key("+major+","+minor+","+ctp+") -> "+ + throw new InternalError("GLContext GL ProcAddressTable mapped key("+contextFQN+") -> "+ table.getClass().getName()+" not matching "+gl.getGLProfile().getGLImplBaseClassName()); } } if(null != table) { glProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GL ProcAddressTable reusing key("+major+","+minor+","+ctp+") -> "+table.hashCode()); + System.err.println(getThreadName() + ": !!! GLContext GL ProcAddressTable reusing key("+contextFQN+") -> "+table.hashCode()); } } else { if (glProcAddressTable == null) { @@ -803,20 +857,52 @@ public abstract class GLContextImpl extends GLContext { new Object[] { new GLProcAddressResolver() } ); } resetProcAddressTable(getGLProcAddressTable()); - synchronized(mappedProcAddressLock) { - mappedGLProcAddress.put(key, getGLProcAddressTable()); + synchronized(mappedContextTypeObjectLock) { + mappedGLProcAddress.put(contextFQN, getGLProcAddressTable()); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GL ProcAddressTable mapping key("+major+","+minor+","+ctp+") -> "+getGLProcAddressTable().hashCode()); + System.err.println(getThreadName() + ": !!! GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+getGLProcAddressTable().hashCode()); } } } + + // + // Set GL Version + // setContextVersion(major, minor, ctp); - extensionAvailability.reset(); + // + // Update ExtensionAvailabilityCache + // + ExtensionAvailabilityCache eCache; + synchronized(mappedContextTypeObjectLock) { + eCache = (ExtensionAvailabilityCache) mappedExtensionAvailabilityCache.get( contextFQN ); + } + if(null != eCache) { + extensionAvailability = eCache; + if(DEBUG) { + System.err.println(getThreadName() + ": !!! GLContext GL ExtensionAvailabilityCache reusing key("+contextFQN+") -> "+eCache.hashCode()); + } + } else { + if(null==extensionAvailability) { + extensionAvailability = new ExtensionAvailabilityCache(this); + } + extensionAvailability.reset(); + synchronized(mappedContextTypeObjectLock) { + mappedExtensionAvailabilityCache.put(contextFQN, extensionAvailability); + if(DEBUG) { + System.err.println(getThreadName() + ": !!! GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+extensionAvailability.hashCode()); + } + } + } hasNativeES2Methods = isGLES2() || isExtensionAvailable("GL_ARB_ES2_compatibility") ; } + /** + * Updates the platform's 'GLX' function cache + */ + protected abstract void updateGLXProcAddressTable(int major, int minor, int ctp); + protected boolean hasNativeES2Methods = false; public final boolean hasNativeES2Methods() { return hasNativeES2Methods; } @@ -833,23 +919,26 @@ public abstract class GLContextImpl extends GLContext { * javax.media.opengl.GL#glPolygonOffset(float,float)} is available). */ public boolean isFunctionAvailable(String glFunctionName) { - if(isCreated()) { - // Check GL 1st (cached) - ProcAddressTable pTable = getGLProcAddressTable(); + // Check GL 1st (cached) + ProcAddressTable pTable = getGLProcAddressTable(); // null if ctx not created once + if(null!=pTable) { try { if(0!=pTable.getAddressFor(glFunctionName)) { return true; } } catch (Exception e) {} + } - // Check platform extensions 2nd (cached) - pTable = getPlatformExtProcAddressTable(); + // Check platform extensions 2nd (cached) - had to be enabled once + pTable = getPlatformExtProcAddressTable(); // null if ctx not created once + if(null!=pTable) { try { if(0!=pTable.getAddressFor(glFunctionName)) { return true; } } catch (Exception e) {} } + // dynamic function lookup at last incl name aliasing (not cached) DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper(); String tmpBase = GLExtensionNames.normalizeVEN(GLExtensionNames.normalizeARB(glFunctionName, true), true); @@ -878,19 +967,31 @@ public abstract class GLContextImpl extends GLContext { * "GL_VERTEX_PROGRAM_ARB"). */ public boolean isExtensionAvailable(String glExtensionName) { - return extensionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName)); + if(null!=extensionAvailability) { + return extensionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName)); + } + return false; } public String getPlatformExtensionsString() { - return extensionAvailability.getPlatformExtensionsString(); + if(null!=extensionAvailability) { + return extensionAvailability.getPlatformExtensionsString(); + } + return null; } public String getGLExtensions() { - return extensionAvailability.getGLExtensions(); + if(null!=extensionAvailability) { + return extensionAvailability.getGLExtensions(); + } + return null; } public boolean isExtensionCacheInitialized() { - return extensionAvailability.isInitialized(); + if(null!=extensionAvailability) { + return extensionAvailability.isInitialized(); + } + return false; } /** Indicates which floating-point pbuffer implementation is in @@ -909,10 +1010,6 @@ public abstract class GLContextImpl extends GLContext { /** Only called for offscreen contexts; needed by glReadPixels */ public abstract int getOffscreenContextPixelDataType(); - protected static String getThreadName() { - return Thread.currentThread().getName(); - } - //---------------------------------------------------------------------- // Helpers for buffer object optimizations diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java index 6837949d3..43f705e34 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java @@ -225,8 +225,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // // GLDrawableFactoryImpl details // - protected abstract GLDrawableImpl getSharedDrawable(); - protected abstract GLContextImpl getSharedContext(); protected void maybeDoSingleThreadedWorkaround(Runnable action) { if (Threading.isSingleThreaded() && diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2D.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2D.java index d8f83a5f7..5566a3a4a 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2D.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2D.java @@ -558,7 +558,7 @@ public class Java2D { } invokeWithOGLSharedContextCurrent(device.getDefaultConfiguration(), new Runnable() { public void run() { - j2dFBOShareContext = GLDrawableFactory.getFactory(GLProfile.getDefault()).createExternalGLContext(); + j2dFBOShareContext = GLDrawableFactory.getFactory(GLProfile.getDefault(GLProfile.getDefaultDesktopDevice())).createExternalGLContext(); } }); if (DEBUG) { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java index d8b5b78f2..d95a9e3ff 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java @@ -192,22 +192,21 @@ public abstract class EGLContext extends GLContextImpl { return true; } - protected void updateGLProcAddressTable(int major, int minor, int ctp) { + protected final void updateGLXProcAddressTable(int major, int minor, int ctp) { if (DEBUG) { System.err.println(getThreadName() + ": !!! Initializing EGL extension address table"); } eglQueryStringInitialized = false; eglQueryStringAvailable = false; - int key = compose8bit(major, minor, ctp, 0); EGLExtProcAddressTable table = null; - synchronized(mappedProcAddressLock) { - table = (EGLExtProcAddressTable) mappedGLXProcAddress.get( key ); + synchronized(mappedContextTypeObjectLock) { + table = (EGLExtProcAddressTable) mappedGLXProcAddress.get( contextFQN ); } if(null != table) { eglExtProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext EGL ProcAddressTable reusing key("+major+","+minor+","+ctp+") -> "+table.hashCode()); + System.err.println(getThreadName() + ": !!! GLContext EGL ProcAddressTable reusing key("+contextFQN+") -> "+table.hashCode()); } } else { if (eglExtProcAddressTable == null) { @@ -216,14 +215,13 @@ public abstract class EGLContext extends GLContextImpl { eglExtProcAddressTable = new EGLExtProcAddressTable(new GLProcAddressResolver()); } resetProcAddressTable(getEGLExtProcAddressTable()); - synchronized(mappedProcAddressLock) { - mappedGLXProcAddress.put(key, getEGLExtProcAddressTable()); + synchronized(mappedContextTypeObjectLock) { + mappedGLXProcAddress.put(contextFQN, getEGLExtProcAddressTable()); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext EGL ProcAddressTable mapping key("+major+","+minor+","+ctp+") -> "+getEGLExtProcAddressTable().hashCode()); + System.err.println(getThreadName() + ": !!! GLContext EGL ProcAddressTable mapping key("+contextFQN+") -> "+getEGLExtProcAddressTable().hashCode()); } } } - super.updateGLProcAddressTable(major, minor, ctp); } public synchronized String getPlatformExtensionsString() { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java index deb659ddf..6ebd3938a 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java @@ -42,6 +42,8 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.*; import com.jogamp.opengl.impl.*; import com.jogamp.nativewindow.impl.ProxySurface; +import java.util.HashMap; +import javax.media.nativewindow.egl.EGLGraphicsDevice; public class EGLDrawableFactory extends GLDrawableFactoryImpl { @@ -93,6 +95,39 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { public EGLDrawableFactory() { super(); + /** FIXME: + * find out the Windows semantics of a device connection {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection()} + * to actually use multiple devices. + */ + defaultDevice = new EGLGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION); + } + + static class SharedResource { + private EGLDrawable drawable; + private EGLContext context; + + SharedResource(EGLDrawable draw, EGLContext ctx) { + drawable = draw; + context = ctx; + } + } + HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); + EGLGraphicsDevice defaultDevice; + + public final AbstractGraphicsDevice getDefaultDevice() { + return defaultDevice; + } + + public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) { + if(device instanceof EGLGraphicsDevice) { + return true; + } + return false; + } + + protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) { + // FIXME: not implemented .. needs a dummy EGL surface + return null; } public GLDynamicLookupHelper getGLDynamicLookupHelper(int esProfile) { @@ -112,8 +147,6 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } protected void shutdownInstance() {} - protected final GLDrawableImpl getSharedDrawable() { return null; } - protected final GLContextImpl getSharedContext() { return null; } protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { if (target == null) { @@ -141,7 +174,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } protected GLContext createExternalGLContextImpl() { - AbstractGraphicsScreen absScreen = DefaultGraphicsScreen.createScreenDevice(0); + AbstractGraphicsScreen absScreen = DefaultGraphicsScreen.createScreenDevice(AbstractGraphicsDevice.EXTERNAL_CONNECTION, 0); return new EGLExternalContext(absScreen); } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java index f9934fe20..e9b543721 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java @@ -224,19 +224,18 @@ public abstract class MacOSXCGLContext extends GLContextImpl } } - protected void updateGLProcAddressTable(int major, int minor, int ctp) { + protected final void updateGLXProcAddressTable(int major, int minor, int ctp) { if (DEBUG) { System.err.println(getThreadName() + ": !!! Initializing CGL extension address table"); } - int key = compose8bit(major, minor, ctp, 0); CGLExtProcAddressTable table = null; - synchronized(mappedProcAddressLock) { - table = (CGLExtProcAddressTable) mappedGLXProcAddress.get( key ); + synchronized(mappedContextTypeObjectLock) { + table = (CGLExtProcAddressTable) mappedGLXProcAddress.get( contextFQN ); } if(null != table) { cglExtProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext CGL ProcAddressTable reusing key("+major+","+minor+","+ctp+") -> "+table.hashCode()); + System.err.println(getThreadName() + ": !!! GLContext CGL ProcAddressTable reusing key("+contextFQN+") -> "+table.hashCode()); } } else { if (cglExtProcAddressTable == null) { @@ -245,14 +244,13 @@ public abstract class MacOSXCGLContext extends GLContextImpl cglExtProcAddressTable = new CGLExtProcAddressTable(new GLProcAddressResolver()); } resetProcAddressTable(getCGLExtProcAddressTable()); - synchronized(mappedProcAddressLock) { - mappedGLXProcAddress.put(key, getCGLExtProcAddressTable()); + synchronized(mappedContextTypeObjectLock) { + mappedGLXProcAddress.put(contextFQN, getCGLExtProcAddressTable()); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext CGL ProcAddressTable mapping key("+major+","+minor+","+ctp+") -> "+getCGLExtProcAddressTable().hashCode()); + System.err.println(getThreadName() + ": !!! GLContext CGL ProcAddressTable mapping key("+contextFQN+") -> "+getCGLExtProcAddressTable().hashCode()); } } } - super.updateGLProcAddressTable(major, minor, ctp); } public String getPlatformExtensionsString() diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java index 9a02e55ee..f41b68d31 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -47,6 +47,8 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.*; import com.jogamp.opengl.impl.*; import com.jogamp.nativewindow.impl.ProxySurface; +import java.util.HashMap; +import javax.media.nativewindow.macosx.MacOSXGraphicsDevice; public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { private static final DesktopGLDynamicLookupHelper macOSXCGLDynamicLookupHelper; @@ -83,11 +85,43 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { null, getClass().getClassLoader()); } catch (JogampRuntimeException jre) { /* n/a .. */ } } + + /** FIXME: + * find out the Windows semantics of a device connection {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection()} + * to actually use multiple devices. + */ + defaultDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION); + } + + static class SharedResource { + private MacOSXCGLDrawable drawable; + private MacOSXCGLContext context; + + SharedResource(MacOSXCGLDrawable draw, MacOSXCGLContext ctx) { + drawable = draw; + context = ctx; + } + } + HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); + MacOSXGraphicsDevice defaultDevice; + + public final AbstractGraphicsDevice getDefaultDevice() { + return defaultDevice; + } + + public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) { + if(device instanceof MacOSXGraphicsDevice) { + return true; + } + return false; + } + + protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) { + // FIXME: not implemented .. needs a dummy OSX surface + return null; } protected void shutdownInstance() {} - protected final GLDrawableImpl getSharedDrawable() { return null; } - protected final GLContextImpl getSharedContext() { return null; } protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { if (target == null) { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java index c9a12c85b..7be597dcc 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java @@ -49,12 +49,12 @@ import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; public class WindowsWGLContext extends GLContextImpl { + private static final Map/*<String, String>*/ functionNameMap; + private static final Map/*<String, String>*/ extensionNameMap; private boolean wglGetExtensionsStringEXTInitialized; private boolean wglGetExtensionsStringEXTAvailable; private boolean wglMakeContextCurrentInitialized; private boolean wglMakeContextCurrentAvailable; - private static final Map/*<String, String>*/ functionNameMap; - private static final Map/*<String, String>*/ extensionNameMap; private WGLExt wglExt; // Table that holds the addresses of the native C-language entry points for // WGL extension functions. @@ -80,6 +80,15 @@ public class WindowsWGLContext extends GLContextImpl { GLContext shareWith) { this(drawable, null, shareWith); } + + protected void resetState() { + wglGetExtensionsStringEXTInitialized=false; + wglGetExtensionsStringEXTAvailable=false; + wglMakeContextCurrentInitialized=false; + wglMakeContextCurrentAvailable=false; + // no inner state wglExt=null; + wglExtProcAddressTable=null; + } public Object getPlatformGLExtensions() { return getWGLExt(); @@ -120,17 +129,20 @@ public class WindowsWGLContext extends GLContextImpl { protected Map/*<String, String>*/ getExtensionNameMap() { return extensionNameMap; } protected void destroyContextARBImpl(long context) { - WGL.wglMakeCurrent(0, 0); + wglMakeContextCurrent(0, 0, 0); WGL.wglDeleteContext(context); } protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); + AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); + WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); WGLExt wglExt; - if(null==factory.getSharedContext()) { + if(null==sharedContext) { wglExt = getWGLExt(); } else { - wglExt = ((WindowsWGLContext)factory.getSharedContext()).getWGLExt(); + wglExt = sharedContext.getWGLExt(); } boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; @@ -171,22 +183,32 @@ public class WindowsWGLContext extends GLContextImpl { } } - ctx = wglExt.wglCreateContextAttribsARB(drawable.getHandle(), share, attribs, 0); - if(DEBUG) { - System.err.println("WindowsWGLContext.createContextARB success: "+(0!=ctx)+" - "+getGLVersion(major, minor, ctp, "@creation")+", bwdCompat "+ctBwdCompat+", fwdCompat "+ctFwdCompat); + try { + ctx = wglExt.wglCreateContextAttribsARB(drawable.getHandle(), share, attribs, 0); + } catch (RuntimeException re) { + if(DEBUG) { + Throwable t = new Throwable("Info: WindowWGLContext.createContextARBImpl wglCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re); + t.printStackTrace(); + } } + if(0!=ctx) { - // In contrast to GLX no verification with a drawable binding, ie default framebuffer, is necessary, - // if no 3.2 is available creation fails already! - // Nevertheless .. we do it .. - if (!WGL.wglMakeCurrent(drawable.getHandle(), ctx)) { + if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), ctx)) { if(DEBUG) { System.err.println("WindowsWGLContext.createContextARB couldn't make current "+getGLVersion(major, minor, ctp, "@creation")); } WGL.wglMakeCurrent(0, 0); WGL.wglDeleteContext(ctx); ctx = 0; + } else { + if (DEBUG) { + System.err.println(getThreadName() + ": createContextARBImpl: OK "+getGLVersion(major, minor, ctp, "@creation")+", share "+share+", direct "+direct+", hasSharedContext "+(null!=sharedContext)); + } + // the following is issued by the caller 'GLContextImpl.createContextARB()' + // setGLFunctionAvailability(true, major, minor, ctp); } + } else if (DEBUG) { + System.err.println(getThreadName() + ": createContextARBImpl: NO "+getGLVersion(major, minor, ctp, "@creation")); } return ctx; } @@ -197,6 +219,9 @@ public class WindowsWGLContext extends GLContextImpl { */ protected boolean createImpl() { WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); + AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); + WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); GLCapabilities glCaps = drawable.getChosenGLCapabilities(); // Windows can set up sharing of display lists after creation time @@ -215,7 +240,7 @@ public class WindowsWGLContext extends GLContextImpl { boolean createContextARBTried = false; // utilize the shared context's GLXExt in case it was using the ARB method and it already exists - if( null!=factory.getSharedContext() && factory.getSharedContext().isCreatedWithARBMethod() ) { + if( null!=sharedContext && sharedContext.isCreatedWithARBMethod() ) { contextHandle = createContextARB(share, true, major, minor, ctp); createContextARBTried = true; if (DEBUG && 0!=contextHandle) { @@ -235,16 +260,24 @@ public class WindowsWGLContext extends GLContextImpl { throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: 0x"+Integer.toHexString(GDI.GetLastError())); } setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + boolean isCreateContextAttribsARBAvailable = isFunctionAvailable("wglCreateContextAttribsARB"); WGL.wglMakeCurrent(0, 0); // release temp context - if( !createContextARBTried && - isFunctionAvailable("wglCreateContextAttribsARB") && - isExtensionAvailable("WGL_ARB_create_context") ) { - // initial ARB context creation - contextHandle = createContextARB(share, true, major, minor, ctp); - createContextARBTried=true; - if (DEBUG && 0!=contextHandle) { - System.err.println(getThreadName() + ": createImpl: OK (ARB, initial) share "+share); + if( !createContextARBTried) { + if(isCreateContextAttribsARBAvailable && + isExtensionAvailable("WGL_ARB_create_context") ) { + // initial ARB context creation + contextHandle = createContextARB(share, true, major, minor, ctp); + createContextARBTried=true; + if (DEBUG) { + if(0!=contextHandle) { + System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+share); + } else { + System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+share); + } + } + } else if (DEBUG) { + System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+share); } } } @@ -328,7 +361,7 @@ public class WindowsWGLContext extends GLContextImpl { } } - protected void updateGLProcAddressTable(int major, int minor, int ctp) { + protected final void updateGLXProcAddressTable(int major, int minor, int ctp) { if (DEBUG) { System.err.println(getThreadName() + ": !!! Initializing WGL extension address table for " + this); } @@ -337,15 +370,14 @@ public class WindowsWGLContext extends GLContextImpl { wglMakeContextCurrentInitialized=false; wglMakeContextCurrentAvailable=false; - int key = compose8bit(major, minor, ctp, 0); WGLExtProcAddressTable table = null; - synchronized(mappedProcAddressLock) { - table = (WGLExtProcAddressTable) mappedGLXProcAddress.get( key ); + synchronized(mappedContextTypeObjectLock) { + table = (WGLExtProcAddressTable) mappedGLXProcAddress.get( contextFQN ); } if(null != table) { wglExtProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext WGL ProcAddressTable reusing key("+major+","+minor+","+ctp+") -> "+table.hashCode()); + System.err.println(getThreadName() + ": !!! GLContext WGL ProcAddressTable reusing key("+contextFQN+") -> "+table.hashCode()); } } else { if (wglExtProcAddressTable == null) { @@ -354,14 +386,13 @@ public class WindowsWGLContext extends GLContextImpl { wglExtProcAddressTable = new WGLExtProcAddressTable(new GLProcAddressResolver()); } resetProcAddressTable(getWGLExtProcAddressTable()); - synchronized(mappedProcAddressLock) { - mappedGLXProcAddress.put(key, getWGLExtProcAddressTable()); + synchronized(mappedContextTypeObjectLock) { + mappedGLXProcAddress.put(contextFQN, getWGLExtProcAddressTable()); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext WGL ProcAddressTable mapping key("+major+","+minor+","+ctp+") -> "+getWGLExtProcAddressTable().hashCode()); + System.err.println(getThreadName() + ": !!! GLContext WGL ProcAddressTable mapping key("+contextFQN+") -> "+getWGLExtProcAddressTable().hashCode()); } } } - super.updateGLProcAddressTable(major, minor, ctp); } public String getPlatformExtensionsString() { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java index cea176b1f..f8405961f 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java @@ -48,6 +48,7 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.*; import com.jogamp.opengl.impl.*; import com.jogamp.nativewindow.impl.ProxySurface; +import javax.media.nativewindow.windows.WindowsGraphicsDevice; public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { private static final boolean VERBOSE = Debug.verbose(); @@ -86,57 +87,112 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } catch (JogampRuntimeException jre) { /* n/a .. */ } } - NativeWindowFactory.getDefaultToolkitLock().lock(); // OK - try { - sharedDrawable = new WindowsDummyWGLDrawable(this, null); - WindowsWGLContext ctx = (WindowsWGLContext) sharedDrawable.createContext(null); - ctx.makeCurrent(); - canCreateGLPbuffer = ctx.getGL().isExtensionAvailable("GL_ARB_pbuffer"); - ctx.release(); - sharedContext = ctx; - } catch (Throwable t) { - throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources", t); - } finally { - NativeWindowFactory.getDefaultToolkitLock().unlock(); // OK - } - if(null==sharedContext) { - throw new GLException("WindowsWGLDrawableFactory - Shared Context is null"); - } - if (DEBUG) { - System.err.println("!!! SharedContext: "+sharedContext+", pbuffer supported "+canCreateGLPbuffer); - } + /** FIXME: + * find out the Windows semantics of a device connection {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection()} + * to actually use multiple devices. + */ + defaultDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION); } - WindowsDummyWGLDrawable sharedDrawable=null; - WindowsWGLContext sharedContext=null; - boolean canCreateGLPbuffer = false; + static class SharedResource { + private WindowsDummyWGLDrawable drawable; + private WindowsWGLContext context; + private boolean canCreateGLPbuffer; + + SharedResource(WindowsDummyWGLDrawable draw, WindowsWGLContext ctx, boolean canPbuffer) { + drawable = draw; + context = ctx; + canCreateGLPbuffer = canPbuffer; + } + } + HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); + WindowsGraphicsDevice defaultDevice; + + public final AbstractGraphicsDevice getDefaultDevice() { + return defaultDevice; + } - protected final GLDrawableImpl getSharedDrawable() { - return sharedDrawable; + public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) { + if(device instanceof WindowsGraphicsDevice) { + return true; + } + return false; } - protected final GLContextImpl getSharedContext() { - return sharedContext; + HashSet devicesTried = new HashSet(); + private final boolean getDeviceTried(String connection) { + synchronized(devicesTried) { + return devicesTried.contains(connection); + } + } + private final void addDeviceTried(String connection) { + synchronized(devicesTried) { + devicesTried.add(connection); + } + } + + protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) { + String connection = device.getConnection(); + SharedResource sr; + synchronized(sharedMap) { + sr = (SharedResource) sharedMap.get(connection); + } + if(null==sr && !getDeviceTried(connection)) { + addDeviceTried(connection); + NativeWindowFactory.getDefaultToolkitLock().lock(); // OK + try { + WindowsDummyWGLDrawable sharedDrawable = new WindowsDummyWGLDrawable(this, null); + WindowsWGLContext ctx = (WindowsWGLContext) sharedDrawable.createContext(null); + ctx.makeCurrent(); + boolean canCreateGLPbuffer = ctx.getGL().isExtensionAvailable("GL_ARB_pbuffer"); + ctx.release(); + sr = new SharedResource(sharedDrawable, ctx, canCreateGLPbuffer); + synchronized(sharedMap) { + sharedMap.put(device.getConnection(), sr); + } + if (DEBUG) { + System.err.println("!!! SharedContext: "+ctx+", pbuffer supported "+canCreateGLPbuffer); + } + + } catch (Throwable t) { + throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources", t); + } finally { + NativeWindowFactory.getDefaultToolkitLock().unlock(); // OK + } + } + if(null!=sr) { + return sr.context; + } + return null; } protected void shutdownInstance() { - if (DEBUG) { + if (DEBUG) { + Exception e = new Exception("Debug"); + e.printStackTrace(); + } + Collection/*<SharedResource>*/ sharedResources = sharedMap.values(); + for(Iterator iter=sharedResources.iterator(); iter.hasNext(); ) { + SharedResource sr = (SharedResource) iter.next(); + + if (DEBUG) { System.err.println("!!! Shutdown Shared:"); - System.err.println("!!! CTX : "+sharedContext); - System.err.println("!!! Drawable: "+sharedDrawable); - Exception e = new Exception("Debug"); - e.printStackTrace(); - } - // don't free native resources from this point on, - // since we might be in a critical shutdown hook sequence - if(null!=sharedContext) { - // may cause deadlock: sharedContext.destroy(); // implies release, if current - sharedContext=null; - } - if(null!=sharedDrawable) { - // may cause deadlock: sharedDrawable.destroy(); - sharedDrawable=null; - } + System.err.println("!!! Drawable: "+sr.drawable); + System.err.println("!!! CTX : "+sr.context); + } + + if (null != sr.context) { + // may cause JVM SIGSEGV: sharedContext.destroy(); + sr.context = null; + } + + if (null != sr.drawable) { + // may cause JVM SIGSEGV: sharedDrawable.destroy(); + sr.drawable = null; + } + + } + sharedMap.clear(); } protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { @@ -154,13 +210,29 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { - return canCreateGLPbuffer; + SharedResource sr; + synchronized(sharedMap) { + sr = (SharedResource) sharedMap.get(device.getConnection()); + } + if(null!=sr) { + return sr.canCreateGLPbuffer; + } + return false; } protected GLDrawableImpl createGLPbufferDrawableImpl(final NativeSurface target) { if (target == null) { throw new IllegalArgumentException("Null target"); } + final AbstractGraphicsDevice device = target.getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + + final SharedResource sr; + synchronized(sharedMap) { + sr = (SharedResource) sharedMap.get(device.getConnection()); + } + if(null==sr) { + return null; + } final List returnList = new ArrayList(); Runnable r = new Runnable() { public void run() { @@ -168,16 +240,16 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { if (lastContext != null) { lastContext.release(); } - synchronized(WindowsWGLDrawableFactory.this.sharedContext) { - WindowsWGLDrawableFactory.this.sharedContext.makeCurrent(); + synchronized(sr.context) { + sr.context.makeCurrent(); try { - WGLExt wglExt = WindowsWGLDrawableFactory.this.sharedContext.getWGLExt(); + WGLExt wglExt = sr.context.getWGLExt(); GLDrawableImpl pbufferDrawable = new WindowsPbufferWGLDrawable(WindowsWGLDrawableFactory.this, target, - WindowsWGLDrawableFactory.this.sharedDrawable, + sr.drawable, wglExt); returnList.add(pbufferDrawable); } finally { - WindowsWGLDrawableFactory.this.sharedContext.release(); + sr.context.release(); if (lastContext != null) { lastContext.makeCurrent(); } diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java index 8744b7a37..619034da4 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -65,7 +65,7 @@ public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguratio throw new GLException("Invalid pixelformat id "+pfdID); } if(null==glp) { - glp = GLProfile.getDefault(); + glp = GLProfile.getDefault(screen.getDevice()); } PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); if (GDI.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index 317751725..d34467fb1 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -98,8 +98,13 @@ public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfiguratio throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); } - boolean choosenBywGLPixelFormat = false; WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); + WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); + if(null==sharedContext) { + throw new InternalError("SharedContext is null: "+device); + } + boolean choosenBywGLPixelFormat = false; GLCapabilities capabilities = (GLCapabilities) config.getRequestedCapabilities(); boolean onscreen = capabilities.isOnscreen(); boolean usePBuffer = capabilities.isPBuffer(); @@ -138,12 +143,11 @@ public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfiguratio // Produce a recommended pixel format selection for the GLCapabilitiesChooser. // Use wglChoosePixelFormatARB if user requested multisampling and if we have it available int recommendedPixelFormat = pixelFormat; // 1-based pixel format - boolean gotAvailableCaps = false; - synchronized(factory.sharedContext) { - factory.sharedContext.makeCurrent(); + boolean gotAvailableCaps = false; + synchronized(sharedContext) { + sharedContext.makeCurrent(); try { - WGLExt wglExt = factory.sharedContext.getWGLExt(); - + WGLExt wglExt = sharedContext.getWGLExt(); boolean haveWGLChoosePixelFormatARB = false; if (wglExt != null) { haveWGLChoosePixelFormatARB = wglExt.isExtensionAvailable("WGL_ARB_pixel_format"); @@ -198,7 +202,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfiguratio } } } finally { - factory.sharedContext.release(); + sharedContext.release(); } } // synchronized(factory.sharedContext) diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java index d80da1dd4..75e523cbc 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java @@ -48,14 +48,15 @@ import com.jogamp.opengl.impl.*; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; import com.jogamp.nativewindow.impl.x11.X11Util; +import javax.media.nativewindow.x11.X11GraphicsDevice; public abstract class X11GLXContext extends GLContextImpl { protected static final boolean TRACE_CONTEXT_CURRENT = false; // true; - private boolean glXQueryExtensionsStringInitialized; - private boolean glXQueryExtensionsStringAvailable; private static final Map/*<String, String>*/ functionNameMap; private static final Map/*<String, String>*/ extensionNameMap; + private boolean glXQueryExtensionsStringInitialized; + private boolean glXQueryExtensionsStringAvailable; private GLXExt glXExt; // Table that holds the addresses of the native C-language entry points for // GLX extension functions. @@ -87,6 +88,15 @@ public abstract class X11GLXContext extends GLContextImpl { this(drawable, null, shareWith); } + protected void resetState() { + glXQueryExtensionsStringInitialized=false; + glXQueryExtensionsStringAvailable=false; + // no inner state glXExt=null; + glXExtProcAddressTable = null; + hasSwapIntervalSGI = 0; + isDirect = false; + } + public final ProcAddressTable getPlatformExtProcAddressTable() { return getGLXExtProcAddressTable(); } @@ -145,13 +155,15 @@ public abstract class X11GLXContext extends GLContextImpl { X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl(); X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - long display = config.getScreen().getDevice().getHandle(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); + X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContextImpl(device); + long display = device.getHandle(); GLXExt glXExt; - if(null==factory.getSharedContext()) { + if(null==sharedContext) { glXExt = getGLXExt(); } else { - glXExt = ((X11GLXContext)factory.getSharedContext()).getGLXExt(); + glXExt = sharedContext.getGLXExt(); } boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; @@ -192,7 +204,11 @@ public abstract class X11GLXContext extends GLContextImpl { } try { + // critical path, a remote display might not support this command, + // hence we need to catch the X11 Error within this block. + X11Util.XSync(display, false); ctx = glXExt.glXCreateContextAttribsARB(display, config.getFBConfig(), share, direct, attribs, 0); + X11Util.XSync(display, false); } catch (RuntimeException re) { if(DEBUG) { Throwable t = new Throwable("Info: X11GLXContext.createContextARBImpl glXCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re); @@ -210,8 +226,10 @@ public abstract class X11GLXContext extends GLContextImpl { ctx = 0; } else { if (DEBUG) { - System.err.println(getThreadName() + ": createContextARBImpl: OK "+getGLVersion(major, minor, ctp, "@creation")+", share "+share+", direct "+direct+", hasSharedContext "+(null!=factory.getSharedContext())); + System.err.println(getThreadName() + ": createContextARBImpl: OK "+getGLVersion(major, minor, ctp, "@creation")+", share "+share+", direct "+direct+", hasSharedContext "+(null!=sharedContext)); } + // the following is issued by the caller 'GLContextImpl.createContextARB()' + // setGLFunctionAvailability(true, major, minor, ctp); } } else if (DEBUG) { System.err.println(getThreadName() + ": createContextARBImpl: NO "+getGLVersion(major, minor, ctp, "@creation")); @@ -236,7 +254,9 @@ public abstract class X11GLXContext extends GLContextImpl { X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl(); X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - long display = config.getScreen().getDevice().getHandle(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); + X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContextImpl(device); + long display = device.getHandle(); X11GLXContext other = (X11GLXContext) GLContextShareSet.getShareContext(this); long share = 0; @@ -250,7 +270,7 @@ public abstract class X11GLXContext extends GLContextImpl { GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); GLProfile glp = glCaps.getGLProfile(); - isVendorATI = factory.isVendorATI(); + isVendorATI = factory.isVendorATI(device); if(config.getFBConfigID()<0) { // not able to use FBConfig @@ -278,7 +298,7 @@ public abstract class X11GLXContext extends GLContextImpl { boolean createContextARBTried = false; // utilize the shared context's GLXExt in case it was using the ARB method and it already exists - if(null!=factory.getSharedContext() && factory.getSharedContext().isCreatedWithARBMethod()) { + if(null!=sharedContext && sharedContext.isCreatedWithARBMethod()) { contextHandle = createContextARB(share, direct, major, minor, ctp); createContextARBTried = true; if (DEBUG && 0!=contextHandle) { @@ -298,16 +318,24 @@ public abstract class X11GLXContext extends GLContextImpl { throw new GLException("Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable); } setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + boolean isCreateContextAttribsARBAvailable = isFunctionAvailable("glXCreateContextAttribsARB"); glXMakeContextCurrent(display, 0, 0, 0); // release temp context - if( !createContextARBTried && - isFunctionAvailable("glXCreateContextAttribsARB") && - isExtensionAvailable("GLX_ARB_create_context") ) { - // initial ARB context creation - contextHandle = createContextARB(share, direct, major, minor, ctp); - createContextARBTried=true; - if (DEBUG && 0!=contextHandle) { - System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+share); + if( !createContextARBTried ) { + if ( isCreateContextAttribsARBAvailable && + isExtensionAvailable("GLX_ARB_create_context") ) { + // initial ARB context creation + contextHandle = createContextARB(share, direct, major, minor, ctp); + createContextARBTried=true; + if (DEBUG) { + if(0!=contextHandle) { + System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+share); + } else { + System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+share); + } + } + } else if (DEBUG) { + System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+share); } } } @@ -407,36 +435,34 @@ public abstract class X11GLXContext extends GLContextImpl { // Should check for X errors and raise GLException } - protected void updateGLProcAddressTable(int major, int minor, int ctp) { + protected final void updateGLXProcAddressTable(int major, int minor, int ctp) { if (DEBUG) { System.err.println(getThreadName() + ": !!! Initializing GLX extension address table"); } glXQueryExtensionsStringInitialized = false; glXQueryExtensionsStringAvailable = false; - int key = compose8bit(major, minor, ctp, 0); GLXExtProcAddressTable table = null; - synchronized(mappedProcAddressLock) { - table = (GLXExtProcAddressTable) mappedGLXProcAddress.get( key ); + synchronized(mappedContextTypeObjectLock) { + table = (GLXExtProcAddressTable) mappedGLXProcAddress.get( contextFQN ); } if(null != table) { glXExtProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GLX ProcAddressTable reusing key("+major+","+minor+","+ctp+") -> "+table.hashCode()); + System.err.println(getThreadName() + ": !!! GLContext GLX ProcAddressTable reusing key("+contextFQN+") -> "+table.hashCode()); } } else { if (glXExtProcAddressTable == null) { glXExtProcAddressTable = new GLXExtProcAddressTable(new GLProcAddressResolver()); } resetProcAddressTable(getGLXExtProcAddressTable()); - synchronized(mappedProcAddressLock) { - mappedGLXProcAddress.put(key, getGLXExtProcAddressTable()); + synchronized(mappedContextTypeObjectLock) { + mappedGLXProcAddress.put(contextFQN, getGLXExtProcAddressTable()); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GLX ProcAddressTable mapping key("+major+","+minor+","+ctp+") -> "+getGLXExtProcAddressTable().hashCode()); + System.err.println(getThreadName() + ": !!! GLContext GLX ProcAddressTable mapping key("+contextFQN+") -> "+getGLXExtProcAddressTable().hashCode()); } } } - super.updateGLProcAddressTable(major, minor, ctp); } public synchronized String getPlatformExtensionsString() { @@ -476,8 +502,8 @@ public abstract class X11GLXContext extends GLContextImpl { try { hasSwapIntervalSGI = glXExt.isExtensionAvailable("GLX_SGI_swap_control")?1:-1; } catch (Throwable t) { hasSwapIntervalSGI=1; } - } - if (hasSwapIntervalSGI>0) { + } + if (hasSwapIntervalSGI>0) { try { if( 0 == glXExt.glXSwapIntervalSGI(interval) ) { currentSwapInterval = interval; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java index 5b5c07a61..7efbc6ed7 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java @@ -47,6 +47,10 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.*; import com.jogamp.nativewindow.impl.ProxySurface; import com.jogamp.nativewindow.impl.x11.*; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { @@ -83,43 +87,61 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } catch (JogampRuntimeException jre) { /* n/a .. */ } } + defaultDevice = new X11GraphicsDevice(X11Util.getNullDisplayName()); + // Init shared resources via own thread // Will be released via ShutdownHook sharedResourcesRunner = new SharedResourcesRunner(); sharedResourcesThread = new Thread(sharedResourcesRunner, Thread.currentThread().getName()+"-SharedResourcesRunner"); sharedResourcesThread.setDaemon(true); // Allow JVM to exit, even if this one is running sharedResourcesThread.start(); - sharedResourcesRunner.waitUntilInitialized(); - - if (DEBUG) { - System.err.println("!!! Vendor: "+vendorName+", ATI: "+isVendorATI+", NV: "+isVendorNVIDIA); - System.err.println("!!! SharedScreen: "+sharedScreen); - System.err.println("!!! SharedContext: "+sharedContext); - } } class SharedResourcesRunner implements Runnable { - boolean initialized = false; + boolean ready = false; boolean released = false; boolean shouldRelease = false; + String initConnection = null; + SharedResource result = null; - public void waitUntilInitialized() { + public final void initializeAndWait(String connection) { + // wait until thread becomes ready to init new device, + // pass the device and release the sync + String threadName = Thread.currentThread().getName(); + if (DEBUG) { + System.err.println(threadName+ " initializeAndWait START: "+connection); + } synchronized (this) { - while (!this.initialized) { + while (!ready) { try { this.wait(); - } catch (InterruptedException ex) { - } + } catch (InterruptedException ex) { } + } + if (DEBUG) { + System.err.println(threadName+ " initializeAndWait set command: "+connection); + } + initConnection = connection; + this.notifyAll(); + + // wait until thread has initialized the device + while (!ready || null != initConnection) { + try { + this.wait(); + } catch (InterruptedException ex) { } + } + if (DEBUG) { + System.err.println(threadName+ " initializeAndWait done: "+connection); } } + // done } - public void releaseAndWait() { + public final void releaseAndWait() { synchronized (this) { - this.shouldRelease = true; + shouldRelease = true; this.notifyAll(); - while (!this.released) { + while (!released) { try { this.wait(); } catch (InterruptedException ex) { @@ -128,118 +150,244 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } } - public void run() { + public final void run() { String threadName = Thread.currentThread().getName(); - X11GraphicsDevice sharedDevice; + synchronized (this) { if (DEBUG) { - System.err.println(threadName+ " initializing START"); + System.err.println(threadName+ " STARTED -> ready"); } - sharedDevice = new X11GraphicsDevice(X11Util.createDisplay(null)); - sharedDevice.setCloseDisplay(true); - X11Util.lockDefaultToolkit(sharedDevice.getHandle()); // OK - try { - vendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); - isVendorATI = GLXUtil.isVendorATI(vendorName); - isVendorNVIDIA = GLXUtil.isVendorNVIDIA(vendorName); - sharedScreen = new X11GraphicsScreen(sharedDevice, 0); - sharedDrawable = new X11DummyGLXDrawable(sharedScreen, X11GLXDrawableFactory.this, GLProfile.getDefault()); - if (null == sharedScreen || null == sharedDrawable) { - throw new GLException("Couldn't init shared screen(" + sharedScreen + ")/drawable(" + sharedDrawable + ")"); - } + + while (!shouldRelease) { try { - X11GLXContext ctx = (X11GLXContext) sharedDrawable.createContext(null); - ctx.makeCurrent(); - ctx.release(); - sharedContext = ctx; - } catch (Throwable t) { - throw new GLException("X11GLXDrawableFactory - Could not initialize shared resources", t); - } - if (null == sharedContext) { - throw new GLException("X11GLXDrawableFactory - Shared Context is null"); + // wait for stop or init + ready = true; + this.wait(); + } catch (InterruptedException ex) { } + ready = false; + + if(!shouldRelease && null!=initConnection) { + if (DEBUG) { + System.err.println(threadName+ " create Shared for: "+initConnection); + } + SharedResource sr = createSharedResource(initConnection); + if(null!=sr) { + synchronized(sharedMap) { + sharedMap.put(initConnection, sr); + } + } + if (DEBUG) { + String msg = "Info: (" + threadName + ") initializedSharedResource for device connection: "+initConnection+" -> ready"; + System.err.println(msg); + Throwable t = new Throwable(msg); + t.printStackTrace(); + } } - } finally { - X11Util.unlockDefaultToolkit(sharedDevice.getHandle()); // OK + initConnection = null; + notifyAll(); } if (DEBUG) { - System.err.println(threadName+ " initializing DONE"); + System.err.println(threadName+ " release START"); + } + + releaseSharedResources(); + + if (DEBUG) { + System.err.println(threadName+ " release END"); } - initialized = true; + + released = true; + ready = false; notifyAll(); } - - if (DEBUG) { - System.err.println(threadName+ " release WAIT"); + } + + private final SharedResource createSharedResource(String connection) { + X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.createDisplay(connection)); + sharedDevice.setCloseDisplay(true); + X11Util.lockDefaultToolkit(sharedDevice.getHandle()); // OK + try { + String vendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); + X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0); + X11DummyGLXDrawable sharedDrawable = new X11DummyGLXDrawable(sharedScreen, X11GLXDrawableFactory.this, GLProfile.getDefault(sharedDevice)); + if (null == sharedScreen || null == sharedDrawable) { + throw new GLException("Couldn't init shared screen(" + sharedScreen + ")/drawable(" + sharedDrawable + ")"); + } + X11GLXContext sharedContext; + try { + X11GLXContext ctx = (X11GLXContext) sharedDrawable.createContext(null); + ctx.makeCurrent(); + ctx.release(); + sharedContext = ctx; + } catch (Throwable t) { + throw new GLException("X11GLXDrawableFactory - Could not initialize shared resources", t); + } + if (null == sharedContext) { + throw new GLException("X11GLXDrawableFactory - Shared Context is null"); + } + if (DEBUG) { + System.err.println("!!! SharedDevice: "+sharedDevice); + System.err.println("!!! SharedScreen: "+sharedScreen); + System.err.println("!!! SharedContext: "+sharedContext); + System.err.println("!!! Vendor: "+vendorName); + } + return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext, vendorName); + } finally { + X11Util.unlockDefaultToolkit(sharedDevice.getHandle()); // OK } + } + + private final void releaseSharedResources() { + Collection/*<SharedResource>*/ sharedResources = sharedMap.values(); + for(Iterator iter=sharedResources.iterator(); iter.hasNext(); ) { + SharedResource sr = (SharedResource) iter.next(); - synchronized(this) { - while (!this.shouldRelease) { - try { - this.wait(); - } catch (InterruptedException ex) { - } - } if (DEBUG) { - System.err.println(threadName+ " release START"); + System.err.println("!!! Shutdown Shared:"); + System.err.println("!!! Device : "+sr.device); + System.err.println("!!! Screen : "+sr.screen); + System.err.println("!!! Drawable: "+sr.drawable); + System.err.println("!!! CTX : "+sr.context); } - if (null != sharedContext) { + + if (null != sr.context) { // may cause JVM SIGSEGV: sharedContext.destroy(); - sharedContext = null; + sr.context = null; } - if (null != sharedDrawable) { + if (null != sr.drawable) { // may cause JVM SIGSEGV: sharedDrawable.destroy(); - sharedDrawable = null; - } - - if (null != sharedScreen) { - sharedScreen = null; + sr.drawable = null; } - if (null != sharedDevice) { - sharedDevice.close(); - sharedDevice = null; + if (null != sr.screen) { + sr.screen = null; } - if (DEBUG) { - System.err.println(threadName+ " release END"); + if (null != sr.device) { + sr.device.close(); + sr.device=null; } - released = true; - notifyAll(); } + sharedMap.clear(); } } - Thread sharedResourcesThread = null; SharedResourcesRunner sharedResourcesRunner=null; - private X11GraphicsScreen sharedScreen=null; - private X11DummyGLXDrawable sharedDrawable=null; - private X11GLXContext sharedContext=null; - private String vendorName; - private boolean isVendorATI; - private boolean isVendorNVIDIA; - - protected String getVendorName() { return vendorName; } - protected boolean isVendorATI() { return isVendorATI; } - protected boolean isVendorNVIDIA() { return isVendorNVIDIA; } - - protected final GLDrawableImpl getSharedDrawable() { - return sharedDrawable; + + static class SharedResource { + private X11GraphicsDevice device; + private X11GraphicsScreen screen; + private X11DummyGLXDrawable drawable; + private X11GLXContext context; + private String vendorName; + private boolean isVendorATI; + private boolean isVendorNVIDIA; + + SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn, X11DummyGLXDrawable draw, X11GLXContext ctx, String vendor) { + device = dev; + screen = scrn; + drawable = draw; + context = ctx; + vendorName = vendor; + isVendorATI = GLXUtil.isVendorATI(vendorName); + isVendorNVIDIA = GLXUtil.isVendorNVIDIA(vendorName); + } } + HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); + SharedResource defaultShare; + X11GraphicsDevice defaultDevice; - protected final GLContextImpl getSharedContext() { - return sharedContext; + public final AbstractGraphicsDevice getDefaultDevice() { + return defaultDevice; } - protected void shutdownInstance() { + public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) { + if(device instanceof X11GraphicsDevice) { + return true; + } + return false; + } + + HashSet devicesTried = new HashSet(); + private final boolean getDeviceTried(String connection) { + synchronized(devicesTried) { + return devicesTried.contains(connection); + } + } + private final void addDeviceTried(String connection) { + synchronized(devicesTried) { + devicesTried.add(connection); + } + } + + protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) { + String connection = device.getConnection(); + boolean deviceTried = getDeviceTried(connection); + SharedResource sr; + synchronized(sharedMap) { + sr = (SharedResource) sharedMap.get(connection); + } + if (DEBUG) { - System.err.println("!!! Shutdown Shared:"); - System.err.println("!!! CTX : "+sharedContext); - System.err.println("!!! Drawable: "+sharedDrawable); - System.err.println("!!! Screen : "+sharedScreen); + System.err.println("getOrCreateSharedContext() "+connection+": has shared "+(null!=sr)+", already tried "+deviceTried); } + if(null==sr && !deviceTried) { + if (DEBUG) { + System.err.println("getOrCreateSharedContext() "+connection+": trying"); + } + addDeviceTried(connection); + sharedResourcesRunner.initializeAndWait(connection); + synchronized(sharedMap) { + sr = (SharedResource) sharedMap.get(connection); + } + if(DEBUG) { + Throwable t = new Throwable("getOrCreateSharedContextImpl() "+connection+": done"); + t.printStackTrace(); + } + } + if(null!=sr) { + return sr.context; + } + return null; + } + + protected final String getVendorName(AbstractGraphicsDevice device) { + SharedResource sr; + synchronized(sharedMap) { + sr = (SharedResource) sharedMap.get(device.getConnection()); + } + if(null!=sr) { + return sr.vendorName; + } + return null; + } + + protected final boolean isVendorATI(AbstractGraphicsDevice device) { + SharedResource sr; + synchronized(sharedMap) { + sr = (SharedResource) sharedMap.get(device.getConnection()); + } + if(null!=sr) { + return sr.isVendorATI; + } + return false; + } + + protected final boolean isVendorNVIDIA(AbstractGraphicsDevice device) { + SharedResource sr; + synchronized(sharedMap) { + sr = (SharedResource) sharedMap.get(device.getConnection()); + } + if(null!=sr) { + return sr.isVendorNVIDIA; + } + return false; + } + + protected void shutdownInstance() { sharedResourcesRunner.releaseAndWait(); X11Util.shutdown( true, DEBUG ); @@ -268,7 +416,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { protected final boolean glxVersionGreaterEqualThan(AbstractGraphicsDevice device, int majorReq, int minorReq) { if (!glxVersionsQueried) { if(null == device) { - device = (X11GraphicsDevice) sharedScreen.getDevice(); + device = (X11GraphicsDevice) defaultShare.screen.getDevice(); } if(null == device) { throw new GLException("FIXME: No AbstractGraphicsDevice (passed or shared-device"); @@ -302,19 +450,26 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { GLDrawableImpl pbufferDrawable; + AbstractGraphicsConfiguration config = target.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); + /** * Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277, * we need to have a context current on the same Display to create a PBuffer. * The dummy context shall also use the same Display, * since switching Display in this regard is another ATI bug. */ - if( isVendorATI() && null == GLContext.getCurrent() ) { - synchronized(sharedContext) { - sharedContext.makeCurrent(); + SharedResource sr; + synchronized(sharedMap) { + sr = (SharedResource) sharedMap.get(device.getConnection()); + } + if( sr.isVendorATI && null == GLContext.getCurrent() ) { + synchronized(sr.context) { + sr.context.makeCurrent(); try { pbufferDrawable = new X11PbufferGLXDrawable(this, target); } finally { - sharedContext.release(); + sr.context.release(); } } } else { @@ -325,7 +480,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { protected NativeSurface createOffscreenSurfaceImpl(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { - ProxySurface ns = new ProxySurface(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capabilities, chooser, sharedScreen)); + ProxySurface ns = new ProxySurface( + X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capabilities, chooser, defaultShare.screen)); if(ns != null) { ns.setSize(width, height); } @@ -364,7 +520,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { return gammaRampLength; } - long display = sharedScreen.getDevice().getHandle(); + long display = defaultShare.screen.getDevice().getHandle(); int[] size = new int[1]; boolean res = X11Util.XF86VidModeGetGammaRampSize(display, @@ -385,7 +541,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { rampData[i] = (short) (ramp[i] * 65535); } - long display = sharedScreen.getDevice().getHandle(); + long display = defaultShare.screen.getDevice().getHandle(); boolean res = X11Util.XF86VidModeSetGammaRamp(display, X11Util.DefaultScreen(display), rampData.length, @@ -407,7 +563,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { rampData.position(2 * size); rampData.limit(3 * size); ShortBuffer blueRampData = rampData.slice(); - long display = sharedScreen.getDevice().getHandle(); + long display = defaultShare.screen.getDevice().getHandle(); boolean res = X11Util.XF86VidModeGetGammaRamp(display, X11Util.DefaultScreen(display), size, @@ -438,7 +594,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { rampData.position(2 * size); rampData.limit(3 * size); ShortBuffer blueRampData = rampData.slice(); - long display = sharedScreen.getDevice().getHandle(); + long display = defaultShare.screen.getDevice().getHandle(); X11Util.XF86VidModeSetGammaRamp(display, X11Util.DefaultScreen(display), size, diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java index 3df9ee541..8661fba5e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java @@ -67,7 +67,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem throw new GLException("FBConfig null of "+toHexString(fbcfgID)); } if(null==glp) { - glp = GLProfile.getDefault(); + glp = GLProfile.getDefault(x11Screen.getDevice()); } GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, GLXUtil.isMultisampleAvailable(display)); if(null==caps) { |