CompositionTarget.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / Media / CompositionTarget.cs / 3 / CompositionTarget.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
// 
// History:
//  03/22/2004 : [....] - 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 
            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 
                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 
                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));
            } 

            foreach (DUCE.ChannelSet channelSet in MediaContext.From(Dispatcher).GetChannels(this))
            {
                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
        private static int markVisibleCountTotal; 
#endif
 
        private bool _isDisposed; 
        private SecurityCriticalDataForSet _rootVisual;
        private RenderContext _cachedRenderContext; 
        private Matrix _worldTransform = Matrix.Identity;

        //
        // 

 
 

        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

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK