aboutsummaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/MasterControl.java
diff options
context:
space:
mode:
authorJulien Gouesse <[email protected]>2015-11-28 15:11:48 +0100
committerJulien Gouesse <[email protected]>2015-11-28 15:11:48 +0100
commitdbc98deea1884e44da2c74d6ea807253cdefa693 (patch)
tree29c3ee7dea82d7dd773d81f33f645dde67e43a17 /src/javax/media/j3d/MasterControl.java
parent2c99f1329dc55bd496bce91b9aba956ecba3c67e (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.java3748
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;
- }
- }
-
-}