Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / Media / CompositionTarget.cs / 1 / CompositionTarget.cs
//------------------------------------------------------------------------------ // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // // History: // 03/22/2004 : ABaioura - Created. // //----------------------------------------------------------------------------- using System; using System.Collections; using System.Diagnostics; using System.Threading; using System.Windows.Threading; using System.Windows; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Automation.Provider; using System.Windows.Media.Composition; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Security; using MS.Internal; using MS.Win32; using MS.Utility; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; namespace System.Windows.Media { ////// /// ////// CompositionTarget subclassing is not allowed in Partial Trust - Demands UIPermissionWindow.AllWindows for inheritance /// [UIPermissionAttribute(SecurityAction.InheritanceDemand,Window=UIPermissionWindow.AllWindows)] public abstract class CompositionTarget : DispatcherObject, IDisposable, ICompositionTarget { // // Data types for communicating state information between // CompositionTarget and its host. // internal enum HostStateFlags : uint { None = 0, WorldTransform = 1, ClipBounds = 2 }; internal struct HostState { public HostStateFlags flags; public Matrix worldTransform; public Rect clipBounds; }; //--------------------------------------------------------------------- // // Constructors // //--------------------------------------------------------------------- #region Constructors ////// CompositionTarget /// internal CompositionTarget() { #if TRACE_MVR markVisibleCountTotal = 0; #endif } ////// This method is used to create all uce resources either on Startup or session connect /// internal virtual void CreateUCEResources(DUCE.Channel channel, DUCE.Channel outOfBandChannel) { Debug.Assert(channel != null); Debug.Assert(!_contentRoot.IsOnChannel(channel)); Debug.Assert(outOfBandChannel != null); Debug.Assert(!_contentRoot.IsOnChannel(outOfBandChannel)); // // Create root visual on the current channel and send // this command out of band to ensure that composition node is // created by the time this visual target is available for hosting // and to avoid life-time issues when we are working with this node // from the different channels. // bool resourceCreated = _contentRoot.CreateOrAddRefOnChannel(outOfBandChannel, s_contentRootType); Debug.Assert(resourceCreated); _contentRoot.DuplicateHandle(outOfBandChannel, channel); outOfBandChannel.Commit(); } ////// This method is used to release all uce resources either on Shutdown or session disconnect /// internal virtual void ReleaseUCEResources(DUCE.Channel channel, DUCE.Channel outOfBandChannel) { if (_rootVisual.Value != null) { ((DUCE.IResource)(_rootVisual.Value)).ReleaseOnChannel(channel); } // // Release the root visual. // if (_contentRoot.IsOnChannel(channel)) { _contentRoot.ReleaseOnChannel(channel); } if (_contentRoot.IsOnChannel(outOfBandChannel)) { _contentRoot.ReleaseOnChannel(outOfBandChannel); } } #endregion Constructors //---------------------------------------------------------------------- // // Public Methods // //--------------------------------------------------------------------- #region Public Methods ////// Disposes CompositionTarget. /// public virtual void Dispose() { // // Here we cannot use VerifyAPI methods because they check // for the disposed state. // VerifyAccess(); if (!_isDisposed) { // // Disconnect the root visual so that all of the child // animations and resources are cleaned up. // _isDisposed = true; } } ////// Returns true if the CompositionTarget is disposed; otherwise returns false. /// internal bool IsDisposed { get { return _isDisposed; } } #endregion Public Methods //---------------------------------------------------------------------- // // Public Properties // //---------------------------------------------------------------------- #region Public Properties ////// Gets and sets the root Visual of the CompositionTarget. /// ////// /// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Critical: This code sets a rootvisual which is risky to do because /// it can destabilize assumptions made in popup code /// PublicOK: The getter is safe and the setter has a link demand and is critical /// public virtual Visual RootVisual { [SecurityCritical] get { VerifyAPIReadOnly(); return (_rootVisual.Value); } [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)] [SecurityCritical] set { VerifyAPIReadWrite(); if (_rootVisual.Value != value) { SetRootVisual(value); MediaContext.From(Dispatcher).PostRender(); } } } ////// Returns matrix that can be used to transform coordinates from this /// target to the rendering destination device. /// public abstract Matrix TransformToDevice { get; } ////// Returns matrix that can be used to transform coordinates from /// the rendering destination device to this target. /// public abstract Matrix TransformFromDevice { get; } #endregion Public Properties //--------------------------------------------------------------------- // // Internal Methods // //---------------------------------------------------------------------- #region Internal Methods ////// /// internal void PropagateState( ref HostState state ) { // // Marshal state objects to the thread servicing this visual target. // object [] argArray = new object [] {state.flags, null, null}; if ((state.flags & HostStateFlags.WorldTransform) != 0) { argArray[1] = state.worldTransform; } if ((state.flags & HostStateFlags.ClipBounds) != 0) { argArray[2] = state.clipBounds; } Dispatcher.BeginInvoke( DispatcherPriority.Normal, new DispatcherOperationCallback(StateChangedCallback), argArray ); } ////// /// internal object StateChangedCallback(object arg) { object[] argArray = arg as object[]; HostStateFlags stateFlags = (HostStateFlags)argArray[0]; // // Check if world transform of the host has changed and // update cached value accordingly. This requires realization // update on the visual tree. // if ((stateFlags & HostStateFlags.WorldTransform) != 0) { _worldTransform = (Matrix)argArray[1]; } // // Check if clip bounds have changed, update cached value. // if ((stateFlags & HostStateFlags.ClipBounds) != 0) { _worldClipBounds = (Rect)argArray[2]; } // // Set corresponding flags on the root visual and schedule // render if one has not already been scheduled. // if (_rootVisual.Value != null) { // // When replacing the root visual, we need to re-realize all // content in the new tree // _rootVisual.Value.SetFlags(true, VisualFlags.NodeRequiresNewRealization); Visual.PropagateFlags( _rootVisual.Value, VisualFlags.IsSubtreeDirtyForPrecompute | VisualFlags.NodeNeedsBitmapEffectUpdate | VisualFlags.NodeInSubtreeRequiresNewRealization, VisualProxyFlags.IsSubtreeDirtyForRender ); } return null; } void ICompositionTarget.AddRefOnChannel(DUCE.Channel channel, DUCE.Channel outOfBandChannel) { // create all uce resources. CreateUCEResources(channel, outOfBandChannel); } void ICompositionTarget.ReleaseOnChannel(DUCE.Channel channel, DUCE.Channel outOfBandChannel) { // release all the uce resources. ReleaseUCEResources(channel, outOfBandChannel); } ////// Render method renders the visual tree. /// //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 void ICompositionTarget.Render(bool inResize, DUCE.Channel channel) { #if DEBUG_CLR_MEM bool clrTracingEnabled = false; if (CLRProfilerControl.ProcessIsUnderCLRProfiler && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance)) { clrTracingEnabled = true; ++_renderCLRPass; CLRProfilerControl.CLRLogWriteLine("Begin_FullRender_{0}", _renderCLRPass); } #endif // DEBUG_CLR_MEM // // Now we render the scene // #if MEDIA_PERFORMANCE_COUNTERS _frameRateTimer.Begin(); #endif if (_rootVisual.Value != null) { bool etwTracingEnabled = false; if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal)) { etwTracingEnabled = true; EventTrace.EventProvider.TraceEvent( EventTrace.GuidFromId(EventTraceGuidId.PRECOMPUTESCENEGUID), MS.Utility.EventType.StartEvent, GetHashCode() ); } #if MEDIA_PERFORMANCE_COUNTERS _precomputeRateTimer.Begin(); #endif // precompute is channel agnostic _rootVisual.Value.Precompute(); #if MEDIA_PERFORMANCE_COUNTERS _precomputeRateTimer.End(); #endif if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent( EventTrace.GuidFromId(EventTraceGuidId.PRECOMPUTESCENEGUID), MS.Utility.EventType.EndEvent ); } #if DEBUG MediaTrace.RenderPass.Trace("Full Update"); #endif if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent( EventTrace.GuidFromId(EventTraceGuidId.COMPILESCENEGUID), MS.Utility.EventType.StartEvent, GetHashCode() ); } #if MEDIA_PERFORMANCE_COUNTERS _renderRateTimer.Begin(); #endif Compile(channel); #if MEDIA_PERFORMANCE_COUNTERS _renderRateTimer.End(); #endif if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent( EventTrace.GuidFromId(EventTraceGuidId.COMPILESCENEGUID), MS.Utility.EventType.EndEvent ); } } #if DEBUG_CLR_MEM if (clrTracingEnabled && CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance) { CLRProfilerControl.CLRLogWriteLine("End_FullRender_{0}", _renderCLRPass); } #endif // DEBUG_CLR_MEM #if MEDIA_PERFORMANCE_COUNTERS _frameRateTimer.End(); System.Console.WriteLine("RENDERING PERFORMANCE DATA"); System.Console.WriteLine("Frame rendering time: " + _frameRateTimer.TimeOfLastPeriod + "ms"); System.Console.WriteLine("Frame precompute time: " + _precomputeRateTimer.TimeOfLastPeriod + "ms"); System.Console.WriteLine("Frame render time: " + _renderRateTimer.TimeOfLastPeriod + "ms"); #endif } bool ICompositionTarget.VisualTreeContainsGraphness() { // We can only call this after we have precomputed the tree to ensure correctness if (_rootVisual.Value != null) { Debug.Assert(!_rootVisual.Value.CheckFlagsAnd(VisualFlags.IsSubtreeDirtyForPrecompute)); return _rootVisual.Value.NodeContainsGraphness; } else { return false; } } #endregion Internal Methods //--------------------------------------------------------------------- // // Internal Properties // //--------------------------------------------------------------------- #region Internal Properties internal DUCE.MultiChannelResource _contentRoot = new DUCE.MultiChannelResource(); internal const DUCE.ResourceType s_contentRootType = DUCE.ResourceType.TYPE_VISUAL; ////// /// internal Matrix WorldTransform { get { return _worldTransform; } } internal Rect WorldClipBounds { get { return _worldClipBounds; } } #endregion Internal Properties //--------------------------------------------------------------------- // // Private Methods // //---------------------------------------------------------------------- #region Private Methods ////// The compile method transforms the Visual Scene Graph into the Composition Scene Graph. /// ////// Critical - calls critical code, access critical resources (handles) /// TreatAsSafe - safe to compile the visual at anytime /// [SecurityCritical, SecurityTreatAsSafe] private void Compile(DUCE.Channel channel) { MediaContext mctx = MediaContext.From(Dispatcher); Invariant.Assert(_rootVisual.Value!=null); // 1) Check if we have a cached render context. // 2) Initialize the render context. // 3) Call to render the scene graph (transforming it into the composition scene graph). // 4) Deinitalize the render context and cache it if possible. // ----------------------------------------------------------------------------------- // 1) Get cached render context if possible. // For performance reasons the render context is cached between frames. Here we check if // we have a cached one. If we don't we just create a new one. If we do have one, we use // the render context. Note that we null out the _cachedRenderContext field. This means // that in failure cases we will always recreate the render context. RenderContext rc = null; Invariant.Assert(channel != null); if (_cachedRenderContext != null) { rc = _cachedRenderContext; _cachedRenderContext = null; } else { rc = new RenderContext(); } // ------------------------------------------------------------------------------------ // 2) Prepare the render context. rc.Initialize(channel, _contentRoot.GetHandle(channel)); // ------------------------------------------------------------------------------------ // 3) Compile the scene. if (mctx.IsConnected) { _rootVisual.Value.Render(rc, 0); } // ----------------------------------------------------------------------------------- // 4) Cache the render context. Debug.Assert(_cachedRenderContext == null); _cachedRenderContext = rc; } ////// Marks the realizations needed to render the complete client area. /// internal void MarkVisibleRealizations(RealizationContext rc) { if (_rootVisual.Value != null) { #if TRACE_MVR Visual.MarkVisibleRealizationsCount = 0; #endif MediaContext ctx = MediaContext.From(Dispatcher); // Mark realizations for the application itself. MarkVisibleRealizationsForTransform(rc, ref _worldTransform); // Mark realizations for accessibility applications // which may display content at different scales. foreach (Matrix m in ctx.TransformHints) { Matrix transform = m * _worldTransform; // BitmapEffects cannot handle large scale transforms // since allocating large bitmaps can cause // OutOfMemory exceptions. To handle magnifier // scenarios we set the inverse of the hint transform on the // realization context and later use it to remove the // magnifier scale and render the bitmap effect at // its original size. // Ideally, we would get the viewport from the magnifier - // translate transform + clip, and compute the appropriate clip // for effects if (m.HasInverse) { m.Invert(); rc.BaseTransform = m; } else { rc.BaseTransform = Matrix.CreateScaling(0, 0); } MarkVisibleRealizationsForTransform(rc, ref transform); } #if TRACE_MVR CompositionTarget.markVisibleCountTotal += Visual.MarkVisibleRealizationsCount; MediaTrace.MarkVisibleRealizationsStatistics.Trace("MVR: Touched " + Visual.MarkVisibleRealizationsCount + " nodes this pass, total: " + markVisibleCountTotal); #endif } } ////// Marks the realizations needed to render the complete client area for given world transform. /// internal void MarkVisibleRealizationsForTransform(RealizationContext rc, ref Matrix transform) { Debug.Assert(_rootVisual.Value != null); // ------------------------------------------------------------ // 1) Set up the world transform based on the state recieved // from the host. rc.TransformStack.Push(ref transform, /* combine */ false); // ----------------------------------------------------------- // 2) Walk the visual tree marking visible realizations. _rootVisual.Value.MarkVisibleRealizations(rc); // ----------------------------------------------------------- // 3) Restore the previous state of the realization context. rc.TransformStack.Pop(); } ////// Internal method to set the root visual. /// /// Root visual, can be null, but can not be a child of another /// Visual. ////// Critical - calls critical code, access critical resources /// TreatAsSafe - safe to reparent a visual /// [SecurityCritical, SecurityTreatAsSafe] private void SetRootVisual(Visual visual) { // if (visual != null && (visual._parent != null || visual.IsRootElement)) { // If a Visual has already a parent it can not be the root in a CompositionTarget because // otherwise we would have two CompositionTargets party on the same Visual tree. // If want to allow this we need to explicitly add support for this. throw new System.ArgumentException(SR.Get(SRID.CompositionTarget_RootVisual_HasParent)); } DUCE.ChannelSet channelSet = MediaContext.From(Dispatcher).GetChannels(); DUCE.Channel channel = channelSet.Channel; if (_rootVisual.Value != null && _contentRoot.IsOnChannel(channel)) { ClearRootNode(channel); channel.AddToRemoveAndReleaseQueue( null, _rootVisual.Value); _rootVisual.Value.IsRootElement = false; } _rootVisual.Value = visual; if (_rootVisual.Value != null) { _rootVisual.Value.IsRootElement = true; _rootVisual.Value.SetFlagsOnAllChannels( true, VisualProxyFlags.IsSubtreeDirtyForRender); } } ////// Removes all children from the current root node. /// private void ClearRootNode(DUCE.Channel channel) { // // Currently we enqueue this command on the channel immediately // because if we put it in the delayed release queue, then // the _contentRoot might have been disposed by the time we // process the queue. // // Note: Currently we might flicker when replacing the root of the // compositionTarget. DUCE.CompositionNode.RemoveAllChildren( _contentRoot.GetHandle(channel), channel); } ////// Verifies that the CompositionTarget can be accessed. /// internal void VerifyAPIReadOnly() { VerifyAccess(); if (_isDisposed) { throw new System.ObjectDisposedException("CompositionTarget"); } } ////// Verifies that the CompositionTarget can be accessed. /// internal void VerifyAPIReadWrite() { VerifyAccess(); if (_isDisposed) { throw new System.ObjectDisposedException("CompositionTarget"); } MediaContext.From(Dispatcher).VerifyWriteAccess(); } #endregion //--------------------------------------------------------------------- // // Private Fields // //---------------------------------------------------------------------- #region Private Fields #if TRACE_MVR private static int markVisibleCountTotal; #endif private bool _isDisposed; private SecurityCriticalDataForSet_rootVisual; private RenderContext _cachedRenderContext; private Matrix _worldTransform = Matrix.Identity; // // ISSUE-ABaioura-10/19/2004: For now we assume a very large client // rect, because currently clip infromation cannot be robustly // communicated from the host. When this is fixed, we can start off // an empty rect; clip bounds will be updated based on the host clip. // private Rect _worldClipBounds = new Rect( Double.MinValue / 2.0, Double.MinValue / 2.0, Double.MaxValue, Double.MaxValue); #if DEBUG_CLR_MEM // // Used for CLRProfiler comments. // private static int _renderCLRPass = 0; #endif // DEBUG_CLR_MEM #if MEDIA_PERFORMANCE_COUNTERS private HFTimer _frameRateTimer; private HFTimer _precomputeRateTimer; private HFTimer _renderRateTimer; #endif #endregion Private Fields //--------------------------------------------------------------------- // // Static Events // //---------------------------------------------------------------------- #region Static Events /// /// Rendering event. Registers a delegate to be notified after animation and layout but before rendering /// public static event EventHandler Rendering { add { MediaContext mc = MediaContext.From(Dispatcher.CurrentDispatcher); mc.Rendering += value; // We need to get a new rendering operation queued. mc.PostRender(); } remove { MediaContext mc = MediaContext.From(Dispatcher.CurrentDispatcher); mc.Rendering -= value; } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // // History: // 03/22/2004 : ABaioura - Created. // //----------------------------------------------------------------------------- using System; using System.Collections; using System.Diagnostics; using System.Threading; using System.Windows.Threading; using System.Windows; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Automation.Provider; using System.Windows.Media.Composition; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Security; using MS.Internal; using MS.Win32; using MS.Utility; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; namespace System.Windows.Media { ////// /// ////// CompositionTarget subclassing is not allowed in Partial Trust - Demands UIPermissionWindow.AllWindows for inheritance /// [UIPermissionAttribute(SecurityAction.InheritanceDemand,Window=UIPermissionWindow.AllWindows)] public abstract class CompositionTarget : DispatcherObject, IDisposable, ICompositionTarget { // // Data types for communicating state information between // CompositionTarget and its host. // internal enum HostStateFlags : uint { None = 0, WorldTransform = 1, ClipBounds = 2 }; internal struct HostState { public HostStateFlags flags; public Matrix worldTransform; public Rect clipBounds; }; //--------------------------------------------------------------------- // // Constructors // //--------------------------------------------------------------------- #region Constructors ////// CompositionTarget /// internal CompositionTarget() { #if TRACE_MVR markVisibleCountTotal = 0; #endif } ////// This method is used to create all uce resources either on Startup or session connect /// internal virtual void CreateUCEResources(DUCE.Channel channel, DUCE.Channel outOfBandChannel) { Debug.Assert(channel != null); Debug.Assert(!_contentRoot.IsOnChannel(channel)); Debug.Assert(outOfBandChannel != null); Debug.Assert(!_contentRoot.IsOnChannel(outOfBandChannel)); // // Create root visual on the current channel and send // this command out of band to ensure that composition node is // created by the time this visual target is available for hosting // and to avoid life-time issues when we are working with this node // from the different channels. // bool resourceCreated = _contentRoot.CreateOrAddRefOnChannel(outOfBandChannel, s_contentRootType); Debug.Assert(resourceCreated); _contentRoot.DuplicateHandle(outOfBandChannel, channel); outOfBandChannel.Commit(); } ////// This method is used to release all uce resources either on Shutdown or session disconnect /// internal virtual void ReleaseUCEResources(DUCE.Channel channel, DUCE.Channel outOfBandChannel) { if (_rootVisual.Value != null) { ((DUCE.IResource)(_rootVisual.Value)).ReleaseOnChannel(channel); } // // Release the root visual. // if (_contentRoot.IsOnChannel(channel)) { _contentRoot.ReleaseOnChannel(channel); } if (_contentRoot.IsOnChannel(outOfBandChannel)) { _contentRoot.ReleaseOnChannel(outOfBandChannel); } } #endregion Constructors //---------------------------------------------------------------------- // // Public Methods // //--------------------------------------------------------------------- #region Public Methods ////// Disposes CompositionTarget. /// public virtual void Dispose() { // // Here we cannot use VerifyAPI methods because they check // for the disposed state. // VerifyAccess(); if (!_isDisposed) { // // Disconnect the root visual so that all of the child // animations and resources are cleaned up. // _isDisposed = true; } } ////// Returns true if the CompositionTarget is disposed; otherwise returns false. /// internal bool IsDisposed { get { return _isDisposed; } } #endregion Public Methods //---------------------------------------------------------------------- // // Public Properties // //---------------------------------------------------------------------- #region Public Properties ////// Gets and sets the root Visual of the CompositionTarget. /// ////// /// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Critical: This code sets a rootvisual which is risky to do because /// it can destabilize assumptions made in popup code /// PublicOK: The getter is safe and the setter has a link demand and is critical /// public virtual Visual RootVisual { [SecurityCritical] get { VerifyAPIReadOnly(); return (_rootVisual.Value); } [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)] [SecurityCritical] set { VerifyAPIReadWrite(); if (_rootVisual.Value != value) { SetRootVisual(value); MediaContext.From(Dispatcher).PostRender(); } } } ////// Returns matrix that can be used to transform coordinates from this /// target to the rendering destination device. /// public abstract Matrix TransformToDevice { get; } ////// Returns matrix that can be used to transform coordinates from /// the rendering destination device to this target. /// public abstract Matrix TransformFromDevice { get; } #endregion Public Properties //--------------------------------------------------------------------- // // Internal Methods // //---------------------------------------------------------------------- #region Internal Methods ////// /// internal void PropagateState( ref HostState state ) { // // Marshal state objects to the thread servicing this visual target. // object [] argArray = new object [] {state.flags, null, null}; if ((state.flags & HostStateFlags.WorldTransform) != 0) { argArray[1] = state.worldTransform; } if ((state.flags & HostStateFlags.ClipBounds) != 0) { argArray[2] = state.clipBounds; } Dispatcher.BeginInvoke( DispatcherPriority.Normal, new DispatcherOperationCallback(StateChangedCallback), argArray ); } ////// /// internal object StateChangedCallback(object arg) { object[] argArray = arg as object[]; HostStateFlags stateFlags = (HostStateFlags)argArray[0]; // // Check if world transform of the host has changed and // update cached value accordingly. This requires realization // update on the visual tree. // if ((stateFlags & HostStateFlags.WorldTransform) != 0) { _worldTransform = (Matrix)argArray[1]; } // // Check if clip bounds have changed, update cached value. // if ((stateFlags & HostStateFlags.ClipBounds) != 0) { _worldClipBounds = (Rect)argArray[2]; } // // Set corresponding flags on the root visual and schedule // render if one has not already been scheduled. // if (_rootVisual.Value != null) { // // When replacing the root visual, we need to re-realize all // content in the new tree // _rootVisual.Value.SetFlags(true, VisualFlags.NodeRequiresNewRealization); Visual.PropagateFlags( _rootVisual.Value, VisualFlags.IsSubtreeDirtyForPrecompute | VisualFlags.NodeNeedsBitmapEffectUpdate | VisualFlags.NodeInSubtreeRequiresNewRealization, VisualProxyFlags.IsSubtreeDirtyForRender ); } return null; } void ICompositionTarget.AddRefOnChannel(DUCE.Channel channel, DUCE.Channel outOfBandChannel) { // create all uce resources. CreateUCEResources(channel, outOfBandChannel); } void ICompositionTarget.ReleaseOnChannel(DUCE.Channel channel, DUCE.Channel outOfBandChannel) { // release all the uce resources. ReleaseUCEResources(channel, outOfBandChannel); } ////// Render method renders the visual tree. /// //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 void ICompositionTarget.Render(bool inResize, DUCE.Channel channel) { #if DEBUG_CLR_MEM bool clrTracingEnabled = false; if (CLRProfilerControl.ProcessIsUnderCLRProfiler && (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance)) { clrTracingEnabled = true; ++_renderCLRPass; CLRProfilerControl.CLRLogWriteLine("Begin_FullRender_{0}", _renderCLRPass); } #endif // DEBUG_CLR_MEM // // Now we render the scene // #if MEDIA_PERFORMANCE_COUNTERS _frameRateTimer.Begin(); #endif if (_rootVisual.Value != null) { bool etwTracingEnabled = false; if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal)) { etwTracingEnabled = true; EventTrace.EventProvider.TraceEvent( EventTrace.GuidFromId(EventTraceGuidId.PRECOMPUTESCENEGUID), MS.Utility.EventType.StartEvent, GetHashCode() ); } #if MEDIA_PERFORMANCE_COUNTERS _precomputeRateTimer.Begin(); #endif // precompute is channel agnostic _rootVisual.Value.Precompute(); #if MEDIA_PERFORMANCE_COUNTERS _precomputeRateTimer.End(); #endif if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent( EventTrace.GuidFromId(EventTraceGuidId.PRECOMPUTESCENEGUID), MS.Utility.EventType.EndEvent ); } #if DEBUG MediaTrace.RenderPass.Trace("Full Update"); #endif if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent( EventTrace.GuidFromId(EventTraceGuidId.COMPILESCENEGUID), MS.Utility.EventType.StartEvent, GetHashCode() ); } #if MEDIA_PERFORMANCE_COUNTERS _renderRateTimer.Begin(); #endif Compile(channel); #if MEDIA_PERFORMANCE_COUNTERS _renderRateTimer.End(); #endif if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent( EventTrace.GuidFromId(EventTraceGuidId.COMPILESCENEGUID), MS.Utility.EventType.EndEvent ); } } #if DEBUG_CLR_MEM if (clrTracingEnabled && CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance) { CLRProfilerControl.CLRLogWriteLine("End_FullRender_{0}", _renderCLRPass); } #endif // DEBUG_CLR_MEM #if MEDIA_PERFORMANCE_COUNTERS _frameRateTimer.End(); System.Console.WriteLine("RENDERING PERFORMANCE DATA"); System.Console.WriteLine("Frame rendering time: " + _frameRateTimer.TimeOfLastPeriod + "ms"); System.Console.WriteLine("Frame precompute time: " + _precomputeRateTimer.TimeOfLastPeriod + "ms"); System.Console.WriteLine("Frame render time: " + _renderRateTimer.TimeOfLastPeriod + "ms"); #endif } bool ICompositionTarget.VisualTreeContainsGraphness() { // We can only call this after we have precomputed the tree to ensure correctness if (_rootVisual.Value != null) { Debug.Assert(!_rootVisual.Value.CheckFlagsAnd(VisualFlags.IsSubtreeDirtyForPrecompute)); return _rootVisual.Value.NodeContainsGraphness; } else { return false; } } #endregion Internal Methods //--------------------------------------------------------------------- // // Internal Properties // //--------------------------------------------------------------------- #region Internal Properties internal DUCE.MultiChannelResource _contentRoot = new DUCE.MultiChannelResource(); internal const DUCE.ResourceType s_contentRootType = DUCE.ResourceType.TYPE_VISUAL; ////// /// internal Matrix WorldTransform { get { return _worldTransform; } } internal Rect WorldClipBounds { get { return _worldClipBounds; } } #endregion Internal Properties //--------------------------------------------------------------------- // // Private Methods // //---------------------------------------------------------------------- #region Private Methods ////// The compile method transforms the Visual Scene Graph into the Composition Scene Graph. /// ////// Critical - calls critical code, access critical resources (handles) /// TreatAsSafe - safe to compile the visual at anytime /// [SecurityCritical, SecurityTreatAsSafe] private void Compile(DUCE.Channel channel) { MediaContext mctx = MediaContext.From(Dispatcher); Invariant.Assert(_rootVisual.Value!=null); // 1) Check if we have a cached render context. // 2) Initialize the render context. // 3) Call to render the scene graph (transforming it into the composition scene graph). // 4) Deinitalize the render context and cache it if possible. // ----------------------------------------------------------------------------------- // 1) Get cached render context if possible. // For performance reasons the render context is cached between frames. Here we check if // we have a cached one. If we don't we just create a new one. If we do have one, we use // the render context. Note that we null out the _cachedRenderContext field. This means // that in failure cases we will always recreate the render context. RenderContext rc = null; Invariant.Assert(channel != null); if (_cachedRenderContext != null) { rc = _cachedRenderContext; _cachedRenderContext = null; } else { rc = new RenderContext(); } // ------------------------------------------------------------------------------------ // 2) Prepare the render context. rc.Initialize(channel, _contentRoot.GetHandle(channel)); // ------------------------------------------------------------------------------------ // 3) Compile the scene. if (mctx.IsConnected) { _rootVisual.Value.Render(rc, 0); } // ----------------------------------------------------------------------------------- // 4) Cache the render context. Debug.Assert(_cachedRenderContext == null); _cachedRenderContext = rc; } ////// Marks the realizations needed to render the complete client area. /// internal void MarkVisibleRealizations(RealizationContext rc) { if (_rootVisual.Value != null) { #if TRACE_MVR Visual.MarkVisibleRealizationsCount = 0; #endif MediaContext ctx = MediaContext.From(Dispatcher); // Mark realizations for the application itself. MarkVisibleRealizationsForTransform(rc, ref _worldTransform); // Mark realizations for accessibility applications // which may display content at different scales. foreach (Matrix m in ctx.TransformHints) { Matrix transform = m * _worldTransform; // BitmapEffects cannot handle large scale transforms // since allocating large bitmaps can cause // OutOfMemory exceptions. To handle magnifier // scenarios we set the inverse of the hint transform on the // realization context and later use it to remove the // magnifier scale and render the bitmap effect at // its original size. // Ideally, we would get the viewport from the magnifier - // translate transform + clip, and compute the appropriate clip // for effects if (m.HasInverse) { m.Invert(); rc.BaseTransform = m; } else { rc.BaseTransform = Matrix.CreateScaling(0, 0); } MarkVisibleRealizationsForTransform(rc, ref transform); } #if TRACE_MVR CompositionTarget.markVisibleCountTotal += Visual.MarkVisibleRealizationsCount; MediaTrace.MarkVisibleRealizationsStatistics.Trace("MVR: Touched " + Visual.MarkVisibleRealizationsCount + " nodes this pass, total: " + markVisibleCountTotal); #endif } } ////// Marks the realizations needed to render the complete client area for given world transform. /// internal void MarkVisibleRealizationsForTransform(RealizationContext rc, ref Matrix transform) { Debug.Assert(_rootVisual.Value != null); // ------------------------------------------------------------ // 1) Set up the world transform based on the state recieved // from the host. rc.TransformStack.Push(ref transform, /* combine */ false); // ----------------------------------------------------------- // 2) Walk the visual tree marking visible realizations. _rootVisual.Value.MarkVisibleRealizations(rc); // ----------------------------------------------------------- // 3) Restore the previous state of the realization context. rc.TransformStack.Pop(); } ////// Internal method to set the root visual. /// /// Root visual, can be null, but can not be a child of another /// Visual. ////// Critical - calls critical code, access critical resources /// TreatAsSafe - safe to reparent a visual /// [SecurityCritical, SecurityTreatAsSafe] private void SetRootVisual(Visual visual) { // if (visual != null && (visual._parent != null || visual.IsRootElement)) { // If a Visual has already a parent it can not be the root in a CompositionTarget because // otherwise we would have two CompositionTargets party on the same Visual tree. // If want to allow this we need to explicitly add support for this. throw new System.ArgumentException(SR.Get(SRID.CompositionTarget_RootVisual_HasParent)); } DUCE.ChannelSet channelSet = MediaContext.From(Dispatcher).GetChannels(); DUCE.Channel channel = channelSet.Channel; if (_rootVisual.Value != null && _contentRoot.IsOnChannel(channel)) { ClearRootNode(channel); channel.AddToRemoveAndReleaseQueue( null, _rootVisual.Value); _rootVisual.Value.IsRootElement = false; } _rootVisual.Value = visual; if (_rootVisual.Value != null) { _rootVisual.Value.IsRootElement = true; _rootVisual.Value.SetFlagsOnAllChannels( true, VisualProxyFlags.IsSubtreeDirtyForRender); } } ////// Removes all children from the current root node. /// private void ClearRootNode(DUCE.Channel channel) { // // Currently we enqueue this command on the channel immediately // because if we put it in the delayed release queue, then // the _contentRoot might have been disposed by the time we // process the queue. // // Note: Currently we might flicker when replacing the root of the // compositionTarget. DUCE.CompositionNode.RemoveAllChildren( _contentRoot.GetHandle(channel), channel); } ////// Verifies that the CompositionTarget can be accessed. /// internal void VerifyAPIReadOnly() { VerifyAccess(); if (_isDisposed) { throw new System.ObjectDisposedException("CompositionTarget"); } } ////// Verifies that the CompositionTarget can be accessed. /// internal void VerifyAPIReadWrite() { VerifyAccess(); if (_isDisposed) { throw new System.ObjectDisposedException("CompositionTarget"); } MediaContext.From(Dispatcher).VerifyWriteAccess(); } #endregion //--------------------------------------------------------------------- // // Private Fields // //---------------------------------------------------------------------- #region Private Fields #if TRACE_MVR private static int markVisibleCountTotal; #endif private bool _isDisposed; private SecurityCriticalDataForSet_rootVisual; private RenderContext _cachedRenderContext; private Matrix _worldTransform = Matrix.Identity; // // ISSUE-ABaioura-10/19/2004: For now we assume a very large client // rect, because currently clip infromation cannot be robustly // communicated from the host. When this is fixed, we can start off // an empty rect; clip bounds will be updated based on the host clip. // private Rect _worldClipBounds = new Rect( Double.MinValue / 2.0, Double.MinValue / 2.0, Double.MaxValue, Double.MaxValue); #if DEBUG_CLR_MEM // // Used for CLRProfiler comments. // private static int _renderCLRPass = 0; #endif // DEBUG_CLR_MEM #if MEDIA_PERFORMANCE_COUNTERS private HFTimer _frameRateTimer; private HFTimer _precomputeRateTimer; private HFTimer _renderRateTimer; #endif #endregion Private Fields //--------------------------------------------------------------------- // // Static Events // //---------------------------------------------------------------------- #region Static Events /// /// Rendering event. Registers a delegate to be notified after animation and layout but before rendering /// public static event EventHandler Rendering { add { MediaContext mc = MediaContext.From(Dispatcher.CurrentDispatcher); mc.Rendering += value; // We need to get a new rendering operation queued. mc.PostRender(); } remove { MediaContext mc = MediaContext.From(Dispatcher.CurrentDispatcher); mc.Rendering -= value; } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TableLayoutStyle.cs
- WindowsFont.cs
- ConnectionProviderAttribute.cs
- HtmlInputImage.cs
- ScriptRef.cs
- TypeElement.cs
- DataSourceControl.cs
- BigInt.cs
- ZoomPercentageConverter.cs
- EditorPartCollection.cs
- HttpRawResponse.cs
- BaseCollection.cs
- SqlNotificationRequest.cs
- DataServiceProcessingPipeline.cs
- EntityCollectionChangedParams.cs
- BaseValidator.cs
- FormViewModeEventArgs.cs
- LowerCaseStringConverter.cs
- ColorContext.cs
- ObjectDataSource.cs
- SQLInt32.cs
- EncoderParameters.cs
- PngBitmapDecoder.cs
- Size3DConverter.cs
- HttpStreamMessage.cs
- Viewport2DVisual3D.cs
- MessageBodyMemberAttribute.cs
- AsymmetricSecurityProtocol.cs
- CompositeControlDesigner.cs
- DataGridViewComboBoxEditingControl.cs
- ProfileInfo.cs
- PhysicalAddress.cs
- XmlAtomicValue.cs
- SHA1Cng.cs
- FileInfo.cs
- ConfigurationValidatorAttribute.cs
- WindowsStartMenu.cs
- TimeoutException.cs
- HtmlWindow.cs
- Vector3DAnimationBase.cs
- GeometryDrawing.cs
- Timer.cs
- PrimaryKeyTypeConverter.cs
- GroupDescription.cs
- Triplet.cs
- Misc.cs
- Util.cs
- RegistrySecurity.cs
- CodeDirectionExpression.cs
- HtmlTextArea.cs
- FeatureSupport.cs
- SystemIPAddressInformation.cs
- VectorCollectionValueSerializer.cs
- CommandField.cs
- ExtensionSimplifierMarkupObject.cs
- ClientRuntimeConfig.cs
- Walker.cs
- SpecularMaterial.cs
- DataSourceView.cs
- PrefixQName.cs
- TemplateAction.cs
- _Connection.cs
- BaseAsyncResult.cs
- Rfc2898DeriveBytes.cs
- StrokeNode.cs
- XmlSchemaSequence.cs
- CalendarDay.cs
- ErrorHandler.cs
- DeobfuscatingStream.cs
- BookmarkScope.cs
- MethodAccessException.cs
- Highlights.cs
- MessagePartDescription.cs
- TextEndOfSegment.cs
- DataGridViewCellPaintingEventArgs.cs
- querybuilder.cs
- ResourcesBuildProvider.cs
- SqlBuffer.cs
- ProtectedProviderSettings.cs
- DataGridViewLinkColumn.cs
- DtdParser.cs
- RectangleGeometry.cs
- DataRowView.cs
- UnionCqlBlock.cs
- WebPartVerbCollection.cs
- Operators.cs
- TimeoutException.cs
- ClientApiGenerator.cs
- CharConverter.cs
- ContextDataSourceView.cs
- ObfuscationAttribute.cs
- StandardBindingOptionalReliableSessionElement.cs
- IdentifierService.cs
- XmlWrappingWriter.cs
- DocumentViewer.cs
- EntityDataSourceDataSelection.cs
- TdsParserSessionPool.cs
- ExtensionCollection.cs
- AttachedAnnotationChangedEventArgs.cs
- AllMembershipCondition.cs