diff options
author | Sven Gothel <[email protected]> | 2010-12-11 06:41:00 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-12-11 06:41:00 +0100 |
commit | c8807f6847e34d599b8bc9a476c84785e1925c8a (patch) | |
tree | cd1703bf757f864daaf9335a8a387fe88b0b7bc6 /src | |
parent | 74fb7ca7ac8484e86ff6c84a5e3ceef79fb4d0d6 (diff) |
Generalize SharedResourceRunner and use/impl it for WGL as well (besides X11).
It seems necessary to use off thread shared resources (dummy window, drawable and context)
to keep them alive in Java Webstart.
Diffstat (limited to 'src')
3 files changed, 521 insertions, 368 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/SharedResourceRunner.java b/src/jogl/classes/com/jogamp/opengl/impl/SharedResourceRunner.java new file mode 100644 index 000000000..1ea83f84a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/SharedResourceRunner.java @@ -0,0 +1,244 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.impl; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; + +public class SharedResourceRunner implements Runnable { + protected static final boolean DEBUG = GLDrawableImpl.DEBUG; + + public static interface Resource { + AbstractGraphicsDevice getDevice(); + AbstractGraphicsScreen getScreen(); + GLDrawableImpl getDrawable(); + GLContextImpl getContext(); + } + + public static interface Implementation { + Resource createSharedResource(String connection); + void releaseSharedResource(Resource shared); + void clear(); + + Resource mapPut(String connection, Resource resource); + Resource mapGet(String connection); + Collection/*<Resource>*/ mapValues(); + } + + Implementation impl = null; + + boolean ready = false; + boolean released = false; + boolean shouldRelease = false; + String initConnection = null; + String releaseConnection = null; + + HashSet devicesTried = new HashSet(); + + private boolean getDeviceTried(String connection) { + synchronized (devicesTried) { + return devicesTried.contains(connection); + } + } + private void addDeviceTried(String connection) { + synchronized (devicesTried) { + devicesTried.add(connection); + } + } + private void removeDeviceTried(String connection) { + synchronized (devicesTried) { + devicesTried.remove(connection); + } + } + + public SharedResourceRunner(Implementation impl) { + this.impl = impl; + } + + public SharedResourceRunner.Resource getOrCreateShared(AbstractGraphicsDevice device) { + String connection = device.getConnection(); + SharedResourceRunner.Resource sr = impl.mapGet(connection); + + if (null == sr && !getDeviceTried(connection)) { + addDeviceTried(connection); + if (DEBUG) { + System.err.println("getOrCreateShared() " + connection + ": trying"); + } + doAndWait(connection, null); + sr = impl.mapGet(connection); + if (DEBUG) { + Throwable t = new Throwable("getOrCreateSharedl() " + connection + ": done"); + t.printStackTrace(); + } + } + return sr; + } + + public SharedResourceRunner.Resource releaseShared(AbstractGraphicsDevice device) { + String connection = device.getConnection(); + SharedResourceRunner.Resource sr = impl.mapGet(connection); + + if (null != sr) { + removeDeviceTried(connection); + if (DEBUG) { + System.err.println("releaseShared() " + connection + ": trying"); + } + doAndWait(null, connection); + if (DEBUG) { + Throwable t = new Throwable("releaseSharedl() " + connection + ": done"); + t.printStackTrace(); + } + } + return sr; + } + + private final void doAndWait(String initConnection, String releaseConnection) { + // 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 + " doAndWait START init: " + initConnection + ", release: "+releaseConnection); + } + synchronized (this) { + while (!ready) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + if (DEBUG) { + System.err.println(threadName + " initializeAndWait set command init: " + initConnection + ", release: "+releaseConnection); + } + this.initConnection = initConnection; + this.releaseConnection = releaseConnection; + this.notifyAll(); + + // wait until thread has init/released the device + while (!ready || null != this.initConnection || null != this.releaseConnection) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + if (DEBUG) { + System.err.println(threadName + " initializeAndWait END init: " + initConnection + ", release: "+releaseConnection); + } + } + // done + } + + public final void releaseAndWait() { + synchronized (this) { + shouldRelease = true; + this.notifyAll(); + + while (!released) { + try { + this.wait(); + } catch (InterruptedException ex) { + } + } + } + } + + public final void run() { + String threadName = Thread.currentThread().getName(); + + if (DEBUG) { + System.err.println(threadName + " STARTED"); + } + + synchronized (this) { + while (!shouldRelease) { + try { + // wait for stop or init + ready = true; + if (DEBUG) { + System.err.println(threadName + " -> ready"); + } + notifyAll(); + this.wait(); + } catch (InterruptedException ex) { } + ready = false; + + if (!shouldRelease) { + if (DEBUG) { + System.err.println(threadName + " woke up for device connection init: " + initConnection + + ", release: " + releaseConnection); + } + if(null != initConnection) { + if (DEBUG) { + System.err.println(threadName + " create Shared for: " + initConnection); + } + Resource sr = impl.createSharedResource(initConnection); + if (null != sr) { + impl.mapPut(initConnection, sr); + } + } + if(null != releaseConnection) { + if (DEBUG) { + System.err.println(threadName + " release Shared for: " + releaseConnection); + } + Resource sr = impl.mapPut(releaseConnection, null); + if (null != sr) { + impl.releaseSharedResource(sr); + } + } + } + initConnection = null; + releaseConnection = null; + } + + if (DEBUG) { + System.err.println(threadName + " release START"); + } + + releaseSharedResources(); + + if (DEBUG) { + System.err.println(threadName + " release END"); + } + + released = true; + ready = false; + notifyAll(); + } + } + + private void releaseSharedResources() { + Collection/*<Resource>*/ sharedResources = impl.mapValues(); + for (Iterator iter = sharedResources.iterator(); iter.hasNext();) { + Resource sr = (Resource) iter.next(); + impl.releaseSharedResource(sr); + } + impl.clear(); + } +} 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 84636f539..4d687a00c 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 @@ -66,9 +66,11 @@ import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.impl.ProxySurface; import com.jogamp.nativewindow.impl.windows.GDI; import com.jogamp.opengl.impl.DesktopGLDynamicLookupHelper; +import com.jogamp.opengl.impl.GLContextImpl; import com.jogamp.opengl.impl.GLDrawableFactoryImpl; import com.jogamp.opengl.impl.GLDrawableImpl; import com.jogamp.opengl.impl.GLDynamicLookupHelper; +import com.jogamp.opengl.impl.SharedResourceRunner; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.opengl.GLCapabilitiesImmutable; @@ -108,32 +110,141 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } defaultDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + + // Init shared resources off thread + // Will be released via ShutdownHook + sharedResourceImpl = new SharedResourceImplementation(); + sharedResourceRunner = new SharedResourceRunner(sharedResourceImpl); + sharedResourceThread = new Thread(sharedResourceRunner, Thread.currentThread().getName()+"-SharedResourceRunner"); + sharedResourceThread.setDaemon(true); // Allow JVM to exit, even if this one is running + sharedResourceThread.start(); } - static class SharedResource { + WindowsGraphicsDevice defaultDevice; + SharedResourceImplementation sharedResourceImpl; + SharedResourceRunner sharedResourceRunner; + Thread sharedResourceThread; + HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); + + static class SharedResource implements SharedResourceRunner.Resource { private WindowsGraphicsDevice device; + private AbstractGraphicsScreen screen; private WindowsDummyWGLDrawable drawable; private WindowsWGLContext context; private boolean canCreateGLPbuffer; private boolean readDrawableAvailable; - SharedResource(WindowsGraphicsDevice dev, WindowsDummyWGLDrawable draw, WindowsWGLContext ctx, + SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, WindowsDummyWGLDrawable draw, WindowsWGLContext ctx, boolean readBufferAvail, boolean canPbuffer) { device = dev; + screen = scrn; drawable = draw; context = ctx; canCreateGLPbuffer = canPbuffer; readDrawableAvailable = readBufferAvail; } - WindowsGraphicsDevice getDevice() { return device; } - WindowsWGLDrawable getDrawable() { return drawable; } - WindowsWGLContext getContext() { return context; } + public AbstractGraphicsDevice getDevice() { return device; } + public AbstractGraphicsScreen getScreen() { return screen; } + public GLDrawableImpl getDrawable() { return drawable; } + public GLContextImpl getContext() { return context; } + boolean canCreateGLPbuffer() { return canCreateGLPbuffer; } boolean isReadDrawableAvailable() { return readDrawableAvailable; } + } + + class SharedResourceImplementation implements SharedResourceRunner.Implementation { + public void clear() { + synchronized(sharedMap) { + sharedMap.clear(); + } + } + public SharedResourceRunner.Resource mapPut(String connection, SharedResourceRunner.Resource resource) { + synchronized(sharedMap) { + return (SharedResourceRunner.Resource) sharedMap.put(connection, resource); + } + } + public SharedResourceRunner.Resource mapGet(String connection) { + synchronized(sharedMap) { + return (SharedResourceRunner.Resource) sharedMap.get(connection); + } + } + public Collection/*<Resource>*/ mapValues() { + synchronized(sharedMap) { + return sharedMap.values(); + } + } + + public SharedResourceRunner.Resource createSharedResource(String connection) { + WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT); + sharedDevice.lock(); + try { + AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0); + if (null == absScreen) { + throw new GLException("Couldn't create shared screen for device: "+sharedDevice+", idx 0"); + } + GLProfile glp = GLProfile.getDefault(sharedDevice); + if (null == glp) { + throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); + } + WindowsDummyWGLDrawable sharedDrawable = WindowsDummyWGLDrawable.create(WindowsWGLDrawableFactory.this, glp, absScreen); + if (null == sharedDrawable) { + throw new GLException("Couldn't create shared drawable for screen: "+absScreen+", "+glp); + } + WindowsWGLContext sharedContext = (WindowsWGLContext) sharedDrawable.createContext(null); + if (null == sharedContext) { + throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable); + } + sharedContext.setSynchronized(true); + sharedContext.makeCurrent(); + boolean canCreateGLPbuffer = sharedContext.getGL().isExtensionAvailable(GL_ARB_pbuffer); + boolean readDrawableAvailable = sharedContext.isExtensionAvailable(WGL_ARB_make_current_read) && + sharedContext.isFunctionAvailable(wglMakeContextCurrent); + sharedContext.release(); + if (DEBUG) { + System.err.println("!!! SharedDevice: " + sharedDevice); + System.err.println("!!! SharedScreen: " + absScreen); + System.err.println("!!! SharedContext: " + sharedContext); + System.err.println("!!! pbuffer avail: " + canCreateGLPbuffer); + System.err.println("!!! readDrawable: " + readDrawableAvailable); + } + return new SharedResource(sharedDevice, absScreen, sharedDrawable, sharedContext, readDrawableAvailable, canCreateGLPbuffer); + } catch (Throwable t) { + throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+connection, t); + } finally { + sharedDevice.unlock(); + } + } + + public void releaseSharedResource(SharedResourceRunner.Resource shared) { + SharedResource sr = (SharedResource) shared; + if (DEBUG) { + 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 != sr.context) { + // may cause JVM SIGSEGV: sharedContext.destroy(); + sr.context = null; + } + + if (null != sr.drawable) { + // may cause JVM SIGSEGV: sharedDrawable.destroy(); + sr.drawable = null; + } + + if (null != sr.screen) { + sr.screen = null; + } + if (null != sr.device) { + sr.device.close(); + sr.device = null; + } + } } - HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); - WindowsGraphicsDevice defaultDevice; public final AbstractGraphicsDevice getDefaultDevice() { return defaultDevice; @@ -146,62 +257,12 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { 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); - } - } - final static String GL_ARB_pbuffer = "GL_ARB_pbuffer"; final static String WGL_ARB_make_current_read = "WGL_ARB_make_current_read"; final static String wglMakeContextCurrent = "wglMakeContextCurrent"; - private SharedResource getOrCreateShared(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 { - WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT); - GLProfile glp = GLProfile.getDefault(/*sharedDevice*/); // can't fetch device profile, which shared resource we create here - AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0); - WindowsDummyWGLDrawable sharedDrawable = WindowsDummyWGLDrawable.create(this, glp, absScreen); - WindowsWGLContext ctx = (WindowsWGLContext) sharedDrawable.createContext(null); - ctx.setSynchronized(true); - ctx.makeCurrent(); - boolean canCreateGLPbuffer = ctx.getGL().isExtensionAvailable(GL_ARB_pbuffer); - boolean readDrawableAvailable = ctx.isExtensionAvailable(WGL_ARB_make_current_read) && - ctx.isFunctionAvailable(wglMakeContextCurrent); - if (DEBUG) { - System.err.println("!!! SharedContext: "+ctx+", pbuffer supported "+canCreateGLPbuffer+ - ", readDrawable supported "+readDrawableAvailable); - } - ctx.release(); - sr = new SharedResource(sharedDevice, sharedDrawable, ctx, readDrawableAvailable, canCreateGLPbuffer); - synchronized(sharedMap) { - sharedMap.put(connection, sr); - } - } catch (Throwable t) { - throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources", t); - } finally { - NativeWindowFactory.getDefaultToolkitLock().unlock(); // OK - } - } - return sr; - } - protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { return sr.getContext(); } @@ -209,7 +270,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { return sr.getDevice(); } @@ -217,43 +278,15 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } protected WindowsWGLDrawable getSharedDrawable(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { - return sr.getDrawable(); + return (WindowsWGLDrawable) sr.getDrawable(); } return null; } protected final void shutdownInstance() { - 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("!!! 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(); - if (DEBUG) { - System.err.println("!!! Shutdown Shared Finished"); - } + sharedResourceRunner.releaseAndWait(); } protected final GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { @@ -276,7 +309,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { // PBuffer GLDrawable Creation final AbstractGraphicsDevice device = config.getScreen().getDevice(); - final SharedResource sr = getOrCreateShared(device); + final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); if(null==sr) { throw new IllegalArgumentException("No shared resource for "+device); } @@ -287,19 +320,17 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { if (lastContext != null) { lastContext.release(); } - synchronized(sr.context) { - sr.context.makeCurrent(); - try { - GLDrawableImpl pbufferDrawable = new WindowsPbufferWGLDrawable(WindowsWGLDrawableFactory.this, target, - sr.drawable, - sr.context); - returnList.add(pbufferDrawable); - } finally { - sr.context.release(); - if (lastContext != null) { - lastContext.makeCurrent(); - } - } + sr.context.makeCurrent(); + try { + GLDrawableImpl pbufferDrawable = new WindowsPbufferWGLDrawable(WindowsWGLDrawableFactory.this, target, + sr.drawable, + sr.context); + returnList.add(pbufferDrawable); + } finally { + sr.context.release(); + if (lastContext != null) { + lastContext.makeCurrent(); + } } } }; @@ -312,7 +343,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { * and -1 if undefined yet, ie no shared device exist at this point. */ public final int isReadDrawableAvailable(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared((null!=device)?device:defaultDevice); + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice); if(null!=sr) { return sr.isReadDrawableAvailable() ? 1 : 0 ; } @@ -320,7 +351,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared((null!=device)?device:defaultDevice); + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice); if(null!=sr) { return sr.canCreateGLPbuffer(); } 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 7303e6e50..38294bf4f 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 @@ -49,8 +49,6 @@ 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 { @@ -90,205 +88,22 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { defaultDevice = new X11GraphicsDevice(X11Util.getNullDisplayName(), AbstractGraphicsDevice.DEFAULT_UNIT); - // Init shared resources via own thread + // Init shared resources off 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(); + sharedResourceImpl = new SharedResourceImplementation(); + sharedResourceRunner = new SharedResourceRunner(sharedResourceImpl); + sharedResourceThread = new Thread(sharedResourceRunner, Thread.currentThread().getName()+"-SharedResourceRunner"); + sharedResourceThread.setDaemon(true); // Allow JVM to exit, even if this one is running + sharedResourceThread.start(); } - class SharedResourcesRunner implements Runnable { - boolean ready = false; - boolean released = false; - boolean shouldRelease = false; - String initConnection = null; - SharedResource result = null; - - 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 (!ready) { - try { - this.wait(); - } 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 final void releaseAndWait() { - synchronized (this) { - shouldRelease = true; - this.notifyAll(); - - while (!released) { - try { - this.wait(); - } catch (InterruptedException ex) { - } - } - } - } - - public final void run() { - String threadName = Thread.currentThread().getName(); - - synchronized (this) { - if (DEBUG) { - System.err.println(threadName+ " STARTED -> ready"); - } - - while (!shouldRelease) { - try { - // 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(); - } - } - initConnection = null; - notifyAll(); - } - - if (DEBUG) { - System.err.println(threadName+ " release START"); - } - - releaseSharedResources(); - - if (DEBUG) { - System.err.println(threadName+ " release END"); - } - - released = true; - ready = false; - notifyAll(); - } - } - - private final SharedResource createSharedResource(String connection) { - X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.createDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT); - sharedDevice.setCloseDisplay(true); - sharedDevice.lock(); - try { - String glXVendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); - X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0); - X11DummyGLXDrawable sharedDrawable = X11DummyGLXDrawable.create(sharedScreen, X11GLXDrawableFactory.this, - GLProfile.getDefault(sharedDevice)); - if (null == sharedScreen || null == sharedDrawable) { - throw new GLException("Couldn't init shared screen(" + sharedScreen + ")/drawable(" + sharedDrawable + ")"); - } - X11GLXContext sharedContext; - VersionNumber glXVersion; - try { - X11GLXContext ctx = (X11GLXContext) sharedDrawable.createContext(null); - ctx.setSynchronized(true); - ctx.makeCurrent(); - { - int[] major = new int[1]; - int[] minor = new int[1]; - GLXUtil.getGLXVersion(sharedDevice.getHandle(), major, minor); - glXVersion = new VersionNumber(major[0], minor[0], 0); - } - 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("!!! GLX Vendor: "+glXVendorName); - System.err.println("!!! GLX Version: "+glXVersion + - " >= 1.3: " + ( glXVersion.compareTo(versionOneThree) >= 0 ) ); - } - return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext, glXVersion, glXVendorName); - } finally { - sharedDevice.unlock(); - } - } - - private final void releaseSharedResources() { - 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("!!! Device : "+sr.device); - System.err.println("!!! Screen : "+sr.screen); - 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; - } - - if (null != sr.screen) { - sr.screen = null; - } - - if (null != sr.device) { - sr.device.close(); - sr.device=null; - } - } - sharedMap.clear(); - } - } - Thread sharedResourcesThread = null; - SharedResourcesRunner sharedResourcesRunner=null; + X11GraphicsDevice defaultDevice; + SharedResourceImplementation sharedResourceImpl; + SharedResourceRunner sharedResourceRunner; + Thread sharedResourceThread; + HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); - static class SharedResource { + static class SharedResource implements SharedResourceRunner.Resource { X11GraphicsDevice device; X11GraphicsScreen screen; X11DummyGLXDrawable drawable; @@ -298,7 +113,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { boolean isGLXVendorNVIDIA; VersionNumber glXVersion; - SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn, + SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn, X11DummyGLXDrawable draw, X11GLXContext ctx, VersionNumber glXVer, String glXVendor) { device = dev; @@ -310,16 +125,117 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { isGLXVendorATI = GLXUtil.isVendorATI(glXVendorName); isGLXVendorNVIDIA = GLXUtil.isVendorNVIDIA(glXVendorName); } - X11GraphicsDevice getDevice() { return device; } - X11GraphicsScreen getScreen() { return screen; } - X11GLXContext getContext() { return context; } + public AbstractGraphicsDevice getDevice() { return device; } + public AbstractGraphicsScreen getScreen() { return screen; } + public GLDrawableImpl getDrawable() { return drawable; } + public GLContextImpl getContext() { return context; } + String getGLXVendorName() { return glXVendorName; } boolean isGLXVendorATI() { return isGLXVendorATI; } boolean isGLXVendorNVIDIA() { return isGLXVendorNVIDIA; } VersionNumber getGLXVersion() { return glXVersion; } } - HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); - X11GraphicsDevice defaultDevice; + + class SharedResourceImplementation implements SharedResourceRunner.Implementation { + public void clear() { + synchronized(sharedMap) { + sharedMap.clear(); + } + } + public SharedResourceRunner.Resource mapPut(String connection, SharedResourceRunner.Resource resource) { + synchronized(sharedMap) { + return (SharedResourceRunner.Resource) sharedMap.put(connection, resource); + } + } + public SharedResourceRunner.Resource mapGet(String connection) { + synchronized(sharedMap) { + return (SharedResourceRunner.Resource) sharedMap.get(connection); + } + } + public Collection/*<Resource>*/ mapValues() { + synchronized(sharedMap) { + return sharedMap.values(); + } + } + + public SharedResourceRunner.Resource createSharedResource(String connection) { + X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.createDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT); + sharedDevice.setCloseDisplay(true); + sharedDevice.lock(); + try { + String glXVendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); + X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0); + if (null == sharedScreen) { + throw new GLException("Couldn't create shared screen for device: "+sharedDevice+", idx 0"); + } + GLProfile glp = GLProfile.getDefault(sharedDevice); + if (null == glp) { + throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); + } + X11DummyGLXDrawable sharedDrawable = X11DummyGLXDrawable.create(sharedScreen, X11GLXDrawableFactory.this, glp); + if (null == sharedDrawable) { + throw new GLException("Couldn't create shared drawable for screen: "+sharedScreen+", "+glp); + } + X11GLXContext sharedContext = (X11GLXContext) sharedDrawable.createContext(null); + if (null == sharedContext) { + throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable); + } + sharedContext.setSynchronized(true); + sharedContext.makeCurrent(); + VersionNumber glXVersion; + { + int[] major = new int[1]; + int[] minor = new int[1]; + GLXUtil.getGLXVersion(sharedDevice.getHandle(), major, minor); + glXVersion = new VersionNumber(major[0], minor[0], 0); + } + sharedContext.release(); + if (DEBUG) { + System.err.println("!!! SharedDevice: " + sharedDevice); + System.err.println("!!! SharedScreen: " + sharedScreen); + System.err.println("!!! SharedContext: " + sharedContext); + System.err.println("!!! GLX Vendor: " + glXVendorName); + System.err.println("!!! GLX Version: " + glXVersion + + " >= 1.3: " + (glXVersion.compareTo(versionOneThree) >= 0)); + } + return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext, glXVersion, glXVendorName); + } catch (Throwable t) { + throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+connection, t); + } finally { + sharedDevice.unlock(); + } + } + + public void releaseSharedResource(SharedResourceRunner.Resource shared) { + SharedResource sr = (SharedResource) shared; + if (DEBUG) { + 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 != sr.context) { + // may cause JVM SIGSEGV: sharedContext.destroy(); + sr.context = null; + } + + if (null != sr.drawable) { + // may cause JVM SIGSEGV: sharedDrawable.destroy(); + sr.drawable = null; + } + + if (null != sr.screen) { + sr.screen = null; + } + + if (null != sr.device) { + sr.device.close(); + sr.device = null; + } + } + } public final AbstractGraphicsDevice getDefaultDevice() { return defaultDevice; @@ -332,44 +248,8 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { 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); - } - } - - private SharedResource getOrCreateShared(AbstractGraphicsDevice device) { - String connection = device.getConnection(); - SharedResource sr; - synchronized(sharedMap) { - sr = (SharedResource) sharedMap.get(connection); - } - - if(null==sr && !getDeviceTried(connection)) { - addDeviceTried(connection); - if (DEBUG) { - System.err.println("getOrCreateShared() "+connection+": trying"); - } - sharedResourcesRunner.initializeAndWait(connection); - synchronized(sharedMap) { - sr = (SharedResource) sharedMap.get(connection); - } - if(DEBUG) { - Throwable t = new Throwable("getOrCreateSharedl() "+connection+": done"); - t.printStackTrace(); - } - } - return sr; - } - protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { return sr.getContext(); } @@ -377,7 +257,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { return sr.getDevice(); } @@ -385,7 +265,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } protected final long getOrCreateSharedDpy(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { return sr.getDevice().getHandle(); } @@ -393,39 +273,39 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { } protected final VersionNumber getGLXVersion(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { - return sr.getGLXVersion(); + return ((SharedResource)sr).getGLXVersion(); } return null; } protected final String getGLXVendorName(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { - return sr.getGLXVendorName(); + return ((SharedResource)sr).getGLXVendorName(); } return GLXUtil.getVendorName(device.getHandle()); } protected final boolean isGLXVendorATI(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { - return sr.isGLXVendorATI(); + return ((SharedResource)sr).isGLXVendorATI(); } return GLXUtil.isVendorATI(device.getHandle()); } protected final boolean isGLXVendorNVIDIA(AbstractGraphicsDevice device) { - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { - return sr.isGLXVendorNVIDIA(); + return ((SharedResource)sr).isGLXVendorNVIDIA(); } return GLXUtil.isVendorNVIDIA(device.getHandle()); } protected final void shutdownInstance() { - sharedResourcesRunner.releaseAndWait(); + sharedResourceRunner.releaseAndWait(); // Don't really close pending Display connections, // since this may trigger a JVM exception @@ -459,15 +339,13 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { * The dummy context shall also use the same Display, * since switching Display in this regard is another ATI bug. */ - SharedResource sr = getOrCreateShared(device); + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); if( null!=sr && sr.isGLXVendorATI() && null == GLContext.getCurrent() ) { - synchronized(sr.context) { - sr.context.makeCurrent(); - try { - pbufferDrawable = new X11PbufferGLXDrawable(this, target); - } finally { - sr.context.release(); - } + sr.getContext().makeCurrent(); + try { + pbufferDrawable = new X11PbufferGLXDrawable(this, target); + } finally { + sr.getContext().release(); } } else { pbufferDrawable = new X11PbufferGLXDrawable(this, target); @@ -482,7 +360,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { if(null == device) { - SharedResource sr = getOrCreateShared(defaultDevice); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(defaultDevice); if(null!=sr) { device = sr.getDevice(); } @@ -495,9 +373,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { GLCapabilitiesChooser chooser, int width, int height) { X11GraphicsScreen screen = null; - SharedResource sr = getOrCreateShared(device); + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); if(null!=sr) { - screen = sr.getScreen(); + screen = (X11GraphicsScreen) sr.getScreen(); } if(null==screen) { return null; |