diff options
author | Julien Gouesse <[email protected]> | 2015-11-28 15:11:48 +0100 |
---|---|---|
committer | Julien Gouesse <[email protected]> | 2015-11-28 15:11:48 +0100 |
commit | dbc98deea1884e44da2c74d6ea807253cdefa693 (patch) | |
tree | 29c3ee7dea82d7dd773d81f33f645dde67e43a17 /src/javax/media/j3d/MasterControl.java | |
parent | 2c99f1329dc55bd496bce91b9aba956ecba3c67e (diff) |
Relocate package prefix to org.jogamp.java3d
Diffstat (limited to 'src/javax/media/j3d/MasterControl.java')
-rw-r--r-- | src/javax/media/j3d/MasterControl.java | 3748 |
1 files changed, 0 insertions, 3748 deletions
diff --git a/src/javax/media/j3d/MasterControl.java b/src/javax/media/j3d/MasterControl.java deleted file mode 100644 index 0d7af66..0000000 --- a/src/javax/media/j3d/MasterControl.java +++ /dev/null @@ -1,3748 +0,0 @@ -/* - * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - */ - -/* - * Portions of this code were derived from work done by the Blackdown - * group (www.blackdown.org), who did the initial Linux implementation - * of the Java 3D API. - */ - -package javax.media.j3d; - -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.logging.Level; -import java.util.logging.Logger; - -class MasterControl { - - /** - * Options for the runMonitor - */ - static final int CHECK_FOR_WORK = 0; - static final int SET_WORK = 1; - static final int RUN_THREADS = 2; - static final int THREAD_DONE = 3; - static final int SET_WORK_FOR_REQUEST_RENDERER = 5; - static final int RUN_RENDERER_CLEANUP = 6; - - // The thread states for MC - static final int SLEEPING = 0; - static final int RUNNING = 1; - static final int WAITING_FOR_THREADS = 3; - static final int WAITING_FOR_CPU = 4; - static final int WAITING_FOR_RENDERER_CLEANUP = 5; - - // Constants used in renderer thread argument - static final Integer REQUESTRENDER = new Integer(Renderer.REQUESTRENDER); - static final Integer RENDER = new Integer(Renderer.RENDER); - static final Integer SWAP = new Integer(Renderer.SWAP); - - // Constants used for request from user threads - static final Integer ACTIVATE_VIEW = new Integer(1); - static final Integer DEACTIVATE_VIEW = new Integer(2); - static final Integer START_VIEW = new Integer(3); - static final Integer STOP_VIEW = new Integer(4); - static final Integer REEVALUATE_CANVAS = new Integer(5); - static final Integer UNREGISTER_VIEW = new Integer(6); - static final Integer PHYSICAL_ENV_CHANGE = new Integer(7); - static final Integer INPUTDEVICE_CHANGE = new Integer(8); - static final Integer EMPTY_UNIVERSE = new Integer(9); - static final Integer START_RENDERER = new Integer(10); - static final Integer STOP_RENDERER = new Integer(11); - static final Integer RENDER_ONCE = new Integer(12); - static final Integer FREE_CONTEXT = new Integer(13); - static final Integer FREE_DRAWING_SURFACE = new Integer(14); - static final Integer FREE_MESSAGE = new Integer(15); - static final Integer RESET_CANVAS = new Integer(16); - static final Integer GETBESTCONFIG = new Integer(17); - static final Integer ISCONFIGSUPPORT = new Integer(18); - static final Integer SET_GRAPHICSCONFIG_FEATURES = new Integer(19); - static final Integer SET_QUERYPROPERTIES = new Integer(20); - static final Integer SET_VIEW = new Integer(21); - - // Developer logger for reporting informational messages; see getDevLogger() - private static boolean devLoggerEnabled = false; - private static Logger devLogger; - - // Stats logger for reporting runtime statistics; see getStatsLogger() - private static boolean statsLoggerEnabled = false; - private static Logger statsLogger; - - // Core logger for reporting internal errors, warning, and - // informational messages; see getCoreLogger() - private static boolean coreLoggerEnabled = false; - private static Logger coreLogger; - - // Flag indicating that the rendering pipeline libraries are loaded - private static boolean librariesLoaded = false; - - /** - * reference to MasterControl thread - */ - private MasterControlThread mcThread = null; - - /** - * The list of views that are currently registered - */ - private UnorderList views = new UnorderList(1, View.class); - - - /** - * by MIK OF CLASSX - * - * the flag to indicate whether the background of the offscreen - * canvas must be transparent or not false by default - */ - boolean transparentOffScreen = false; - - /** - * Flag to indicate whether Pbuffers are used for off-screen - * rendering; true by default. Set by the "j3d.usePbuffer" - * property, When this flag is set to false, Bitmap (Windows) or - * Pixmap (UNIX) rendering will be used - */ - boolean usePbuffer = true; - - /** - * Flag to indicate whether should renderer view frustum culling is done; - * true by default. - * Set by the -Dj3d.viewFrustumCulling property, When this flag is - * set to false, the renderer view frustum culling is turned off. - */ - boolean viewFrustumCulling = true; - - /** - * the flag to indicate whether the geometry should be locked or not - */ - - private boolean lockGeometry = false; - - /** - * The number of registered views that are active - */ - private int numActiveViews = 0; - - /** - * The list of active universes get from View - */ - private UnorderList activeUniverseList = new UnorderList(VirtualUniverse.class); - - /** - * The list of universes register from View - */ - private UnorderList regUniverseList = new UnorderList(VirtualUniverse.class); - - /** - * A lock used for accessing time structures. - */ - private Object timeLock = new Object(); - - - /** - * The current "time" value - */ - private long time = 0; - - /** - * Use to assign threadOpts in Renderer thread. - */ - private long waitTimestamp = 0; - - /** - * The current list of work threads - */ - private UnorderList stateWorkThreads = - new UnorderList(J3dThreadData.class); - private UnorderList renderWorkThreads = - new UnorderList(J3dThreadData.class); - private UnorderList requestRenderWorkThreads = - new UnorderList(J3dThreadData.class); - - /** - * The current list of work threads - */ - private UnorderList renderThreadData = new UnorderList(J3dThreadData.class); - - /** - * The list of input device scheduler thread - */ - private UnorderList inputDeviceThreads = - new UnorderList(1, InputDeviceScheduler.class); - - /** - * A flag that is true when the thread lists need updating - */ - private boolean threadListsChanged; - - - /** - * Markers for the last transform structure update thread - * and the last update thread. - */ - private int lastTransformStructureThread = 0; - private int lastStructureUpdateThread = 0; - - /** - * The current time snapshots - */ - private long currentTime; - - // Only one Timer thread in the system. - TimerThread timerThread; - - // Only one Notification thread in the system. - private NotificationThread notificationThread; - - /** - * This flag indicates that MC is running - */ - volatile boolean running = true; - - /** - * This flag indicates that MC has work to do - */ - private boolean workToDo = false; - - /** - * This flag indicates that there is work for requestRenderer - */ - private boolean requestRenderWorkToDo = false; - - /** - * The number of THREAD_DONE messages pending - */ - private int threadPending = 0; - private int renderPending = 0; - private int statePending = 0; - - /** - * State variables for work lists - */ - private boolean renderWaiting = false; - private boolean stateWaiting = false; - - /** - * The current state of the MC thread - */ - private int state = SLEEPING; - - // time for sleep in order to met the minimum frame duration - private long sleepTime = 0; - - - /** - * The number of cpu's Java 3D may use - */ - private int cpuLimit; - - /** - * A list of mirror objects to be updated - */ - private UnorderList mirrorObjects = new UnorderList(ObjectUpdate.class); - - /** - * The renderingAttributesStructure for updating node component - * objects - */ - private RenderingAttributesStructure renderingAttributesStructure = - new RenderingAttributesStructure(); - - /** - * The default rendering method - */ - private DefaultRenderMethod defaultRenderMethod = null; - - /** - * The text3D rendering method - */ - private Text3DRenderMethod text3DRenderMethod = null; - - /** - * The vertex array rendering method - */ - private VertexArrayRenderMethod vertexArrayRenderMethod = null; - - /** - * The displayList rendering method - */ - private DisplayListRenderMethod displayListRenderMethod = null; - - /** - * The compressed geometry rendering method - */ - private CompressedGeometryRenderMethod compressedGeometryRenderMethod = null; - - /** - * The oriented shape3D rendering method - */ - private OrientedShape3DRenderMethod orientedShape3DRenderMethod = null; - - /** - * This is the start time upon which alpha's and behaviors - * are synchronized to. It is initialized once, the first time - * that a MasterControl object is created. - */ - static long systemStartTime = 0L; - - // This is a time stamp used when context is created - private long contextTimeStamp = 0; - - // This is an array of canvasIds in used - private boolean[] canvasIds = null; - private int canvasFreeIndex = 0; - private Object canvasIdLock = new Object(); - - // This is a counter for rendererBit - private int rendererCount = 0; - - // Flag that indicates whether to shared display context or not - boolean isSharedCtx = false; - - // Flag that tells us to use NV_register_combiners - boolean useCombiners = false; - - // Flag that indicates whether compile is disabled or not - boolean disableCompile = false; - - // Flag that indicates whether or not compaction occurs - boolean doCompaction = true; - - // Flag that indicates whether separate specular color is disabled or not - boolean disableSeparateSpecularColor = false; - - // Flag that indicates whether DisplayList is used or not - boolean isDisplayList = true; - - // If this flag is set, then by-ref geometry will not be - // put in display list - boolean buildDisplayListIfPossible = false; - - // If this flag is set, then geometry arrays with vertex attributes can - // be in display list. - boolean vertexAttrsInDisplayList = false; - - // Issue 249 - flag that indicates whether the soleUser optimization is permitted - boolean allowSoleUser = false; - - // Issue 266 - Flag indicating whether null graphics configs are allowed - // Set by -Dj3d.allowNullGraphicsConfig property - // Setting this flag causes Canvas3D to allow a null GraphicsConfiguration - // for on-screen canvases. This is only for backward compatibility with - // legacy applications. - boolean allowNullGraphicsConfig = false; - - // Issue 239 - Flag indicating whether the stencil buffer is cleared by - // default each frame when the color and depth buffers are cleared. - // Note that this is a partial solution, since we eventually want an API - // to control this. - boolean stencilClear = false; - - // REQUESTCLEANUP messages argument - static Integer REMOVEALLCTXS_CLEANUP = new Integer(1); - static Integer REMOVECTX_CLEANUP = new Integer(2); - static Integer REMOVENOTIFY_CLEANUP = new Integer(3); - static Integer RESETCANVAS_CLEANUP = new Integer(4); - static Integer FREECONTEXT_CLEANUP = new Integer(5); - - // arguments for renderer resource cleanup run - Object rendererCleanupArgs[] = {new Integer(Renderer.REQUESTCLEANUP), - null, null}; - - - // Context creation should obtain this lock, so that - // first_time and all the extension initilialization - // are done in the MT safe manner - Object contextCreationLock = new Object(); - - // Flag that indicates whether to lock the DSI while rendering - boolean doDsiRenderLock = false; - - // Flag that indicates the pre-1.5 behavior of enforcing power-of-two - // textures. If set, then any non-power-of-two textures will throw an - // exception. - boolean enforcePowerOfTwo = false; - - // Flag that indicates whether the framebuffer is sharing the - // Z-buffer with both the left and right eyes when in stereo mode. - // If this is true, we need to clear the Z-buffer between rendering - // to the left and right eyes. - boolean sharedStereoZBuffer = true; - - // True to disable all underlying multisampling API so it uses - // the setting in the driver. - boolean implicitAntialiasing = false; - - // False to disable compiled vertex array extensions if support - boolean isCompiledVertexArray = true; - - // Number of reserved vertex attribute locations for GLSL (must be at - // least 1). - // Issue 269 - need to reserve up to 6 vertex attribtue locations to ensure - // that we don't collide with a predefined gl_* attribute on nVidia cards. - int glslVertexAttrOffset = 6; - - // Hashtable that maps a GraphicsDevice to its associated - // Screen3D--this is only used for on-screen Canvas3Ds - Hashtable<GraphicsDevice, Screen3D> deviceScreenMap = new Hashtable<GraphicsDevice, Screen3D>(); - - // Use to store all requests from user threads. - UnorderList requestObjList = new UnorderList(); - private UnorderList requestTypeList = new UnorderList(Integer.class); - - // Temporary storage to store stop request for requestViewList - private UnorderList tempViewList = new UnorderList(); - private UnorderList renderOnceList = new UnorderList(); - - // This flag is true when there is pending request - // i.e. false when the above requestxxx Lists are all empty. - private boolean pendingRequest = false; - - // Root ThreadGroup for creating Java 3D threads - private static ThreadGroup rootThreadGroup; - - // Thread priority for all Java 3D threads - private static int threadPriority; - - static private Object mcThreadLock = new Object(); - - private ArrayList<View> timestampUpdateList = new ArrayList<View>(3); - - private UnorderList freeMessageList = new UnorderList(8); - - // Maximum number of lights - int maxLights; - - // Set by the -Dj3d.sortShape3DBounds property, When this flag is - // set to true, the bounds of the Shape3D node will be used in - // place of the computed GeometryArray bounds for transparency - // sorting for those Shape3D nodes whose boundsAutoCompute - // attribute is set to false. - boolean sortShape3DBounds = false; - - //Set by -Dj3d.forceReleaseView property. - //Setting this flag as true disables the bug fix 4267395 in View deactivate(). - //The bug 4267395 can lock-up *some* systems, but the bug fix can - //produce memory leaks in applications which creates and destroy Canvas3D - //from time to time. - //Set as true if you have memory leaks after disposing Canvas3D. - //Default false value does affect Java3D View dispose behavior. - boolean forceReleaseView = false; - - // Issue 480: Cache the bounds of nodes so that getBounds does not - // recompute the boounds of the entire graph per call - boolean cacheAutoComputedBounds = false; - - // issue 544 - boolean useBoxForGroupBounds = false; - - /** - * Constructs a new MasterControl object. Note that there is - * exatly one MasterControl object, created statically by - * VirtualUniverse. - */ - MasterControl() { - assert librariesLoaded; - - // Initialize the start time upon which alpha's and behaviors - // are synchronized to (if it isn't already set). - if (systemStartTime == 0L) { - systemStartTime = J3dClock.currentTimeMillis(); - } - - if(J3dDebug.devPhase) { - // Check to see whether debug mode is allowed - J3dDebug.debug = getBooleanProperty("j3d.debug", false, - "J3dDebug.debug"); - } - - // Check to see whether shared contexts are allowed - isSharedCtx = getBooleanProperty("j3d.sharedctx", isSharedCtx, "shared contexts"); - - doCompaction = getBooleanProperty("j3d.docompaction", doCompaction, - "compaction"); - - // by MIK OF CLASSX - transparentOffScreen = getBooleanProperty("j3d.transparentOffScreen", transparentOffScreen, "transparent OffScreen"); - - usePbuffer = getBooleanProperty("j3d.usePbuffer", - usePbuffer, - "Off-screen Pbuffer"); - - viewFrustumCulling = getBooleanProperty("j3d.viewFrustumCulling", viewFrustumCulling,"View frustum culling in the renderer is"); - - sortShape3DBounds = - getBooleanProperty("j3d.sortShape3DBounds", sortShape3DBounds, - "Shape3D bounds enabled for transparency sorting", - "Shape3D bounds *ignored* for transparency sorting"); - - forceReleaseView = - getBooleanProperty("j3d.forceReleaseView", forceReleaseView, - "forceReleaseView after Canvas3D dispose enabled", - "forceReleaseView after Canvas3D dispose disabled"); - -// FIXME: GL_NV_register_combiners -// useCombiners = getBooleanProperty("j3d.usecombiners", useCombiners, -// "Using NV_register_combiners if available", -// "NV_register_combiners disabled"); - - if (getProperty("j3d.disablecompile") != null) { - disableCompile = true; - System.err.println("Java 3D: BranchGroup.compile disabled"); - } - - if (getProperty("j3d.disableSeparateSpecular") != null) { - disableSeparateSpecularColor = true; - System.err.println("Java 3D: separate specular color disabled if possible"); - } - - isDisplayList = getBooleanProperty("j3d.displaylist", isDisplayList, - "display list"); - - implicitAntialiasing = - getBooleanProperty("j3d.implicitAntialiasing", - implicitAntialiasing, - "implicit antialiasing"); - - isCompiledVertexArray = - getBooleanProperty("j3d.compiledVertexArray", - isCompiledVertexArray, - "compiled vertex array"); - - boolean j3dOptimizeSpace = - getBooleanProperty("j3d.optimizeForSpace", true, - "optimize for space"); - - if (isDisplayList) { - // Build Display list for by-ref geometry - // ONLY IF optimizeForSpace is false - if (!j3dOptimizeSpace) { - buildDisplayListIfPossible = true; - } - - // Build display lists for geometry with vertex attributes - // ONLY if we are in GLSL mode and GLSL shaders are available - vertexAttrsInDisplayList = true; - } - - // Check to see whether Renderer can run without DSI lock - doDsiRenderLock = getBooleanProperty("j3d.renderLock", - doDsiRenderLock, - "render lock"); - - // Check to see whether we enforce power-of-two textures - enforcePowerOfTwo = getBooleanProperty("j3d.textureEnforcePowerOfTwo", - enforcePowerOfTwo, - "checking power-of-two textures"); - - // Issue 249 - check to see whether the soleUser optimization is permitted - allowSoleUser = getBooleanProperty("j3d.allowSoleUser", - allowSoleUser, - "sole-user mode"); - - // Issue 266 - check to see whether null graphics configs are allowed - allowNullGraphicsConfig = getBooleanProperty("j3d.allowNullGraphicsConfig", - allowNullGraphicsConfig, - "null graphics configs"); - - // Issue 239 - check to see whether per-frame stencil clear is enabled - stencilClear = getBooleanProperty("j3d.stencilClear", - stencilClear, - "per-frame stencil clear"); - - // Check to see if stereo mode is sharing the Z-buffer for both eyes. - sharedStereoZBuffer = - getBooleanProperty("j3d.sharedstereozbuffer", - sharedStereoZBuffer, - "shared stereo Z buffer"); - - // Get the maximum number of concurrent threads (CPUs) - final int defaultThreadLimit = getNumberOfProcessors() + 1; - Integer threadLimit = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Integer>() { - @Override - public Integer run() { - return Integer.getInteger("j3d.threadLimit", defaultThreadLimit); - } - }); - - cpuLimit = threadLimit.intValue(); - if (cpuLimit < 1) - cpuLimit = 1; - if (J3dDebug.debug || cpuLimit != defaultThreadLimit) { - System.err.println("Java 3D: concurrent threadLimit = " + - cpuLimit); - } - - // Get the input device scheduler sampling time - Integer samplingTime = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Integer>() { - @Override - public Integer run() { - return Integer.getInteger("j3d.deviceSampleTime", 0); - } - }); - - if (samplingTime.intValue() > 0) { - InputDeviceScheduler.samplingTime = - samplingTime.intValue(); - System.err.println("Java 3D: Input device sampling time = " - + samplingTime + " ms"); - } - - // Get the glslVertexAttrOffset - final int defaultGLSLVertexAttrOffset = glslVertexAttrOffset; - Integer vattrOffset = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Integer>() { - @Override - public Integer run() { - return Integer.getInteger("j3d.glslVertexAttrOffset", - defaultGLSLVertexAttrOffset); - } - }); - - glslVertexAttrOffset = vattrOffset.intValue(); - if (glslVertexAttrOffset < 1) { - glslVertexAttrOffset = 1; - } - if (J3dDebug.debug || glslVertexAttrOffset != defaultGLSLVertexAttrOffset) { - System.err.println("Java 3D: glslVertexAttrOffset = " + - glslVertexAttrOffset); - } - - // Issue 480 : Cache bounds returned by getBounds() - cacheAutoComputedBounds = - getBooleanProperty("j3d.cacheAutoComputeBounds", - cacheAutoComputedBounds, - "Cache AutoCompute Bounds, accelerates getBounds()"); - - // Issue 544 - useBoxForGroupBounds = - getBooleanProperty("j3d.useBoxForGroupBounds", - useBoxForGroupBounds, - "Use of BoundingBox for group geometric bounds"); - - // Check for obsolete properties - String[] obsoleteProps = { - "j3d.backgroundtexture", - "j3d.forceNormalized", - "j3d.g2ddrawpixel", - "j3d.simulatedMultiTexture", - "j3d.useFreeLists", - }; - for (int i = 0; i < obsoleteProps.length; i++) { - if (getProperty(obsoleteProps[i]) != null) { - System.err.println("Java 3D: " + obsoleteProps[i] + " property ignored"); - } - } - - // Get the maximum Lights - maxLights = Pipeline.getPipeline().getMaximumLights(); - - // create the freelists - FreeListManager.createFreeLists(); - - // create an array canvas use registers - // The 32 limit can be lifted once the - // resourceXXXMasks in other classes - // are change not to use integer. - canvasIds = new boolean[32]; - for(int i=0; i<canvasIds.length; i++) { - canvasIds[i] = false; - } - canvasFreeIndex = 0; - } - - private static boolean initLogger(Logger logger, Level defaultLevel) { - if (logger == null) { - return false; - } - - if (defaultLevel != null && - logger.getLevel() == null && - Logger.getLogger("j3d").getLevel() == null) { - - try { - // Set default logger level rather than inheriting from system global - logger.setLevel(defaultLevel); - } catch (SecurityException ex) { - System.err.println(ex); - return false; - } - } - - return logger.isLoggable(Level.SEVERE); - } - - // Called by the static initializer to initialize the loggers - private static void initLoggers() { - coreLogger = Logger.getLogger("j3d.core"); - devLogger = Logger.getLogger("j3d.developer"); - statsLogger = Logger.getLogger("j3d.stats"); - - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - coreLoggerEnabled = initLogger(coreLogger, null); - devLoggerEnabled = initLogger(devLogger, Level.OFF); - statsLoggerEnabled = initLogger(statsLogger, Level.OFF); - return null; - } - }); - } - - /** - * Get the developer logger -- OFF by default - * - * WARNING - for probable incorrect or inconsistent api usage - * INFO - for informational messages such as performance hints (less verbose than FINE) - * FINE - for informational messages from inner loops - * FINER - using default values which may not be optimal - */ - static Logger getDevLogger() { - return devLogger; - } - - static boolean isDevLoggable(Level level) { - return devLoggerEnabled && devLogger.isLoggable(level); - } - - /** - * Get the stats logger -- OFF by default - * - * WARNING - statistical anomalies - * INFO - basic performance stats - not too verbose and minimally intrusive - * FINE - somewhat verbose and intrusive - * FINER - more verbose and intrusive - * FINEST - most verbose and intrusive - */ - static Logger getStatsLogger() { - return statsLogger; - } - - static boolean isStatsLoggable(Level level) { - return statsLoggerEnabled && statsLogger.isLoggable(level); - } - - /** - * Get the core logger -- level is INFO by default - * - * SEVERE - Serious internal errors - * WARNING - Possible internal errors or anomalies - * INFO - General informational messages - * FINE - Internal debugging information - somewhat verbose - * FINER - Internal debugging information - more verbose - * FINEST - Internal debugging information - most verbose - */ - static Logger getCoreLogger() { - return coreLogger; - } - - static boolean isCoreLoggable(Level level) { - return coreLoggerEnabled && coreLogger.isLoggable(level); - } - -private static String getProperty(final String prop) { - return java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<String>() { - @Override - public String run() { - return System.getProperty(prop); - } - }); -} - - static boolean getBooleanProperty(String prop, - boolean defaultValue, - String trueMsg, - String falseMsg) { - boolean value = defaultValue; - String propValue = getProperty(prop); - - if (propValue != null) { - value = Boolean.valueOf(propValue).booleanValue(); - if (J3dDebug.debug) - System.err.println("Java 3D: " + (value ? trueMsg : falseMsg)); - } - return value; - } - - static boolean getBooleanProperty(String prop, - boolean defaultValue, - String msg) { - return getBooleanProperty(prop, - defaultValue, - (msg + " enabled"), - (msg + " disabled")); - } - - /** - * Method to create and initialize the rendering Pipeline object, - * and to load the native libraries needed by Java 3D. This is - * called by the static initializer in VirtualUniverse <i>before</i> - * the MasterControl object is created. - */ - static void loadLibraries() { - assert !librariesLoaded; - - // Initialize the Pipeline object associated with the - // renderer specified by the "j3d.rend" system property. - // - // XXXX : We should consider adding support for a more flexible, - // dynamic selection scheme via an API call. - - // Default rendering pipeline is the JOGL pipeline - Pipeline.Type pipelineType = Pipeline.Type.JOGL; - - final String rendStr = getProperty("j3d.rend"); - if (rendStr == null) { - // Use default pipeline - } else if (rendStr.equals("jogl")) { - pipelineType = Pipeline.Type.JOGL; - } else if (rendStr.equals("noop")) { - pipelineType = Pipeline.Type.NOOP; - } else { - System.err.println("Java 3D: Unrecognized renderer: " + rendStr); - // Use default pipeline - } - - // Construct the singleton Pipeline instance - Pipeline.createPipeline(pipelineType); - - librariesLoaded = true; - } - - - /** - * Invoke from InputDeviceScheduler to create an - * InputDeviceBlockingThread. - */ - InputDeviceBlockingThread getInputDeviceBlockingThread( - final InputDevice device) { - - return java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<InputDeviceBlockingThread>() { - @Override - public InputDeviceBlockingThread run() { - synchronized (rootThreadGroup) { - InputDeviceBlockingThread thread = new InputDeviceBlockingThread( - rootThreadGroup, device); - thread.setPriority(threadPriority); - return thread; - } - } - }); - } - - /** - * Set thread priority to all threads under Java3D thread group. - */ - void setThreadPriority(final int pri) { - synchronized (rootThreadGroup) { - threadPriority = pri; - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - Thread list[] = new - Thread[rootThreadGroup.activeCount()]; - int count = rootThreadGroup.enumerate(list); - for (int i=count-1; i >=0; i--) { - list[i].setPriority(pri); - } - return null; - } - }); - } - } - - - /** - * Return Java3D thread priority - */ - int getThreadPriority() { - return threadPriority; - } - - /** - * This returns the a unused renderer bit - */ - int getRendererBit() { - return (1 << rendererCount++); - } - - - /** - * This returns the a unused renderer bit - */ - int getRendererId() { - return rendererCount++; - } - - /** - * This returns a context creation time stamp - * Note: this has to be called under the contextCreationLock - */ - long getContextTimeStamp() { - return (++contextTimeStamp); - } - - - /** - * This returns the a unused displayListId - */ - Integer getDisplayListId() { - return (Integer) FreeListManager.getObject(FreeListManager.DISPLAYLIST); - } - - void freeDisplayListId(Integer id) { - FreeListManager.freeObject(FreeListManager.DISPLAYLIST, id); - } - - int getCanvasId() { - int i; - - synchronized(canvasIdLock) { - // Master control need to keep count itself - for(i=canvasFreeIndex; i<canvasIds.length; i++) { - if(canvasIds[i] == false) - break; - } - - if (i >= canvasIds.length) { - throw new RuntimeException("Cannot render to more than 32 Canvas3Ds"); - } - - canvasIds[i] = true; - canvasFreeIndex = i + 1; - } - - return i; - - } - - void freeCanvasId(int canvasId) { - // Valid range is [0, 31] - synchronized(canvasIdLock) { - - canvasIds[canvasId] = false; - if(canvasFreeIndex > canvasId) { - canvasFreeIndex = canvasId; - } - } - } - - - /** - * Create a Renderer if it is not already done so. - * This is used for GraphicsConfigTemplate3D passing - * graphics call to RequestRenderer, and for creating - * an off-screen buffer for an off-screen Canvas3D. - */ - private Renderer createRenderer(GraphicsConfiguration gc) { - final GraphicsDevice gd = gc.getDevice(); - - Renderer rdr = Screen3D.deviceRendererMap.get(gd); - if (rdr != null) { - return rdr; - } - - - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - Renderer r; - synchronized (rootThreadGroup) { - r = new Renderer(rootThreadGroup); - r.initialize(); - r.setPriority(threadPriority); - Screen3D.deviceRendererMap.put(gd, r); - } - return null; - } - }); - - threadListsChanged = true; - - return Screen3D.deviceRendererMap.get(gd); - } - - /** - * Post the request in queue - */ - void postRequest(Integer type, Object obj) { - - synchronized (mcThreadLock) { - synchronized (requestObjList) { - if (mcThread == null) { - if ((type == ACTIVATE_VIEW) || - (type == GETBESTCONFIG) || - (type == SET_VIEW) || - (type == ISCONFIGSUPPORT) || - (type == SET_QUERYPROPERTIES) || - (type == SET_GRAPHICSCONFIG_FEATURES)) { - createMasterControlThread(); - requestObjList.add(obj); - requestTypeList.add(type); - pendingRequest = true; - } else if (type == EMPTY_UNIVERSE) { - destroyUniverseThreads((VirtualUniverse) obj); - } else if (type == STOP_VIEW) { - View v = (View) obj; - v.stopViewCount = -1; - v.isRunning = false; - } else if (type == STOP_RENDERER) { - if (obj instanceof Canvas3D) { - ((Canvas3D) obj).isRunningStatus = false; - } else { - ((Renderer) obj).userStop = true; - } - } else if (type == UNREGISTER_VIEW) { - ((View) obj).doneUnregister = true; - } else { - requestObjList.add(obj); - requestTypeList.add(type); - pendingRequest = true; - } - } else { - requestObjList.add(obj); - requestTypeList.add(type); - pendingRequest = true; - } - } - } - - setWork(); - } - - - - - /** - * This procedure is invoked when isRunning is false. - * Return true when there is no more pending request so that - * Thread can terminate. Otherwise we have to recreate - * the MC related threads. - */ - boolean mcThreadDone() { - synchronized (mcThreadLock) { - synchronized (requestObjList) { - if (!pendingRequest) { - mcThread = null; - if (renderingAttributesStructure.updateThread != - null) { - renderingAttributesStructure.updateThread.finish(); - renderingAttributesStructure.updateThread = - null; - } - renderingAttributesStructure = new RenderingAttributesStructure(); - if (timerThread != null) { - timerThread.finish(); - timerThread = null; - } - if (notificationThread != null) { - notificationThread.finish(); - notificationThread = null; - } - requestObjList.clear(); - requestTypeList.clear(); - return true; - } - running = true; - createMCThreads(); - return false; - } - } - } - - /** - * This method increments and returns the next time value - * timeLock must get before this procedure is invoked - */ - final long getTime() { - return (time++); - } - - - /** - * This takes a given message and parses it out to the structures and - * marks its time value. - */ - void processMessage(J3dMessage message) { - - synchronized (timeLock) { - message.time = getTime(); - sendMessage(message); - } - setWork(); - } - - /** - * This takes an array of messages and parses them out to the structures and - * marks the time value. Make sure, setWork() is done at the very end - * to make sure all the messages will be processed in the same frame - */ - void processMessage(J3dMessage[] messages) { - - synchronized (timeLock) { - long time = getTime(); - - for (int i = 0; i < messages.length; i++) { - messages[i].time = time; - sendMessage(messages[i]); - } - } - setWork(); - } - - /** - * This takes the specified notification message and sends it to the - * notification thread for processing. - */ - void sendNotification(J3dNotification notification) { - notificationThread.addNotification(notification); - } - - /** - * Create and start the MasterControl Thread. - */ - void createMasterControlThread() { - // Issue 364: don't create master control thread if already created - if (mcThread != null) { - return; - } - - running = true; - workToDo = true; - state = RUNNING; - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - synchronized (rootThreadGroup) { - mcThread = new - MasterControlThread(rootThreadGroup); - mcThread.setPriority(threadPriority); - } - return null; - } - }); - } - - // assuming the timeLock is already acquired - - /** - * Send a message to another Java 3D thread. - */ - void sendMessage(J3dMessage message) { - - synchronized (message) { - VirtualUniverse u = message.universe; - int targetThreads = message.threads; - - if (isCoreLoggable(Level.FINEST)) { - dumpMessage("sendMessage", message); - } - - if ((targetThreads & J3dThread.UPDATE_RENDERING_ATTRIBUTES) != 0) { - renderingAttributesStructure.addMessage(message); - } - - // GraphicsContext3D send message with universe = null - if (u != null) { - if ((targetThreads & J3dThread.UPDATE_GEOMETRY) != 0) { - u.geometryStructure.addMessage(message); - } - if ((targetThreads & J3dThread.UPDATE_TRANSFORM) != 0) { - u.transformStructure.addMessage(message); - } - if ((targetThreads & J3dThread.UPDATE_BEHAVIOR) != 0) { - u.behaviorStructure.addMessage(message); - } - if ((targetThreads & J3dThread.UPDATE_SOUND) != 0) { - u.soundStructure.addMessage(message); - } - if ((targetThreads & J3dThread.UPDATE_RENDERING_ENVIRONMENT) != 0) { - u.renderingEnvironmentStructure.addMessage(message); - } - } - - if ((targetThreads & J3dThread.SOUND_SCHEDULER) != 0) { - // Note that we don't check for active view - if (message.view != null && message.view.soundScheduler != null ) { - // This make sure that message won't lost even - // though this view not yet register - message.view.soundScheduler.addMessage(message); - } else { - synchronized (views) { - View v[] = (View []) views.toArray(false); - int i = views.arraySize()-1; - if (u == null) { - while (i>=0) { - v[i--].soundScheduler.addMessage(message); - } - } else { - while (i>=0) { - if (v[i].universe == u) { - v[i].soundScheduler.addMessage(message); - } - i--; - } - } - } - } - } - - if ((targetThreads & J3dThread.UPDATE_RENDER) != 0) { - // Note that we don't check for active view - if (message.view != null && message.view.renderBin != null) { - // This make sure that message won't lost even - // though this view not yet register - message.view.renderBin.addMessage(message); - } else { - synchronized (views) { - View v[] = (View []) views.toArray(false); - int i = views.arraySize()-1; - if (u == null) { - while (i>=0) { - v[i--].renderBin.addMessage(message); - } - } - else { - while (i>=0) { - if (v[i].universe == u) { - v[i].renderBin.addMessage(message); - } - i--; - } - } - } - } - } - - if (message.getRefcount() == 0) { - message.clear(); - } - } - } - - - /** - * Send a message to another Java 3D thread. - * This variant is only call by TimerThread for Input Device Scheduler - * or to redraw all View for RenderThread - */ - void sendRunMessage(int targetThreads) { - - synchronized (timeLock) { - - long time = getTime(); - - if ((targetThreads & J3dThread.INPUT_DEVICE_SCHEDULER) != 0) { - synchronized (inputDeviceThreads) { - InputDeviceScheduler ds[] = (InputDeviceScheduler []) - inputDeviceThreads.toArray(false); - for (int i=inputDeviceThreads.size()-1; i >=0; i--) { - if (ds[i].physicalEnv.activeViewRef > 0) { - ds[i].getThreadData().lastUpdateTime = - time; - } - } - - // timerThread instance in MC will set to null in - // destroyUniverseThreads() so we need to check if - // TimerThread kick in to sendRunMessage() after that. - // It happens because TimerThread is the only thread run - // asychronizously with MasterControl thread. - - if (timerThread != null) { - // Notify TimerThread to wakeup this procedure - // again next time. - timerThread.addInputDeviceSchedCond(); - } - } - } - if ((targetThreads & J3dThread.RENDER_THREAD) != 0) { - synchronized (renderThreadData) { - J3dThreadData[] threads = (J3dThreadData []) - renderThreadData.toArray(false); - int i=renderThreadData.arraySize()-1; - J3dThreadData thr; - while (i>=0) { - thr = threads[i--]; - if ( thr.view.renderBinReady) { - thr.lastUpdateTime = time; - } - } - } - } - } - setWork(); - } - - /** - * Send a message to another Java 3D thread. - * This variant is only call by TimerThread for Sound Scheduler - */ - void sendRunMessage(long waitTime, View view, int targetThreads) { - - synchronized (timeLock) { - - long time = getTime(); - - if ((targetThreads & J3dThread.SOUND_SCHEDULER) != 0) { - if (view.soundScheduler != null) { - view.soundScheduler.threadData.lastUpdateTime = time; - } - // wakeup this procedure next time - // QUESTION: waitTime calculated some milliseconds BEFORE - // this methods getTime() called - shouldn't actual - // sound Complete time be passed by SoundScheduler - // QUESTION: will this wake up only soundScheduler associated - // with this view?? (since only it's lastUpdateTime is set) - // or all soundSchedulers?? - timerThread.addSoundSchedCond(time+waitTime); - } - } - setWork(); - } - - /** - * Send a message to another Java 3D thread. - * This variant is only called to update Render Thread - */ - void sendRunMessage(View v, int targetThreads) { - - synchronized (timeLock) { - long time = getTime(); - - if ((targetThreads & J3dThread.RENDER_THREAD) != 0) { - synchronized (renderThreadData) { - J3dThreadData[] threads = (J3dThreadData []) - renderThreadData.toArray(false); - int i=renderThreadData.arraySize()-1; - J3dThreadData thr; - while (i>=0) { - thr = threads[i--]; - if (thr.view == v && v.renderBinReady) { - thr.lastUpdateTime = time; - } - } - } - } - } - setWork(); - } - - - /** - * This sends a run message to the given threads. - */ - void sendRunMessage(VirtualUniverse u, int targetThreads) { - // We don't sendRunMessage to update structure except Behavior - - synchronized (timeLock) { - long time = getTime(); - - if ((targetThreads & J3dThread.BEHAVIOR_SCHEDULER) != 0) { - if (u.behaviorScheduler != null) { - u.behaviorScheduler.getThreadData(null, - null).lastUpdateTime = time; - } - } - - if ((targetThreads & J3dThread.UPDATE_BEHAVIOR) != 0) { - u.behaviorStructure.threadData.lastUpdateTime = time; - } - - if ((targetThreads & J3dThread.UPDATE_GEOMETRY) != 0) { - u.geometryStructure.threadData.lastUpdateTime = time; - } - - if ((targetThreads & J3dThread.UPDATE_SOUND) != 0) { - u.soundStructure.threadData.lastUpdateTime = time; - } - - if ((targetThreads & J3dThread.SOUND_SCHEDULER) != 0) { - synchronized (views) { - View v[] = (View []) views.toArray(false); - for (int i= views.arraySize()-1; i >=0; i--) { - if ((v[i].soundScheduler != null) && - (v[i].universe == u)) { - v[i].soundScheduler.threadData.lastUpdateTime = time; - } - } - } - } - - if ((targetThreads & J3dThread.RENDER_THREAD) != 0) { - - synchronized (renderThreadData) { - J3dThreadData[] threads = (J3dThreadData []) - renderThreadData.toArray(false); - int i=renderThreadData.arraySize()-1; - J3dThreadData thr; - while (i>=0) { - thr = threads[i--]; - if (thr.view.universe == u && thr.view.renderBinReady) { - thr.lastUpdateTime = time; - } - } - } - } - } - - setWork(); - } - - - /** - * Return a clone of View, we can't access - * individual element of View after getting the size - * in separate API call without synchronized views. - */ - UnorderList cloneView() { - return (UnorderList) views.clone(); - } - - /** - * Return true if view is already registered with MC - */ - boolean isRegistered(View view) { - return views.contains(view); - } - - /** - * This snapshots the time values to be used for this iteration. - * Note that this method is called without the timeLock held. - * We must synchronize on timeLock to prevent updating - * thread.lastUpdateTime from user thread in sendMessage() - * or sendRunMessage(). - */ - private void updateTimeValues() { - synchronized (timeLock) { - int i=0; - J3dThreadData lastThread=null; - J3dThreadData thread=null; - long lastTime = currentTime; - - currentTime = getTime(); - - J3dThreadData threads[] = (J3dThreadData []) - stateWorkThreads.toArray(false); - int size = stateWorkThreads.arraySize(); - - while (i<lastTransformStructureThread) { - thread = threads[i++]; - - if ((thread.lastUpdateTime > thread.lastRunTime) && - !thread.thread.userStop) { - lastThread = thread; - thread.needsRun = true; - thread.threadOpts = J3dThreadData.CONT_THREAD; - thread.lastRunTime = currentTime; - } else { - thread.needsRun = false; - } - } - - if (lastThread != null) { - lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; - lastThread = null; - } - - while (i<lastStructureUpdateThread) { - thread = threads[i++]; - if ((thread.lastUpdateTime > thread.lastRunTime) && - !thread.thread.userStop) { - lastThread = thread; - thread.needsRun = true; - thread.threadOpts = J3dThreadData.CONT_THREAD; - thread.lastRunTime = currentTime; - } else { - thread.needsRun = false; - } - } - if (lastThread != null) { - lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; - lastThread = null; - } - - while (i<size) { - thread = threads[i++]; - if ((thread.lastUpdateTime > thread.lastRunTime) && - !thread.thread.userStop) { - lastThread = thread; - thread.needsRun = true; - thread.threadOpts = J3dThreadData.CONT_THREAD; - thread.lastRunTime = currentTime; - } else { - thread.needsRun = false; - } - } - if (lastThread != null) { - lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; - lastThread = null; - } - - - threads = (J3dThreadData []) renderWorkThreads.toArray(false); - size = renderWorkThreads.arraySize(); - View v; - J3dThreadData lastRunThread = null; - waitTimestamp++; - sleepTime = 0L; - - boolean threadToRun = false; // Not currently used - - // Fix for Issue 12: loop through the list of threads, calling - // computeCycleTime() exactly once per view. This ensures that - // all threads for a given view see consistent values for - // isMinCycleTimeAchieve and sleepTime. - v = null; - for (i=0; i<size; i++) { - thread = threads[i]; - if (thread.view != v) { - thread.view.computeCycleTime(); - // Set sleepTime to the value needed to satify the - // minimum cycle time of the slowest view - if (thread.view.sleepTime > sleepTime) { - sleepTime = thread.view.sleepTime; - } - } - v = thread.view; - } - - v = null; - for (i=0; i<size; i++) { - thread = threads[i]; - if (thread.canvas == null) { // Only for swap thread - ((Object []) thread.threadArgs)[3] = null; - } - if ((thread.lastUpdateTime > thread.lastRunTime) && - !thread.thread.userStop) { - - if (thread.thread.lastWaitTimestamp == waitTimestamp) { - // This renderer thread is repeated. We must wait - // until all previous renderer threads done before - // allowing this thread to continue. Note that - // lastRunThread can't be null in this case. - waitTimestamp++; - if (thread.view != v) { - // A new View is start - v = thread.view; - threadToRun = true; - lastRunThread.threadOpts = - (J3dThreadData.STOP_TIMER | - J3dThreadData.WAIT_ALL_THREADS); - ((Object []) lastRunThread.threadArgs)[3] = lastRunThread.view; - thread.threadOpts = (J3dThreadData.START_TIMER | - J3dThreadData.CONT_THREAD); - } else { - if ((lastRunThread.threadOpts & - J3dThreadData.START_TIMER) != 0) { - lastRunThread.threadOpts = - (J3dThreadData.START_TIMER | - J3dThreadData.WAIT_ALL_THREADS); - - } else { - lastRunThread.threadOpts = - J3dThreadData.WAIT_ALL_THREADS; - } - thread.threadOpts = J3dThreadData.CONT_THREAD; - - } - } else { - if (thread.view != v) { - v = thread.view; - threadToRun = true; - // Although the renderer thread is not - // repeated. We still need to wait all - // previous renderer threads if new View - // start. - if (lastRunThread != null) { - lastRunThread.threadOpts = - (J3dThreadData.STOP_TIMER | - J3dThreadData.WAIT_ALL_THREADS); - ((Object []) lastRunThread.threadArgs)[3] - = lastRunThread.view; - } - thread.threadOpts = (J3dThreadData.START_TIMER | - J3dThreadData.CONT_THREAD); - } else { - thread.threadOpts = J3dThreadData.CONT_THREAD; - } - } - thread.thread.lastWaitTimestamp = waitTimestamp; - thread.needsRun = true; - thread.lastRunTime = currentTime; - lastRunThread = thread; - } else { - thread.needsRun = false; - } - } - - - if (lastRunThread != null) { - lastRunThread.threadOpts = - (J3dThreadData.STOP_TIMER | - J3dThreadData.WAIT_ALL_THREADS| - J3dThreadData.LAST_STOP_TIMER); - lockGeometry = true; - ((Object []) lastRunThread.threadArgs)[3] = lastRunThread.view; - } else { - lockGeometry = false; - } - } - - // Issue 275 - go to sleep without holding timeLock - // Sleep for the amount of time needed to satisfy the minimum - // cycle time for all views. - if (sleepTime > 0) { - // System.err.println("MasterControl: sleep(" + sleepTime + ")"); - try { - Thread.sleep(sleepTime); - } catch (InterruptedException e) { - System.err.println(e); - } - // System.err.println("MasterControl: done sleeping"); - } - } - - private void createUpdateThread(J3dStructure structure) { - final J3dStructure s = structure; - - if (s.updateThread == null) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - synchronized (rootThreadGroup) { - s.updateThread = new StructureUpdateThread( - rootThreadGroup, s, s.threadType); - s.updateThread.setPriority(threadPriority); - } - return null; - } - }); - s.updateThread.initialize(); - s.threadData.thread = s.updateThread; - // This takes into accout for thread that just destroy and - // create again. In this case the threadData may receive - // message before the thread actually created. We don't want - // the currentTime to overwrite the update time of which - // is set by threadData when get message. - s.threadData.lastUpdateTime = Math.max(currentTime, - s.threadData.lastUpdateTime); - } - } - - private void emptyMessageList(J3dStructure structure, View v) { - if (structure != null) { - if (v == null) { - if (structure.threadData != null) { - structure.threadData.thread = null; - } - - if (structure.updateThread != null) { - structure.updateThread.structure = null; - } - structure.updateThread = null; - } - boolean otherViewExist = false; - if ((v != null) && (v.universe != null)) { - // Check if there is any other View register with the - // same universe - for (int i=views.size()-1; i >= 0; i--) { - if (((View) views.get(i)).universe == v.universe) { - otherViewExist = true; - break; - } - } - } - - - UnorderList mlist = structure.messageList; - // Note that message is add at the end of array - synchronized (mlist) { - int size = mlist.size(); - if (size > 0) { - J3dMessage mess[] = (J3dMessage []) mlist.toArray(false); - J3dMessage m; - int i = 0; - - while (i < size) { - m = mess[i]; - if ((v == null) || (m.view == v) || - ((m.view == null) && !otherViewExist)) { - if (m.type == J3dMessage.INSERT_NODES) { - // There is another View register request - // immediately following, so no need - // to remove message. - break; - } - // Some other thread may still using this - // message so we should not directly - // add this message to free lists - m.decRefcount(); - mlist.removeOrdered(i); - size--; - } else { - i++; - } - } - } - } - } - } - - private void destroyUpdateThread(J3dStructure structure) { - // If unregisterView message got before EMPTY_UNIVERSE - // message, then updateThread is already set to null. - if (structure.updateThread != null) { - structure.updateThread.finish(); - structure.updateThread.structure = null; - structure.updateThread = null; - } - structure.threadData.thread = null; - structure.clearMessages(); - } - - /** - * This register a View with MasterControl. - * The View has at least one Canvas3D added to a container. - */ - private void registerView(View v) { - final VirtualUniverse univ = v.universe; - - if (views.contains(v) && regUniverseList.contains(univ)) { - return; // already register - } - - if (timerThread == null) { - // This handle the case when MC shutdown and restart in - // a series of pending request - running = true; - createMCThreads(); - } - // If viewId is null, assign one .. - v.assignViewId(); - - // Create thread if not done before - createUpdateThread(univ.behaviorStructure); - createUpdateThread(univ.geometryStructure); - createUpdateThread(univ.soundStructure); - createUpdateThread(univ.renderingEnvironmentStructure); - createUpdateThread(univ.transformStructure); - - // create Behavior scheduler - J3dThreadData threadData = null; - - if (univ.behaviorScheduler == null) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - synchronized (rootThreadGroup) { - univ.behaviorScheduler = new BehaviorScheduler( - rootThreadGroup, univ); - univ.behaviorScheduler.setPriority(threadPriority); - } - return null; - } - }); - univ.behaviorScheduler.initialize(); - univ.behaviorScheduler.userStop = v.stopBehavior; - threadData = univ.behaviorScheduler.getThreadData(null, null); - threadData.thread = univ.behaviorScheduler; - threadData.threadType = J3dThread.BEHAVIOR_SCHEDULER; - threadData.lastUpdateTime = Math.max(currentTime, - threadData.lastUpdateTime); - } - - createUpdateThread(v.renderBin); - createUpdateThread(v.soundScheduler); - - if (v.physicalEnvironment != null) { - v.physicalEnvironment.addUser(v); - } - // create InputDeviceScheduler - evaluatePhysicalEnv(v); - - regUniverseList.addUnique(univ); - views.addUnique(v); - } - - - - /** - * This unregister a View with MasterControl. - * The View no longer has any Canvas3Ds in a container. - */ - private void unregisterView(View v) { - - if (!views.remove(v)) { - v.active = false; - v.doneUnregister = true; - return; // already unregister - } - - if (v.active) { - viewDeactivate(v); - } - - if(J3dDebug.devPhase) { - J3dDebug.doDebug(J3dDebug.masterControl, J3dDebug.LEVEL_1, - "MC: Destroy Sound Scheduler and RenderBin Update thread"); - } - - v.soundScheduler.updateThread.finish(); - v.renderBin.updateThread.finish(); - v.soundScheduler.updateThread = null; - v.renderBin.updateThread = null; - - // remove VirtualUniverse related threads if Universe - // is empty - VirtualUniverse univ = v.universe; - - synchronized (timeLock) { - // The reason we need to sync. with timeLock is because we - // don't want user thread running sendMessage() to - // dispatch it in different structure queue when - // part of the structure list is empty at the same time. - // This will cause inconsistence in the message reference - // count. - emptyMessageList(v.soundScheduler, v); - emptyMessageList(v.renderBin, v); - - if (univ.isEmpty()) { - destroyUniverseThreads(univ); - } else { - emptyMessageList(univ.behaviorStructure, v); - emptyMessageList(univ.geometryStructure, v); - emptyMessageList(univ.soundStructure, v); - emptyMessageList(univ.renderingEnvironmentStructure, v); - emptyMessageList(univ.transformStructure, v); - } - } - - if (v.physicalEnvironment != null) { - v.physicalEnvironment.removeUser(v); - } - - // remove all InputDeviceScheduler if this is the last View - ArrayList<PhysicalEnvironment> list = new ArrayList<PhysicalEnvironment>(); - for (Enumeration<PhysicalEnvironment> e = PhysicalEnvironment.physicalEnvMap.keys(); e.hasMoreElements();) { - PhysicalEnvironment phyEnv = e.nextElement(); - InputDeviceScheduler sched = PhysicalEnvironment.physicalEnvMap.get(phyEnv); - boolean phyEnvHasUser = false; - for (int i = 0; i < phyEnv.users.size(); i++) { - if (views.contains(phyEnv.users.get(i))) { - // at least one registered view refer to it. - phyEnvHasUser = true; - break; - } - } - - if (!phyEnvHasUser) { - if (J3dDebug.devPhase) { - J3dDebug.doDebug(J3dDebug.masterControl, J3dDebug.LEVEL_1, - "MC: Destroy InputDeviceScheduler thread " - + sched); - } - sched.finish(); - phyEnv.inputsched = null; - list.add(phyEnv); - } - } - for (int i = 0; i < list.size(); i++) { - PhysicalEnvironment.physicalEnvMap.remove(list.get(i)); - } - - freeContext(v); - - if (views.isEmpty()) { - if(J3dDebug.devPhase) { - J3dDebug.doDebug(J3dDebug.masterControl, J3dDebug.LEVEL_1, - "MC: Destroy all Renderers"); - } - // remove all Renderers if this is the last View - for (Enumeration<Renderer> e = Screen3D.deviceRendererMap.elements(); - e.hasMoreElements(); ) { - Renderer rdr = e.nextElement(); - Screen3D scr; - - rendererCleanupArgs[2] = REMOVEALLCTXS_CLEANUP; - runMonitor(RUN_RENDERER_CLEANUP, null, null, null, rdr); - scr = rdr.onScreen; - if (scr != null) { - if (scr.renderer != null) { - rendererCleanupArgs[2] = REMOVEALLCTXS_CLEANUP; - runMonitor(RUN_RENDERER_CLEANUP, null, null, - null, scr.renderer); - scr.renderer = null; - } - - } - scr = rdr.offScreen; - if (scr != null) { - if (scr.renderer != null) { - rendererCleanupArgs[2] = REMOVEALLCTXS_CLEANUP; - runMonitor(RUN_RENDERER_CLEANUP, null, null, - null, scr.renderer); - scr.renderer = null; - } - } - rdr.onScreen = null; - rdr.offScreen = null; - } - - // cleanup ThreadData corresponds to the view in renderer - for (Enumeration<Renderer> e = Screen3D.deviceRendererMap.elements(); - e.hasMoreElements(); ) { - e.nextElement().cleanup(); - } - // We have to reuse renderer even though MC exit - // see bug 4363279 - // Screen3D.deviceRendererMap.clear(); - - } else { - // cleanup ThreadData corresponds to the view in renderer - for (Enumeration<Renderer> e = Screen3D.deviceRendererMap.elements(); - e.hasMoreElements(); ) { - e.nextElement().cleanupView(); - } - } - - - freeMessageList.add(univ); - freeMessageList.add(v); - - evaluateAllCanvases(); - stateWorkThreads.clear(); - renderWorkThreads.clear(); - requestRenderWorkThreads.clear(); - threadListsChanged = true; - - // This notify VirtualUniverse waitForMC() thread to continue - v.doneUnregister = true; - } - - - /** - * This procedure create MC thread that start together with MC. - */ - void createMCThreads() { - - // There is only one renderingAttributesUpdate Thread globally - createUpdateThread(renderingAttributesStructure); - - // Create timer thread - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - synchronized (rootThreadGroup) { - timerThread = new TimerThread(rootThreadGroup); - timerThread.setPriority(threadPriority); - } - return null; - } - }); - timerThread.start(); - - // Create notification thread - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - synchronized (rootThreadGroup) { - notificationThread = new NotificationThread(rootThreadGroup); - notificationThread.setPriority(threadPriority); - } - return null; - } - }); - notificationThread.start(); - } - - /** - * Destroy all VirtualUniverse related threads. - * This procedure may call two times when Locale detach in a - * live viewPlatform. - */ - private void destroyUniverseThreads(VirtualUniverse univ) { - - if (regUniverseList.contains(univ)) { - if (J3dDebug.devPhase) { - J3dDebug.doDebug(J3dDebug.masterControl, J3dDebug.LEVEL_1, - "MC: Destroy universe threads " + univ); - } - destroyUpdateThread(univ.behaviorStructure); - destroyUpdateThread(univ.geometryStructure); - destroyUpdateThread(univ.soundStructure); - destroyUpdateThread(univ.renderingEnvironmentStructure); - destroyUpdateThread(univ.transformStructure); - univ.behaviorScheduler.finish(); - univ.behaviorScheduler.free(); - univ.behaviorScheduler = null; - univ.initMCStructure(); - activeUniverseList.remove(univ); - regUniverseList.remove(univ); - } else { - emptyMessageList(univ.behaviorStructure, null); - emptyMessageList(univ.geometryStructure, null); - emptyMessageList(univ.soundStructure, null); - emptyMessageList(univ.renderingEnvironmentStructure, null); - emptyMessageList(univ.transformStructure, null); - } - - if (regUniverseList.isEmpty() && views.isEmpty()) { - if(J3dDebug.devPhase) { - J3dDebug.doDebug(J3dDebug.masterControl, J3dDebug.LEVEL_1, - "MC: Destroy RenderingAttributes Update and Timer threads"); - } - if (renderingAttributesStructure.updateThread != null) { - renderingAttributesStructure.updateThread.finish(); - renderingAttributesStructure.updateThread = null; - } - renderingAttributesStructure.messageList.clear(); - renderingAttributesStructure.objList = new ArrayList<J3dMessage>(); - renderingAttributesStructure = new RenderingAttributesStructure(); - if (timerThread != null) { - timerThread.finish(); - timerThread = null; - } - if (notificationThread != null) { - notificationThread.finish(); - notificationThread = null; - } - - // shouldn't all of these be synchronized ??? - synchronized (VirtualUniverse.mc.deviceScreenMap) { - deviceScreenMap.clear(); - } - - mirrorObjects.clear(); - // Note: We should not clear the DISPLAYLIST/TEXTURE - // list here because other structure may release them - // later - - for(int i=0; i<canvasIds.length; i++) { - canvasIds[i] = false; - } - canvasFreeIndex = 0; - - renderOnceList.clear(); - timestampUpdateList.clear(); - - defaultRenderMethod = null; - text3DRenderMethod = null; - vertexArrayRenderMethod = null; - displayListRenderMethod = null; - compressedGeometryRenderMethod = null; - orientedShape3DRenderMethod = null; - // Terminate MC thread - running = false; - } - } - - /** - * Note that we have to go through all views instead of - * evaluate only the canvas in a single view since each screen - * may share by multiple view - */ - private void evaluateAllCanvases() { - - synchronized (renderThreadData) { - // synchronized to prevent lost message when - // renderThreadData is clear - - // First remove all renderrenderThreadData - renderThreadData.clear(); - - // Second reset canvasCount to zero - View viewArr[] = (View []) views.toArray(false); - for (int i=views.size()-1; i>=0; i--) { - viewArr[i].getCanvasList(true); // force canvas cache update - Screen3D screens[] = viewArr[i].getScreens(); - for (int j=screens.length-1; j>=0; j--) { - screens[j].canvasCount = 0; - } - } - - - // Third create render thread and message thread - for (int i=views.size()-1; i>=0; i--) { - View v = viewArr[i]; - Canvas3D canvasList[][] = v.getCanvasList(false); - if (!v.active) { - continue; - } - - for (int j=canvasList.length-1; j>=0; j--) { - boolean added = false; - - for (int k=canvasList[j].length-1; k>=0; k--) { - Canvas3D cv = canvasList[j][k]; - - final Screen3D screen = cv.screen; - - if (cv.active) { - if (screen.canvasCount++ == 0) { - // Create Renderer, one per screen - if (screen.renderer == null) { - // get the renderer created for the graphics - // device of the screen of the canvas - // No need to synchronized since only - // MC use it. - Renderer rdr = Screen3D.deviceRendererMap.get(cv.screen.graphicsDevice); - if (rdr == null) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - - synchronized (rootThreadGroup) { - screen.renderer - = new Renderer( - rootThreadGroup); - screen.renderer.setPriority(threadPriority); - } - return null; - } - }); - screen.renderer.initialize(); - Screen3D.deviceRendererMap.put(screen.graphicsDevice, screen.renderer); - } else { - screen.renderer = rdr; - } - } - } - // offScreen canvases will be handled by the - // request renderer, so don't add offScreen canvas - // the render list - // - // Issue 131: Automatic offscreen canvases need to - // be added to onscreen list. Special case. - // - // TODO KCR Issue 131: this should probably be - // changed to a list of screens since multiple - // off-screen canvases (either auto or manual) can - // be used by the same renderer - if (!cv.manualRendering) { - screen.renderer.onScreen = screen; - } else { - screen.renderer.offScreen = screen; - continue; - } - - if (!added) { - // Swap message data thread, one per - // screen only. Note that we don't set - // lastUpdateTime for this thread so - // that it won't run in the first round - J3dThreadData renderData = - screen.renderer.getThreadData(v, null); - renderThreadData.add(renderData); - - // only if renderBin is ready then we - // update the lastUpdateTime to make it run - if (v.renderBinReady) { - renderData.lastUpdateTime = - Math.max(currentTime, - renderData.lastUpdateTime); - } - added = true; - } - // Renderer message data thread - J3dThreadData renderData = - screen.renderer.getThreadData(v, cv); - renderThreadData.add(renderData); - if (v.renderBinReady) { - renderData.lastUpdateTime = - Math.max(currentTime, - renderData.lastUpdateTime); - } - } - } - } - - } - } - - threadListsChanged = true; - } - - private void evaluatePhysicalEnv(View v) { - final PhysicalEnvironment env = v.physicalEnvironment; - - if (env.inputsched == null) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - synchronized (rootThreadGroup) { - env.inputsched = new InputDeviceScheduler( - rootThreadGroup, - env); - env.inputsched.setPriority(threadPriority); - } - return null; - } - }); - env.inputsched.start(); - PhysicalEnvironment.physicalEnvMap.put(env, env.inputsched); - } - threadListsChanged = true; - } - - final private void addToStateThreads(J3dThreadData threadData) { - if (threadData.thread.active) { - stateWorkThreads.add(threadData); - } - } - - - private void assignNewPrimaryView(VirtualUniverse univ) { - - View currentPrimary = univ.getCurrentView(); - - if (currentPrimary != null) { - currentPrimary.primaryView = false; - } - - View v[] = (View []) views.toArray(false); - int nviews = views.size(); - for (int i=0; i<nviews; i++) { - View view = v[i]; - if (view.active && view.isRunning && - (univ == view.universe)) { - view.primaryView = true; - univ.setCurrentView(view); - return; - } - } - univ.setCurrentView(null); - } - - - /** - * This returns the default RenderMethod - */ - RenderMethod getDefaultRenderMethod() { - if (defaultRenderMethod == null) { - defaultRenderMethod = new DefaultRenderMethod(); - } - return defaultRenderMethod; - } - - /** - * This returns the text3d RenderMethod - */ - RenderMethod getText3DRenderMethod() { - if (text3DRenderMethod == null) { - text3DRenderMethod = new Text3DRenderMethod(); - } - return text3DRenderMethod; - } - - - /** - * This returns the vertexArray RenderMethod - */ - RenderMethod getVertexArrayRenderMethod() { - if (vertexArrayRenderMethod == null) { - vertexArrayRenderMethod = new VertexArrayRenderMethod(); - } - return vertexArrayRenderMethod; - } - - /** - * This returns the displayList RenderMethod - */ - RenderMethod getDisplayListRenderMethod() { - if (displayListRenderMethod == null) { - displayListRenderMethod = new DisplayListRenderMethod(); - } - return displayListRenderMethod; - } - - /** - * This returns the compressed geometry RenderMethod - */ - RenderMethod getCompressedGeometryRenderMethod() { - if (compressedGeometryRenderMethod == null) { - compressedGeometryRenderMethod = - new CompressedGeometryRenderMethod(); - } - return compressedGeometryRenderMethod; - } - - /** - * This returns the oriented shape3d RenderMethod - */ - RenderMethod getOrientedShape3DRenderMethod() { - if (orientedShape3DRenderMethod == null) { - orientedShape3DRenderMethod = new OrientedShape3DRenderMethod(); - } - return orientedShape3DRenderMethod; - } - - /** - * This notifies MasterControl that the given view has been activated - */ - private void viewActivate(View v) { - - VirtualUniverse univ = v.universe; - - if (univ == null) { - return; - } - - if (!views.contains(v) || !regUniverseList.contains(univ)) { - registerView(v); - } else if (v.active) { - evaluateAllCanvases(); - return; - } - - if ((univ.activeViewCount == 0)) { - univ.geometryStructure.resetConditionMet(); - univ.behaviorStructure.resetConditionMet(); - } - - if (v.isRunning) { - numActiveViews++; - univ.activeViewCount++; - renderingAttributesStructure.updateThread.active = true; - univ.transformStructure.updateThread.active = true; - univ.geometryStructure.updateThread.active = true; - univ.soundStructure.updateThread.active = true; - univ.renderingEnvironmentStructure.updateThread.active = true; - } - univ.behaviorScheduler.active = true; - univ.behaviorStructure.updateThread.active = true; - - - activeUniverseList.addUnique(univ); - - if (v.isRunning) { - v.soundScheduler.activate(); - v.renderBin.updateThread.active = true; - } - v.active = true; - - if (v.physicalEnvironment.activeViewRef++ == 0) { - v.physicalEnvironment.inputsched.activate(); - } - - - if (univ.getCurrentView() == null) { - assignNewPrimaryView(univ); - } - - evaluateAllCanvases(); - v.inRenderThreadData = true; - threadListsChanged = true; - // Notify GeometryStructure to query visible atom again - // We should send message instead of just setting - // v.vDirtyMask = View.VISIBILITY_POLICY_DIRTY; - // since RenderBin may not run immediately next time. - // In this case the dirty flag will lost since - // updateViewCache() will reset it to 0. - v.renderBin.reactivateView = true; - } - - /** - * Release context associate with view - */ - private void freeContext(View v) { - Canvas3D[][] canvasList = v.getCanvasList(false); - - for (int j=canvasList.length-1; j>=0; j--) { - for (int k=canvasList[j].length-1; k>=0; k--) { - Canvas3D cv = canvasList[j][k]; - if (!cv.validCanvas) { - if ((cv.screen != null) && - (cv.screen.renderer != null)) { - rendererCleanupArgs[1] = cv; - rendererCleanupArgs[2] = FREECONTEXT_CLEANUP; - runMonitor(RUN_RENDERER_CLEANUP, null, null, null, - cv.screen.renderer); - rendererCleanupArgs[1] = null; - } - } - } - } - } - - /** - * This notifies MasterControl that the given view has been deactivated - */ - private void viewDeactivate(View v) { - - if (!views.contains(v) || !v.active) { - v.active = false; - evaluateAllCanvases(); - return; - } - - VirtualUniverse univ = v.universe; - - if (v.isRunning) { - // if stopView() invoke before, no need to decrement count - --numActiveViews; - --univ.activeViewCount; - } - - if (numActiveViews == 0) { - renderingAttributesStructure.updateThread.active = false; - } - - if (univ.activeViewCount == 0) { - // check if destroyUniverseThread invoked before - if (univ.behaviorScheduler != null) { - univ.behaviorScheduler.deactivate(); - univ.transformStructure.updateThread.active = false; - univ.geometryStructure.updateThread.active = false; - univ.behaviorStructure.updateThread.active = false; - univ.soundStructure.updateThread.active = false; - univ.renderingEnvironmentStructure.updateThread.active - = false; - activeUniverseList.remove(univ); - } - } - - v.soundScheduler.deactivate(); - v.renderBin.updateThread.active = false; - v.active = false; - if (--v.physicalEnvironment.activeViewRef == 0) { - v.physicalEnvironment.inputsched.deactivate(); - } - assignNewPrimaryView(univ); - - - evaluateAllCanvases(); - - freeContext(v); - - v.inRenderThreadData = false; - threadListsChanged = true; - } - - - /** - * This notifies MasterControl to start given view - */ - private void startView(View v) { - - if (!views.contains(v) || v.isRunning || !v.active) { - v.isRunning = true; - return; - } - - numActiveViews++; - renderingAttributesStructure.updateThread.active = true; - - VirtualUniverse univ = v.universe; - - univ.activeViewCount++; - univ.transformStructure.updateThread.active = true; - univ.geometryStructure.updateThread.active = true; - univ.soundStructure.updateThread.active = true; - univ.renderingEnvironmentStructure.updateThread.active = true; - v.renderBin.updateThread.active = true; - v.soundScheduler.activate(); - v.isRunning = true; - if (univ.getCurrentView() == null) { - assignNewPrimaryView(univ); - } - threadListsChanged = true; - } - - - /** - * This notifies MasterControl to stop given view - */ - private void stopView(View v) { - if (!views.contains(v) || !v.isRunning || !v.active) { - v.isRunning = false; - return; - } - - if (--numActiveViews == 0) { - renderingAttributesStructure.updateThread.active = false; - } - VirtualUniverse univ = v.universe; - - if (--univ.activeViewCount == 0) { - univ.transformStructure.updateThread.active = false; - univ.geometryStructure.updateThread.active = false; - univ.renderingEnvironmentStructure.updateThread.active = false; - univ.soundStructure.updateThread.active = false; - } - - v.renderBin.updateThread.active = false; - v.soundScheduler.deactivate(); - v.isRunning = false; - assignNewPrimaryView(univ); - threadListsChanged = true; - } - - // Call from user thread - void addInputDeviceScheduler(InputDeviceScheduler ds) { - synchronized (inputDeviceThreads) { - inputDeviceThreads.add(ds); - if (inputDeviceThreads.size() == 1) { - timerThread.addInputDeviceSchedCond(); - } - } - postRequest(INPUTDEVICE_CHANGE, null); - } - - // Call from user thread - void removeInputDeviceScheduler(InputDeviceScheduler ds) { - inputDeviceThreads.remove(ds); - postRequest(INPUTDEVICE_CHANGE, null); - } - - /** - * Add an object to the mirror object list - */ - void addMirrorObject(ObjectUpdate o) { - mirrorObjects.add(o); - } - - /** - * This updates any mirror objects. It is called when threads - * are done. - */ - void updateMirrorObjects() { - ObjectUpdate objs[] = (ObjectUpdate []) mirrorObjects.toArray(false); - int sz = mirrorObjects.arraySize(); - - for (int i = 0; i< sz; i++) { - objs[i].updateObject(); - } - mirrorObjects.clear(); - } - - - /** - * This fun little method does all the hard work of setting up the - * work thread list. - */ - private void updateWorkThreads() { - - stateWorkThreads.clear(); - renderWorkThreads.clear(); - requestRenderWorkThreads.clear(); - - // First the global rendering attributes structure update - if (numActiveViews > 0) { - addToStateThreads(renderingAttributesStructure.getUpdateThreadData()); - } - - // Next, each of the transform structure updates - VirtualUniverse universes[] = (VirtualUniverse []) - activeUniverseList.toArray(false); - VirtualUniverse univ; - int i; - int size = activeUniverseList.arraySize(); - - for (i=size-1; i>=0; i--) { - addToStateThreads(universes[i].transformStructure.getUpdateThreadData()); - } - lastTransformStructureThread = stateWorkThreads.size(); - - // Next, the GeometryStructure, BehaviorStructure, - // RenderingEnvironmentStructure, and SoundStructure - for (i=size-1; i>=0; i--) { - univ = universes[i]; - addToStateThreads(univ.geometryStructure.getUpdateThreadData()); - addToStateThreads(univ.behaviorStructure.getUpdateThreadData()); - addToStateThreads(univ.renderingEnvironmentStructure.getUpdateThreadData()); - addToStateThreads(univ.soundStructure.getUpdateThreadData()); - } - - lastStructureUpdateThread = stateWorkThreads.size(); - - // Next, the BehaviorSchedulers - for (i=size-1; i>=0; i--) { - addToStateThreads(universes[i].behaviorScheduler. - getThreadData(null, null)); - } - - - // Now InputDeviceScheduler - - InputDeviceScheduler ds[] = (InputDeviceScheduler []) - inputDeviceThreads.toArray(true); - for (i=inputDeviceThreads.size()-1; i >=0; i--) { - J3dThreadData threadData = ds[i].getThreadData(); - threadData.thread.active = true; - addToStateThreads(threadData); - } - - // Now the RenderBins and SoundSchedulers - View viewArr[] = (View []) views.toArray(false); - J3dThreadData thread; - - for (i=views.size()-1; i>=0; i--) { - View v = viewArr[i]; - if (v.active && v.isRunning) { - addToStateThreads(v.renderBin.getUpdateThreadData()); - addToStateThreads(v.soundScheduler.getUpdateThreadData()); - Canvas3D canvasList[][] = v.getCanvasList(false); - int longestScreenList = v.getLongestScreenList(); - Object args[] = null; - // renderer render - for (int j=0; j<longestScreenList; j++) { - for (int k=0; k < canvasList.length; k++) { - if (j < canvasList[k].length) { - Canvas3D cv = canvasList[k][j]; - // Issue 131: setup renderer unless manualRendering - if (cv.active && cv.isRunningStatus && !cv.manualRendering ) { - if (cv.screen.renderer == null) { - continue; - } - thread = cv.screen.renderer.getThreadData(v, cv); - renderWorkThreads.add(thread); - args = (Object []) thread.threadArgs; - args[0] = RENDER; - args[1] = cv; - args[2] = v; - } - } - } - } - - // renderer swap - for (int j=0; j<canvasList.length; j++) { - for (int k=0; k < canvasList[j].length; k++) { - Canvas3D cv = canvasList[j][k]; - // create swap thread only if there is at - // least one active canvas - // Issue 131: only if not manualRendering - if (cv.active && cv.isRunningStatus && !cv.manualRendering) { - if (cv.screen.renderer == null) { - // Should not happen - continue; - } - thread = cv.screen.renderer.getThreadData(v, null); - renderWorkThreads.add(thread); - args = (Object []) thread.threadArgs; - args[0] = SWAP; - args[1] = v; - args[2] = canvasList[j]; - break; - } - } - } - } - } - - thread = null; - - for (Enumeration<Renderer> e = Screen3D.deviceRendererMap.elements(); - e.hasMoreElements(); ) { - Renderer rdr = e.nextElement(); - thread = rdr.getThreadData(null, null); - requestRenderWorkThreads.add(thread); - thread.threadOpts = J3dThreadData.CONT_THREAD; - ((Object[]) thread.threadArgs)[0] = REQUESTRENDER; - } - - if (thread != null) { - thread.threadOpts |= J3dThreadData.WAIT_ALL_THREADS; - } - - threadListsChanged = false; - - // dumpWorkThreads(); - } - - - void dumpWorkThreads() { - System.err.println("-----------------------------"); - System.err.println("MasterControl/dumpWorkThreads"); - - J3dThreadData threads[]; - int size = 0; - - for (int k=0; k<3; k++) { - switch (k) { - case 0: - threads = (J3dThreadData []) stateWorkThreads.toArray(false); - size = stateWorkThreads.arraySize(); - break; - case 1: - threads = (J3dThreadData []) renderWorkThreads.toArray(false); - size = renderWorkThreads.arraySize(); - break; - default: - threads = (J3dThreadData []) requestRenderWorkThreads.toArray(false); - size = requestRenderWorkThreads.arraySize(); - break; - } - - for (int i=0; i<size; i++) { - J3dThreadData thread = threads[i]; - System.err.println("Thread " + i + ": " + thread.thread); - System.err.println("\tOps: " + thread.threadOpts); - if (thread.threadArgs != null) { - Object[] args = (Object[]) thread.threadArgs; - System.err.print("\tArgs: "); - for (int j=0; j<args.length; j++) { - System.err.print(args[j] + " "); - } - } - System.err.println(""); - } - } - System.err.println("-----------------------------"); - } - - - /** - * A convienence wrapper function for various parts of the system - * to force MC to run. - */ - final void setWork() { - runMonitor(SET_WORK, null, null, null, null); - } - - final void setWorkForRequestRenderer() { - runMonitor(SET_WORK_FOR_REQUEST_RENDERER, null, null, null, null); - } - - /** - * Call from GraphicsConfigTemplate to evaluate current - * capabilities using Renderer thread to invoke native - * graphics library functions. This avoid MT-safe problem - * when using thread directly invoke graphics functions. - */ - void sendRenderMessage(GraphicsConfiguration gc, - Object arg, Integer mtype) { - Renderer rdr = createRenderer(gc); - J3dMessage renderMessage = new J3dMessage(); - renderMessage.threads = J3dThread.RENDER_THREAD; - renderMessage.type = J3dMessage.RENDER_IMMEDIATE; - renderMessage.universe = null; - renderMessage.view = null; - renderMessage.args[0] = null; - renderMessage.args[1] = arg; - renderMessage.args[2] = mtype; - rdr.rendererStructure.addMessage(renderMessage); - setWorkForRequestRenderer(); - } - - // Issue for Issue 175 - // Pass DestroyCtxAndOffScreenBuffer to the Renderer thread for execution. - void sendDestroyCtxAndOffScreenBuffer(Canvas3D c) { - // Assertion check. Look for comment in sendCreateOffScreenBuffer. - GraphicsDevice gd = c.graphicsConfiguration.getDevice(); - assert Screen3D.deviceRendererMap.get(gd) != null; - - synchronized (mcThreadLock) { - // Issue 364: create master control thread if needed - createMasterControlThread(); - assert mcThread != null; - - Renderer rdr = createRenderer(c.graphicsConfiguration); - J3dMessage createMessage = new J3dMessage(); - createMessage.threads = J3dThread.RENDER_THREAD; - createMessage.type = J3dMessage.DESTROY_CTX_AND_OFFSCREENBUFFER; - createMessage.universe = null; - createMessage.view = null; - createMessage.args[0] = c; - // Fix for issue 340: send display, drawable & ctx in msg - createMessage.args[1] = Long.valueOf(0L); - createMessage.args[2] = c.drawable; - createMessage.args[3] = c.ctx; - rdr.rendererStructure.addMessage(createMessage); - synchronized (requestObjList) { - setWorkForRequestRenderer(); - pendingRequest = true; - } - } - } - - // Fix for Issue 18 - // Pass CreateOffScreenBuffer to the Renderer thread for execution. - void sendCreateOffScreenBuffer(Canvas3D c) { - // Assertion check that the renderer has already been created. - // If it hasn't, this is very, very bad because it opens up - // the possibility of an MT race condition since this method - // can be called from the user's thread, possibly at the same - // time as the MasterControl thread is trying to create a new - // Renderer. Fortunately, this should never happen since both - // the GraphicsTemplate3D methods that return a valid Graphics - // Configuration and the Canvas3D constructor will ultimately - // cause a renderer to be created via sendRenderMessage(). - GraphicsDevice gd = c.graphicsConfiguration.getDevice(); - J3dDebug.doAssert((Screen3D.deviceRendererMap.get(gd) != null), - "Screen3D.deviceRendererMap.get(gd) != null"); - - synchronized (mcThreadLock) { - // Create master control thread if needed - createMasterControlThread(); - assert mcThread != null; - - // Fix for Issue 72 : call createRenderer rather than getting - // the renderer from the canvas.screen object - Renderer rdr = createRenderer(c.graphicsConfiguration); - J3dMessage createMessage = new J3dMessage(); - createMessage.threads = J3dThread.RENDER_THREAD; - createMessage.type = J3dMessage.CREATE_OFFSCREENBUFFER; - createMessage.universe = null; - createMessage.view = null; - createMessage.args[0] = c; - rdr.rendererStructure.addMessage(createMessage); - synchronized (requestObjList) { - setWorkForRequestRenderer(); - pendingRequest = true; - } - } - } - - // Issue 347 - Pass AllocateCanvasId to the Renderer thread for execution - void sendAllocateCanvasId(Canvas3D c) { - synchronized (mcThreadLock) { - // Issue 364: create master control thread if needed - createMasterControlThread(); - assert mcThread != null; - - Renderer rdr = createRenderer(c.graphicsConfiguration); - J3dMessage createMessage = new J3dMessage(); - createMessage.threads = J3dThread.RENDER_THREAD; - createMessage.type = J3dMessage.ALLOCATE_CANVASID; - createMessage.universe = null; - createMessage.view = null; - createMessage.args[0] = c; - rdr.rendererStructure.addMessage(createMessage); - synchronized (requestObjList) { - setWorkForRequestRenderer(); - pendingRequest = true; - } - } - } - - // Issue 347 - Pass AllocateCanvasId to the Renderer thread for execution - void sendFreeCanvasId(Canvas3D c) { - synchronized (mcThreadLock) { - // Issue 364: create master control thread if needed - createMasterControlThread(); - assert mcThread != null; - - Renderer rdr = createRenderer(c.graphicsConfiguration); - J3dMessage createMessage = new J3dMessage(); - createMessage.threads = J3dThread.RENDER_THREAD; - createMessage.type = J3dMessage.FREE_CANVASID; - createMessage.universe = null; - createMessage.view = null; - createMessage.args[0] = c; - rdr.rendererStructure.addMessage(createMessage); - synchronized (requestObjList) { - setWorkForRequestRenderer(); - pendingRequest = true; - } - } - } - - - /** - * This is the MasterControl work method for Java 3D - */ - void doWork() { - runMonitor(CHECK_FOR_WORK, null, null, null, null); - - synchronized (timeLock) { - synchronized (requestObjList) { - if (pendingRequest) { - handlePendingRequest(); - } - } - } - - if (!running) { - return; - } - - if (threadListsChanged) { // Check for new Threads - updateWorkThreads(); - } - - synchronized (timeLock) { - // This is neccesary to prevent updating - // thread.lastUpdateTime from user thread - // in sendMessage() or sendRunMessage() - updateTimeValues(); - } - - //This is temporary until the view model is updated - View v[] = (View []) views.toArray(false); - for (int i=views.size()-1; i>=0; i--) { - if (v[i].active) { - v[i].updateViewCache(); - // update OrientedShape3D - if ((v[i].viewCache.vcDirtyMask != 0 && - !v[i].renderBin.orientedRAs.isEmpty()) || - (v[i].renderBin.cachedDirtyOrientedRAs != null && - !v[i].renderBin.cachedDirtyOrientedRAs.isEmpty())) { - v[i].renderBin.updateOrientedRAs(); - } - } - } - - runMonitor(RUN_THREADS, stateWorkThreads, renderWorkThreads, - requestRenderWorkThreads, null); - - if (renderOnceList.size() > 0) { - clearRenderOnceList(); - } - - manageMemory(); - - } - - private void handlePendingRequest() { - - Object objs[]; - Integer types[]; - int size; - boolean rendererRun = false; - - objs = requestObjList.toArray(false); - types = (Integer []) requestTypeList.toArray(false); - size = requestObjList.size(); - - for (int i=0; i < size; i++) { - // need to process request in order - Integer type = types[i]; - Object o = objs[i]; - if (type == RESET_CANVAS) { - Canvas3D cv = (Canvas3D) o; - if ((cv.screen != null) && - (cv.screen.renderer != null)) { - rendererCleanupArgs[1] = o; - rendererCleanupArgs[2] = RESETCANVAS_CLEANUP; - runMonitor(RUN_RENDERER_CLEANUP, null, null, null, - cv.screen.renderer); - rendererCleanupArgs[1] = null; - } - cv.reset(); - cv.view = null; - cv.computeViewCache(); - } - else if (type == ACTIVATE_VIEW) { - viewActivate((View) o); - } - else if (type == DEACTIVATE_VIEW) { - viewDeactivate((View) o); - } else if (type == REEVALUATE_CANVAS) { - evaluateAllCanvases(); - } else if (type == INPUTDEVICE_CHANGE) { - inputDeviceThreads.clearMirror(); - threadListsChanged = true; - } else if (type == START_VIEW) { - startView((View) o); - } else if (type == STOP_VIEW) { - View v = (View) o; - // Collision takes 3 rounds to finish its request - if (++v.stopViewCount > 4) { - v.stopViewCount = -1; // reset counter - stopView(v); - } else { - tempViewList.add(v); - } - } else if (type == UNREGISTER_VIEW) { - unregisterView((View) o); - } else if (type == PHYSICAL_ENV_CHANGE) { - evaluatePhysicalEnv((View) o); - } else if (type == EMPTY_UNIVERSE) { - // Issue 81: We need to process this message as long - // as there are no views associated with this - // universe. Previously, this message was ignored if - // there were views associated with *any* universe, - // which led to a memory / thread leak. - boolean foundView = false; - VirtualUniverse univ = (VirtualUniverse) o; - View v[] = (View []) views.toArray(false); - for (int j = views.size() - 1; j >= 0; j--) { - if (v[j].universe == univ) { - foundView = true; - break; - } - } - if (!foundView) { - destroyUniverseThreads(univ); - threadListsChanged = true; - } - } else if (type == START_RENDERER) { - if (o instanceof Canvas3D) { - Canvas3D c3d = (Canvas3D) o; - if (!c3d.isFatalError()) { - c3d.isRunningStatus = true; - } - } else { - ((Renderer) o).userStop = false; - } - threadListsChanged = true; - } else if (type == STOP_RENDERER) { - if (o instanceof Canvas3D) { - ((Canvas3D) o).isRunningStatus = false; - } else { - ((Renderer) o).userStop = true; - } - threadListsChanged = true; - } else if (type == RENDER_ONCE) { - View v = (View) o; - // temporary start View for renderonce - // it will stop afterwards - startView(v); - renderOnceList.add(v); - sendRunMessage(v, J3dThread.UPDATE_RENDER); - threadListsChanged = true; - rendererRun = true; - } else if (type == FREE_CONTEXT) { - Canvas3D cv = (Canvas3D ) ((Object []) o)[0]; - if ((cv.screen != null) && - (cv.screen.renderer != null)) { - rendererCleanupArgs[1] = o; - rendererCleanupArgs[2] = REMOVECTX_CLEANUP; - runMonitor(RUN_RENDERER_CLEANUP, null, null, null, - cv.screen.renderer); - rendererCleanupArgs[1] = null; - } - rendererRun = true; - } else if (type == FREE_DRAWING_SURFACE) { - Pipeline.getPipeline().freeDrawingSurfaceNative(o); - } else if (type == GETBESTCONFIG) { - GraphicsConfiguration gc = ((GraphicsConfiguration []) - ((GraphicsConfigTemplate3D) o).testCfg)[0]; - sendRenderMessage(gc, o, type); - rendererRun = true; - } else if (type == ISCONFIGSUPPORT) { - GraphicsConfiguration gc = (GraphicsConfiguration) - ((GraphicsConfigTemplate3D) o).testCfg; - sendRenderMessage(gc, o, type); - rendererRun = true; - } else if ((type == SET_GRAPHICSCONFIG_FEATURES) || - (type == SET_QUERYPROPERTIES)) { - GraphicsConfiguration gc = ((Canvas3D)o).graphicsConfiguration; - sendRenderMessage(gc, o, type); - rendererRun = true; - } else if (type == SET_VIEW) { - Canvas3D cv = (Canvas3D) o; - cv.view = cv.pendingView; - cv.computeViewCache(); - } - } - - // Do it only after all universe/View is register - for (int i=0; i < size; i++) { - Integer type = types[i]; - if (type == FREE_MESSAGE) { - if (objs[i] instanceof VirtualUniverse) { - VirtualUniverse u = (VirtualUniverse) objs[i]; - if (!regUniverseList.contains(u)) { - emptyMessageList(u.behaviorStructure, null); - emptyMessageList(u.geometryStructure, null); - emptyMessageList(u.soundStructure, null); - emptyMessageList(u.renderingEnvironmentStructure, null); - } - } else if (objs[i] instanceof View) { - View v = (View) objs[i]; - if (!views.contains(v)) { - emptyMessageList(v.soundScheduler, v); - emptyMessageList(v.renderBin, v); - if (v.resetUnivCount == v.universeCount) { - v.reset(); - v.universe = null; - if (running == false) { - // MC is about to terminate - - /* - // Don't free list cause there may - // have some other thread returning ID - // after it. - FreeListManager.clearList(FreeListManager.DISPLAYLIST); - FreeListManager.clearList(FreeListManager.TEXTURE2D); - FreeListManager.clearList(FreeListManager.TEXTURE3D); - - synchronized (textureIdLock) { - textureIdCount = 0; - } - */ - } - } - } - } - - } - - } - requestObjList.clear(); - requestTypeList.clear(); - - size = tempViewList.size(); - if (size > 0) { - if (running) { - for (int i=0; i < size; i++) { - requestTypeList.add(STOP_VIEW); - requestObjList.add(tempViewList.get(i)); - } - setWork(); - } else { // MC will shutdown - for (int i=0; i < size; i++) { - View v = (View) tempViewList.get(i); - v.stopViewCount = -1; - v.isRunning = false; - } - } - tempViewList.clear(); - pendingRequest = true; - } else { - pendingRequest = rendererRun || (requestObjList.size() > 0); - - } - - size = freeMessageList.size(); - if (size > 0) { - for (int i=0; i < size; i++) { - requestTypeList.add(FREE_MESSAGE); - requestObjList.add(freeMessageList.get(i)); - } - pendingRequest = true; - freeMessageList.clear(); - } - if (!running && (renderOnceList.size() > 0)) { - clearRenderOnceList(); - } - - if (pendingRequest) { - setWork(); - } - - if (rendererRun || requestRenderWorkToDo) { - running = true; - } - - } - - private void clearRenderOnceList() { - for (int i=renderOnceList.size()-1; i>=0; i--) { - View v = (View) renderOnceList.get(i); - v.renderOnceFinish = true; - // stop after render once - stopView(v); - } - renderOnceList.clear(); - threadListsChanged = true; - - } - - synchronized void runMonitor(int action, - UnorderList stateThreadList, - UnorderList renderThreadList, - UnorderList requestRenderThreadList, - J3dThread nthread) { - - switch (action) { - case RUN_THREADS: - int currentStateThread = 0; - int currentRenderThread = 0; - int currentRequestRenderThread = 0; - View view; - boolean done; - J3dThreadData thread; - J3dThreadData renderThreads[] = (J3dThreadData []) - renderThreadList.toArray(false); - J3dThreadData stateThreads[] = (J3dThreadData []) - stateThreadList.toArray(false); - J3dThreadData requestRenderThreads[] = (J3dThreadData []) - requestRenderThreadList.toArray(false); - int renderThreadSize = renderThreadList.arraySize(); - int stateThreadSize = stateThreadList.arraySize(); - int requestRenderThreadSize = requestRenderThreadList.arraySize(); - - done = false; - - //lock all the needed geometry and image component - View[] allView = (View []) views.toArray(false); - View currentV; - int i; - - if (lockGeometry) - { - for( i = views.arraySize()-1; i >= 0; i--) { - currentV = allView[i]; - currentV.renderBin.lockGeometry(); - } - } - - while (!done) { - // First try a RenderThread - while (!renderWaiting && - currentRenderThread != renderThreadSize) { - thread = renderThreads[currentRenderThread++]; - if (!thread.needsRun) { - continue; - } - if ((thread.threadOpts & J3dThreadData.START_TIMER) != 0) { - view = (View)((Object[])thread.threadArgs)[2]; - view.frameNumber++; - view.startTime = J3dClock.currentTimeMillis(); - } - - - renderPending++; - - if (cpuLimit == 1) { - thread.thread.args = (Object[])thread.threadArgs; - thread.thread.doWork(currentTime); - } else { - threadPending++; - thread.thread.runMonitor(J3dThread.RUN, - currentTime, - (Object[])thread.threadArgs); - } - - if ((thread.threadOpts & J3dThreadData.STOP_TIMER) != 0) { - view = (View)((Object[])thread.threadArgs)[3]; - timestampUpdateList.add(view); - } - - if ((thread.threadOpts & J3dThreadData.LAST_STOP_TIMER) != 0) { - // release lock on locked geometry and image component - for( i = 0; i < views.arraySize(); i++) { - currentV = allView[i]; - currentV.renderBin.releaseGeometry(); - } - } - - if ((cpuLimit != 1) && - (thread.threadOpts & - J3dThreadData.WAIT_ALL_THREADS) != 0) { - - renderWaiting = true; - } - - - if ((cpuLimit != 1) && (cpuLimit <= threadPending)) { - state = WAITING_FOR_CPU; - try { - wait(); - } catch (InterruptedException e) { - System.err.println(e); - } - state = RUNNING; - } - - } - // Now try state threads - while (!stateWaiting && - currentStateThread != stateThreadSize) { - thread = stateThreads[currentStateThread++]; - - if (!thread.needsRun) { - continue; - } - - statePending++; - - if (cpuLimit == 1) { - thread.thread.args = (Object[])thread.threadArgs; - thread.thread.doWork(currentTime); - } else { - threadPending++; - thread.thread.runMonitor(J3dThread.RUN, - currentTime, - (Object[])thread.threadArgs); - } - if (cpuLimit != 1 && (thread.threadOpts & - J3dThreadData.WAIT_ALL_THREADS) != 0) { - stateWaiting = true; - } - - if ((cpuLimit != 1) && (cpuLimit <= threadPending)) { - // Fix bug 4686766 - always allow - // renderer thread to continue if not finish - // geomLock can release for Behavior thread to - // continue. - if (currentRenderThread == renderThreadSize) { - state = WAITING_FOR_CPU; - try { - wait(); - } catch (InterruptedException e) { - System.err.println(e); - } - state = RUNNING; - } else { - // Run renderer thread next time - break; - } - - } - } - - // Now try requestRender threads - if (!renderWaiting && - (currentRenderThread == renderThreadSize)) { - currentRequestRenderThread = 0; - while (!renderWaiting && - (currentRequestRenderThread != - requestRenderThreadSize)) { - - thread = - requestRenderThreads[currentRequestRenderThread++]; - - renderPending++; - - if (cpuLimit == 1) { - thread.thread.args = (Object[])thread.threadArgs; - thread.thread.doWork(currentTime); - } else { - threadPending++; - thread.thread.runMonitor(J3dThread.RUN, - currentTime, - (Object[])thread.threadArgs); - } - if (cpuLimit != 1 && (thread.threadOpts & - J3dThreadData.WAIT_ALL_THREADS) != 0) { - renderWaiting = true; - } - if (cpuLimit != 1 && cpuLimit <= threadPending) { - state = WAITING_FOR_CPU; - try { - wait(); - } catch (InterruptedException e) { - System.err.println(e); - } - state = RUNNING; - } - } - } - - if (cpuLimit != 1) { - if ((renderWaiting && - (currentStateThread == stateThreadSize)) || - (stateWaiting && - currentRenderThread == renderThreadSize) || - (renderWaiting && stateWaiting)) { - if (!requestRenderWorkToDo) { - state = WAITING_FOR_THREADS; - try { - wait(); - } catch (InterruptedException e) { - System.err.println(e); - } - state = RUNNING; - } - requestRenderWorkToDo = false; - } - } - - if ((currentStateThread == stateThreadSize) && - (currentRenderThread == renderThreadSize) && - (currentRequestRenderThread == requestRenderThreadSize) && - (threadPending == 0)) { - for (int k = timestampUpdateList.size() - 1; k >= 0; k--) { - View v = timestampUpdateList.get(k); - v.setFrameTimingValues(); - v.universe.behaviorStructure.incElapsedFrames(); - } - timestampUpdateList.clear(); - updateMirrorObjects(); - done = true; - - if (isStatsLoggable(Level.INFO)) { - // Instrumentation of Java 3D renderer - logTimes(); - } - } - } - break; - - case THREAD_DONE: - if (state != WAITING_FOR_RENDERER_CLEANUP) { - - threadPending--; - assert threadPending >= 0 : ("threadPending = " + threadPending); - if (nthread.type == J3dThread.RENDER_THREAD) { - View v = (View) nthread.args[3]; - if (v != null) { // STOP_TIMER - v.stopTime = J3dClock.currentTimeMillis(); - } - - if (--renderPending == 0) { - renderWaiting = false; - } - assert renderPending >= 0 : ("renderPending = " + renderPending); - } else { - if (--statePending == 0) { - stateWaiting = false; - } - assert statePending >= 0 : ("statePending = " + statePending); - } - if (state == WAITING_FOR_CPU || state == WAITING_FOR_THREADS) { - notify(); - } - } else { - notify(); - state = RUNNING; - } - break; - - case CHECK_FOR_WORK: - if (!workToDo) { - state = SLEEPING; - // NOTE: this could wakeup spuriously (see issue 279), but it - // will not cause any problems. - try { - wait(); - } catch (InterruptedException e) { - System.err.println(e); - } - state = RUNNING; - } - workToDo = false; - break; - - case SET_WORK: - workToDo = true; - if (state == SLEEPING) { - notify(); - } - break; - - case SET_WORK_FOR_REQUEST_RENDERER: - requestRenderWorkToDo = true; - workToDo = true; - if (state == WAITING_FOR_CPU || state == WAITING_FOR_THREADS || - state == SLEEPING) { - notify(); - } - break; - - case RUN_RENDERER_CLEANUP: - nthread.runMonitor(J3dThread.RUN, currentTime, - rendererCleanupArgs); - state = WAITING_FOR_RENDERER_CLEANUP; - // Issue 279 - loop until state is set to running - while (state != RUNNING) { - try { - wait(); - } catch (InterruptedException e) { - System.err.println(e); - } - } - break; - - default: - // Should never get here - assert false : "missing case in switch statement"; - } - } - - // Static initializer - static { - // create ThreadGroup - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - @Override - public Object run() { - ThreadGroup parent; - Thread thread = Thread.currentThread(); - threadPriority = thread.getPriority(); - rootThreadGroup = thread.getThreadGroup(); - while ((parent = rootThreadGroup.getParent()) != null) { - rootThreadGroup = parent; - } - rootThreadGroup = new ThreadGroup(rootThreadGroup, - "Java3D"); - // use the default maximum group priority - return null; - } - }); - - // Initialize loggers - try { - initLoggers(); - } catch (RuntimeException ex) { - System.err.println(ex); - } - } - - - static String mtype[] = { - "INSERT_NODES", - "REMOVE_NODES", - "RUN", - "TRANSFORM_CHANGED", - "UPDATE_VIEW", - "STOP_THREAD", - "COLORINGATTRIBUTES_CHANGED", - "LINEATTRIBUTES_CHANGED", - "POINTATTRIBUTES_CHANGED", - "POLYGONATTRIBUTES_CHANGED", - "RENDERINGATTRIBUTES_CHANGED", - "TEXTUREATTRIBUTES_CHANGED", - "TRANSPARENCYATTRIBUTES_CHANGED", - "MATERIAL_CHANGED", - "TEXCOORDGENERATION_CHANGED", - "TEXTURE_CHANGED", - "MORPH_CHANGED", - "GEOMETRY_CHANGED", - "APPEARANCE_CHANGED", - "LIGHT_CHANGED", - "BACKGROUND_CHANGED", - "CLIP_CHANGED", - "FOG_CHANGED", - "BOUNDINGLEAF_CHANGED", - "SHAPE3D_CHANGED", - "TEXT3D_TRANSFORM_CHANGED", - "TEXT3D_DATA_CHANGED", - "SWITCH_CHANGED", - "COND_MET", - "BEHAVIOR_ENABLE", - "BEHAVIOR_DISABLE", - "INSERT_RENDERATOMS", - "ORDERED_GROUP_INSERTED", - "ORDERED_GROUP_REMOVED", - "COLLISION_BOUND_CHANGED", - "REGION_BOUND_CHANGED", - "MODELCLIP_CHANGED", - "BOUNDS_AUTO_COMPUTE_CHANGED", - "SOUND_ATTRIB_CHANGED", - "AURALATTRIBUTES_CHANGED", - "SOUNDSCAPE_CHANGED", - "ALTERNATEAPPEARANCE_CHANGED", - "RENDER_OFFSCREEN", - "RENDER_RETAINED", - "RENDER_IMMEDIATE", - "SOUND_STATE_CHANGED", - "ORIENTEDSHAPE3D_CHANGED", - "TEXTURE_UNIT_STATE_CHANGED", - "UPDATE_VIEWPLATFORM", - "BEHAVIOR_ACTIVATE", - "GEOMETRYARRAY_CHANGED", - "MEDIA_CONTAINER_CHANGED", - "RESIZE_CANVAS", - "TOGGLE_CANVAS", - "IMAGE_COMPONENT_CHANGED", - "SCHEDULING_INTERVAL_CHANGED", - "VIEWSPECIFICGROUP_CHANGED", - "VIEWSPECIFICGROUP_INIT", - "VIEWSPECIFICGROUP_CLEAR", - "ORDERED_GROUP_TABLE_CHANGED", - "BEHAVIOR_REEVALUATE", - "CREATE_OFFSCREENBUFFER", - "DESTROY_CTX_AND_OFFSCREENBUFFER", - "SHADER_ATTRIBUTE_CHANGED", - "SHADER_ATTRIBUTE_SET_CHANGED", - "SHADER_APPEARANCE_CHANGED", - "ALLOCATE_CANVASID", - "FREE_CANVASID", - }; - - private String dumpThreads(int threads) { - StringBuffer strBuf = new StringBuffer(); - strBuf.append("threads:"); - //dump Threads type - if ((threads & J3dThread.BEHAVIOR_SCHEDULER) != 0) { - strBuf.append(" BEHAVIOR_SCHEDULER"); - } - if ((threads & J3dThread.SOUND_SCHEDULER) != 0) { - strBuf.append(" SOUND_SCHEDULER"); - } - if ((threads & J3dThread.INPUT_DEVICE_SCHEDULER) != 0) { - strBuf.append(" INPUT_DEVICE_SCHEDULER"); - } - if ((threads & J3dThread.RENDER_THREAD) != 0) { - strBuf.append(" RENDER_THREAD"); - } - if ((threads & J3dThread.UPDATE_GEOMETRY) != 0) { - strBuf.append(" UPDATE_GEOMETRY"); - } - if ((threads & J3dThread.UPDATE_RENDER) != 0) { - strBuf.append(" UPDATE_RENDER"); - } - if ((threads & J3dThread.UPDATE_BEHAVIOR) != 0) { - strBuf.append(" UPDATE_BEHAVIOR"); - } - if ((threads & J3dThread.UPDATE_SOUND) != 0) { - strBuf.append(" UPDATE_SOUND"); - } - if ((threads & J3dThread.UPDATE_RENDERING_ATTRIBUTES) != 0) { - strBuf.append(" UPDATE_RENDERING_ATTRIBUTES"); - } - if ((threads & J3dThread.UPDATE_RENDERING_ENVIRONMENT) != 0) { - strBuf.append(" UPDATE_RENDERING_ENVIRONMENT"); - } - if ((threads & J3dThread.UPDATE_TRANSFORM) != 0) { - strBuf.append(" UPDATE_TRANSFORM"); - } - - return strBuf.toString(); - } - - // Method to log the specified message. Note that the caller - // should check for isCoreLoggable(FINEST) before calling - private void dumpMessage(String str, J3dMessage m) { - StringBuffer strBuf = new StringBuffer(); - strBuf.append(str).append(" "); - if (m.type >= 0 && m.type < mtype.length) { - strBuf.append(mtype[m.type]); - } else { - strBuf.append("<UNKNOWN>"); - } - strBuf.append(" ").append(dumpThreads(m.threads)); - getCoreLogger().finest(strBuf.toString()); - } - - - int frameCount = 0; - private int frameCountCutoff = 100; - - private void manageMemory() { - if (++frameCount > frameCountCutoff) { - FreeListManager.manageLists(); - frameCount = 0; - } - } - - /** - * Yields the current thread, by sleeping for a small amount of - * time. Unlike <code>Thread.yield()</code>, this method - * guarantees that the current thread will yield to another thread - * waiting to run. It also ensures that the other threads will - * run for at least a small amount of time before the current - * thread runs again. - */ - static final void threadYield() { - // Note that we can't just use Thread.yield(), since it - // doesn't guarantee that it will actually yield the thread - // (and, in fact, it appears to be a no-op under Windows). So - // we will sleep for 1 msec instead. Since most threads use - // wait/notify, and only use this when they are waiting for - // another thread to finish something, this shouldn't be a - // performance concern. - - //Thread.yield(); - try { - Thread.sleep(1); - } - catch (InterruptedException e) { - // Do nothing, since we really don't care how long (or - // even whether) we sleep - } - } - - // Return the number of available processors - private int getNumberOfProcessors() { - return Runtime.getRuntime().availableProcessors(); - } - - // - // The following framework supports code instrumentation. To use it, - // add code of the following form to areas that you want to enable for - // timing: - // - // long startTime = System.nanoTime(); - // sortTransformGroups(tSize, tgs); - // long deltaTime = System.nanoTime() - startTime; - // VirtualUniverse.mc.recordTime(MasterControl.TimeType.XXXXX, deltaTime); - // - // where "XXXXX" is the enum representing the code segment being timed. - // Additional enums can be defined for new subsystems. - // - - static enum TimeType { - TOTAL_FRAME, - RENDER, - BEHAVIOR, - // TRANSFORM_UPDATE, - // ... - } - - private long[] statTimes = new long[TimeType.values().length]; - private int[] statCounts = new int[TimeType.values().length]; - private boolean[] statSeen = new boolean[TimeType.values().length]; - private int frameCycleTick = 0; - private long frameCycleNumber = 0L; - - // Method to record times -- should not be called unless the stats logger - // level is set to INFO or lower - synchronized void recordTime(TimeType type, long deltaTime) { - int idx = type.ordinal(); - statTimes[idx] += deltaTime; - statCounts[idx]++; - statSeen[idx] = true; - } - - // Method to record times -- this is not called unless the stats logger - // level is set to INFO or lower - private synchronized void logTimes() { - ++frameCycleNumber; - if (++frameCycleTick >= 10) { - StringBuffer strBuf = new StringBuffer(); - strBuf.append("----------------------------------------------\n"). - append(" Frame Number = "). - append(frameCycleNumber). - append("\n"); - for (int i = 0; i < statTimes.length; i++) { - if (statSeen[i]) { - strBuf.append(" "); - if (statCounts[i] > 0) { - strBuf.append(TimeType.values()[i]). - append(" ["). - append(statCounts[i]). - append("] = "). - append((double)statTimes[i] / 1000000.0 / (double)statCounts[i]). - append(" msec per call\n"); - statTimes[i] = 0L; - statCounts[i] = 0; - } else { - assert statTimes[i] == 0L; - strBuf.append(TimeType.values()[i]). - append(" [0] = 0.0 msec\n"); - } - } - } - getStatsLogger().info(strBuf.toString()); - frameCycleTick = 0; - } - } - -} |