/// <summary> /// Marks this Clock as the root of a timing tree. /// </summary> /// <param name="timeManager"> /// The TimeManager that controls this timing tree. /// </param> internal void MakeRoot(TimeManager timeManager) { Debug.Assert(!IsTimeManager, "Cannot associate a root with multiple timing trees"); Debug.Assert(this._timeManager == null, "Cannot use a timeline already in the timing tree as a root"); Debug.Assert(timeManager.TimeManagerClock == this, "Cannot associate more than one root per timing tree"); Debug.Assert(this._parent == null && _children == null, "Cannot use a timeline connected to other timelines as a root"); IsTimeManager = true; _rootChildren = new List<WeakReference>(); _timeManager = timeManager; _depth = 0; // InternalCurrentIteration = 1; InternalCurrentProgress = 0; InternalCurrentGlobalSpeed = 1; InternalCurrentClockState = ClockState.Active; }
/// <summary> /// The MediaContext lives in the Dispatcher and is the MediaSystem's class that keeps /// per Dispatcher state. /// </summary> internal MediaContext(Dispatcher dispatcher) { // We create exactly one MediaContext per thread. This is the one // for this thread Debug.Assert(dispatcher.Reserved0 == null); // Initialize frame time information if (IsClockSupported) { SafeNativeMethods.QueryPerformanceCounter(out _lastPresentationTime); _estimatedNextPresentationTime = TimeSpan.FromTicks(CountsToTicks(_lastPresentationTime)); } // Generate a unique id for our context so that we can pass this along to // CreateHWNDRenderTarget _contextGuid = Guid.NewGuid(); // Create a dictionary in which we manage the CompositionTargets. _registeredICompositionTargets = new Dictionary<ICompositionTarget, object>(); _renderModeMessage = new DispatcherOperationCallback(InvalidateRenderMode); // Create a notification window to listen for broadcast window messages _notificationWindow = new MediaContextNotificationWindow(this); // Connect to the MediaSystem. if (MediaSystem.Startup(this)) { _isConnected = MediaSystem.ConnectChannels(this); } // Subscribe to the OnDestroyContext event so that we can cleanup our state. _destroyHandler = new EventHandler(this.OnDestroyContext); Dispatcher.ShutdownFinished += _destroyHandler; _renderMessage = new DispatcherOperationCallback(RenderMessageHandler); _animRenderMessage = new DispatcherOperationCallback(AnimatedRenderMessageHandler); _inputMarkerMessage = new DispatcherOperationCallback(InputMarkerMessageHandler); // We hold off connecting ourselves to the dispatcher until we are sure that // initialization will complete successfully. In rare cases, function calls // earlier in this constructor throw exceptions, resulting in the MediaContext // being left in an uninitialized state; however, the Dispatcher could call methods // on the MediaContext, resulting in unpredictable behaviour (see bug 1630647). // // NOTE: We must attach to the Dispatcher before creating a TimeManager, // otherwise we will create a circular function loop where TimeManager attempts // to create a Clock, which attempts to locate a MediaContext, which attempts to // create a TimeManager, resulting in a stack overflow. dispatcher.Reserved0 = this; _timeManager = new TimeManager(); _timeManager.Start(); _timeManager.NeedTickSooner += new EventHandler(OnNeedTickSooner); _promoteRenderOpToInput = new DispatcherTimer(DispatcherPriority.Render); _promoteRenderOpToInput.Tick += new EventHandler(PromoteRenderOpToInput); _promoteRenderOpToRender = new DispatcherTimer(DispatcherPriority.Render); _promoteRenderOpToRender.Tick += new EventHandler(PromoteRenderOpToRender); _estimatedNextVSyncTimer = new DispatcherTimer(DispatcherPriority.Render); _estimatedNextVSyncTimer.Tick += new EventHandler(EstimatedNextVSyncTimeExpired); _commitPendingAfterRender = false; }