diff options
author | Sven Gothel <[email protected]> | 2011-10-13 13:02:32 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-10-13 13:02:32 +0200 |
commit | 5d33b0a3ef993ff2d257c90abc3d84bc93269cd0 (patch) | |
tree | b6a0a984ce20f8f57a37932476cde851ab31d72e /src/jogl/classes/jogamp/opengl/GLContextShareSet.java | |
parent | a8c14db739c8d7765d1a204f73b5708faac07fdd (diff) |
MacOSX: Fix shared ctx release [onMainThread]; Make GLContextShareSet lifecycle deterministic; Remove warnings
Fix shared ctx release [onMainThread]
- Releasing the shared contexts caused a freeze of about 10s from one of the shared release operations.
[NSOpenGLContext release]
- Thorough triage concluded the workaround to release the shared ctx on the main thread.
- Using enhanced GLContextShareSet, see below
Make GLContextShareSet lifecycle deterministic
- Programmatically control the lifecycle of tracked shared ctx allows us using 'hard' references.
- Features queries for isShared() and ofc unregister a share set if all are destroyed.
Remove warnings
- MacOSXWindowSystemInterface.m used 'long', where 'GLint' was requested.
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/GLContextShareSet.java')
-rw-r--r-- | src/jogl/classes/jogamp/opengl/GLContextShareSet.java | 252 |
1 files changed, 121 insertions, 131 deletions
diff --git a/src/jogl/classes/jogamp/opengl/GLContextShareSet.java b/src/jogl/classes/jogamp/opengl/GLContextShareSet.java index bbb46148c..b7acc0dff 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextShareSet.java +++ b/src/jogl/classes/jogamp/opengl/GLContextShareSet.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2011 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 @@ -39,39 +40,36 @@ package jogamp.opengl; -// FIXME: refactor Java SE dependencies -// import java.awt.GraphicsConfiguration; -// import java.awt.GraphicsDevice; -// import java.awt.GraphicsEnvironment; -import java.lang.ref.*; -import java.util.*; -import javax.media.opengl.*; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; -/** Provides a mechanism by which OpenGL contexts can share textures +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; + + +/** Provides a deterministic mechanism by which OpenGL contexts can share textures and display lists in the face of multithreading and asynchronous - context creation as is inherent in the AWT and Swing. */ + context creation. */ public class GLContextShareSet { - // FIXME: refactor Java SE dependencies - // private static boolean forceTracking = Debug.isPropertyDefined("jogl.glcontext.forcetracking"); - private static final boolean DEBUG = Debug.debug("GLContext"); - - // This class is implemented with a WeakHashMap that goes from the - // contexts as keys to a complex data structure as value that tracks - // context creation and deletion. + private static final boolean DEBUG = GLContextImpl.DEBUG; + + // This class is implemented using a HashMap which maps from all shared contexts + // to a share set, containing all shared contexts itself. - private static Map/*<GLContext, ShareSet>*/ shareMap = new WeakHashMap(); - private static Object dummyValue = new Object(); + private static final Map<GLContext, ShareSet> shareMap = new HashMap<GLContext, ShareSet>(); + private static final Object dummyValue = new Object(); private static class ShareSet { - private Map allShares = new WeakHashMap(); - private Map createdShares = new WeakHashMap(); - private Map destroyedShares = new WeakHashMap(); + private Map<GLContext, Object> allShares = new HashMap<GLContext, Object>(); + private Map<GLContext, Object> createdShares = new HashMap<GLContext, Object>(); + private Map<GLContext, Object> destroyedShares = new HashMap<GLContext, Object>(); public void add(GLContext ctx) { if (allShares.put(ctx, dummyValue) == null) { - // FIXME: downcast to GLContextImpl undesirable - if (((GLContextImpl) ctx).isCreated()) { + if (ctx.isCreated()) { createdShares.put(ctx, dummyValue); } else { destroyedShares.put(ctx, dummyValue); @@ -79,9 +77,17 @@ public class GLContextShareSet { } } + public Set<GLContext> getCreatedShares() { + return createdShares.keySet(); + } + + public Set<GLContext> getDestroyedShares() { + return destroyedShares.keySet(); + } + public GLContext getCreatedShare(GLContext ignore) { - for (Iterator iter = createdShares.keySet().iterator(); iter.hasNext(); ) { - GLContext ctx = (GLContext) iter.next(); + for (Iterator<GLContext> iter = createdShares.keySet().iterator(); iter.hasNext(); ) { + GLContext ctx = iter.next(); if (ctx != ignore) { return ctx; } @@ -126,8 +132,84 @@ public class GLContextShareSet { share.add(share2); addEntry(share1, share); addEntry(share2, share); + if (DEBUG) { + System.err.println("GLContextShareSet: registereSharing: 1: " + + toHexString(share1.getHandle()) + ", 2: " + toHexString(share2.getHandle())); + } } + public static synchronized void unregisterSharing(GLContext lastContext) { + if (lastContext == null) { + throw new IllegalArgumentException("Last context is null"); + } + ShareSet share = entryFor(lastContext); + if (share == null) { + throw new GLException("Last context is unknown: "+lastContext); + } + Set<GLContext> s = share.getCreatedShares(); + if(s.size()>0) { + throw new GLException("Last context's share set contains "+s.size()+" non destroyed context"); + } + s = share.getDestroyedShares(); + if(s.size()==0) { + throw new GLException("Last context's share set contains no destroyed context"); + } + if (DEBUG) { + System.err.println("GLContextShareSet: unregisterSharing: " + + toHexString(lastContext.getHandle())+", entries: "+s.size()); + } + for(Iterator<GLContext> iter = s.iterator() ; iter.hasNext() ; ) { + GLContext ctx = iter.next(); + if(null == removeEntry(ctx)) { + throw new GLException("Removal of shareSet for context failed"); + } + } + } + + private static synchronized Set<GLContext> getCreatedSharedImpl(GLContext context) { + if (context == null) { + throw new IllegalArgumentException("context is null"); + } + final ShareSet share = entryFor(context); + if (share != null) { + return share.getCreatedShares(); + } + return null; + } + + public static synchronized boolean isShared(GLContext context) { + if (context == null) { + throw new IllegalArgumentException("context is null"); + } + final ShareSet share = entryFor(context); + return share != null; + } + + public static synchronized boolean hasCreatedSharedLeft(GLContext context) { + final Set<GLContext> s = getCreatedSharedImpl(context); + return null != s && s.size()>0 ; + } + + /** currently not used .. + public static synchronized Set<GLContext> getCreatedShared(GLContext context) { + final Set<GLContext> s = getCreatedSharedImpl(context); + if (s == null) { + throw new GLException("context is unknown: "+context); + } + return s; + } + + public static synchronized Set<GLContext> getDestroyedShared(GLContext context) { + if (context == null) { + throw new IllegalArgumentException("context is null"); + } + ShareSet share = entryFor(context); + if (share == null) { + throw new GLException("context is unknown: "+context); + } + return share.getDestroyedShares(); + } */ + public static synchronized GLContext getShareContext(GLContext contextToCreate) { ShareSet share = entryFor(contextToCreate); if (share == null) { @@ -136,18 +218,22 @@ public class GLContextShareSet { return share.getCreatedShare(contextToCreate); } - public static synchronized void contextCreated(GLContext context) { + public static synchronized boolean contextCreated(GLContext context) { ShareSet share = entryFor(context); if (share != null) { share.contextCreated(context); + return true; } + return false; } - public static synchronized void contextDestroyed(GLContext context) { + public static synchronized boolean contextDestroyed(GLContext context) { ShareSet share = entryFor(context); if (share != null) { share.contextDestroyed(context); + return true; } + return false; } /** In order to avoid glGet calls for buffer object checks related @@ -159,8 +245,7 @@ public class GLContextShareSet { currently only needed in a fairly esoteric case, when the Java2D/JOGL bridge is active, but the GLBufferSizeTracker mechanism is now always required.) */ - public static void registerForBufferObjectSharing(GLContext olderContextOrNull, GLContext newContext) { - // FIXME: downcasts to GLContextImpl undesirable + public static void synchronizeBufferObjectSharing(GLContext olderContextOrNull, GLContext newContext) { GLContextImpl older = (GLContextImpl) olderContextOrNull; GLContextImpl newer = (GLContextImpl) newContext; GLBufferSizeTracker tracker = null; @@ -175,98 +260,6 @@ public class GLContextShareSet { newer.setBufferSizeTracker(tracker); } - // FIXME: refactor Java SE dependencies - // /** Indicates that the two supplied contexts (which must be able to - // share textures and display lists) should be in the same - // namespace for tracking of server-side object creation and - // deletion. Because the sharing necessary behind the scenes is - // different than that requested at the user level, the two notions - // are different. This must be called immediately after the - // creation of the new context (which is the second argument) - // before any server-side OpenGL objects have been created in that - // context. */ - // public static void registerForObjectTracking(GLContext olderContextOrNull, - // GLContext newContext, - // GLContext realShareContext) { - // if (isObjectTrackingEnabled() || isObjectTrackingDebuggingEnabled()) { - // GLContextImpl impl1 = null; - // GLContextImpl impl2 = null; - // GLObjectTracker tracker = null; - // - // synchronized (GLContextShareSet.class) { - // if (olderContextOrNull != null && - // newContext != null) { - // if (entryFor(olderContextOrNull) != entryFor(newContext)) { - // throw new IllegalArgumentException("old and new contexts must be able to share textures and display lists"); - // } - // } - // - // // FIXME: downcast to GLContextImpl undesirable - // impl1 = (GLContextImpl) olderContextOrNull; - // impl2 = (GLContextImpl) newContext; - // - // GLObjectTracker deletedObjectTracker = null; - // GLContextImpl shareImpl = (GLContextImpl) realShareContext; - // // Before we zap the "user-level" object trackers, make sure - // // that all contexts in the share set share the destroyed object - // // tracker - // if (shareImpl != null) { - // deletedObjectTracker = shareImpl.getDeletedObjectTracker(); - // } - // if (deletedObjectTracker == null) { - // // Must create one and possibly set it up in the older context - // deletedObjectTracker = new GLObjectTracker(); - // if (DEBUG) { - // System.err.println("Created deletedObjectTracker " + deletedObjectTracker + " because " + - // ((shareImpl == null) ? "shareImpl was null" : "shareImpl's (" + shareImpl + ") deletedObjectTracker was null")); - // } - // - // if (shareImpl != null) { - // // FIXME: think should really assert in this case - // shareImpl.setDeletedObjectTracker(deletedObjectTracker); - // if (DEBUG) { - // System.err.println("Set deletedObjectTracker " + deletedObjectTracker + " in shareImpl context " + shareImpl); - // } - // } - // } - // impl2.setDeletedObjectTracker(deletedObjectTracker); - // if (DEBUG) { - // System.err.println("Set deletedObjectTracker " + deletedObjectTracker + " in impl2 context " + impl2); - // } - // } - // - // // Must not hold lock around this operation - // // Don't share object trackers with the primordial share context from Java2D - // if (Java2D.isOGLPipelineActive()) { - // // FIXME: probably need to do something different here - // // Need to be able to figure out the GraphicsDevice for the - // // older context if it's on-screen - // GraphicsDevice device = GraphicsEnvironment. - // getLocalGraphicsEnvironment(). - // getDefaultScreenDevice(); - // GLContext j2dShareContext = Java2D.getShareContext(device); - // if (impl1 != null && impl1 == j2dShareContext) { - // impl1 = null; - // } - // } - // - // synchronized (GLContextShareSet.class) { - // if (impl1 != null) { - // tracker = impl1.getObjectTracker(); - // assert (tracker != null) - // : "registerForObjectTracking was not called properly for the older context"; - // } - // if (tracker == null) { - // tracker = new GLObjectTracker(); - // } - // // Note that we don't assert that the tracker is non-null for - // // impl2 because the way we use this functionality we actually - // // overwrite the initially-set object tracker in the new context - // impl2.setObjectTracker(tracker); - // } - // } - // } - //---------------------------------------------------------------------- // Internals only below this point @@ -280,14 +273,11 @@ public class GLContextShareSet { shareMap.put(context, share); } } - - // FIXME: refactor Java SE dependencies - // private static boolean isObjectTrackingEnabled() { - // return ((Java2D.isOGLPipelineActive() && Java2D.isFBOEnabled()) || - // isObjectTrackingDebuggingEnabled()); - // } - // - // private static boolean isObjectTrackingDebuggingEnabled() { - // return forceTracking; - // } + private static ShareSet removeEntry(GLContext context) { + return (ShareSet) shareMap.remove(context); + } + + protected static String toHexString(long hex) { + return "0x" + Long.toHexString(hex); + } } |