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 | |
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.
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; |