CompositionTarget.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / CompositionTarget.cs / 1305600 / 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
        }; 

        //---------------------------------------------------------------------
        //
        //  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(this, outOfBandChannel, s_contentRootType);
            Debug.Assert(resourceCreated); 
            _contentRoot.DuplicateHandle(outOfBandChannel, channel);
            outOfBandChannel.CloseBatch(); 
            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;

                GC.SuppressFinalize(this);
            } 
        }
 
        ///  
        /// 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 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. 
            //

            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
                // 
                Visual.PropagateFlags(
                    _rootVisual.Value,
                    VisualFlags.IsSubtreeDirtyForPrecompute,
                    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.Keyword.KeywordGeneral | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Info)) 
                {
                    etwTracingEnabled = true;
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientPrecomputeSceneBegin, EventTrace.Keyword.KeywordGraphics | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Info, PerfService.GetPerfElementID(this));
                } 

#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.Event.WClientPrecomputeSceneEnd, EventTrace.Keyword.KeywordGraphics | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Info); 
                }

#if DEBUG
                MediaTrace.RenderPass.Trace("Full Update"); 
#endif
 
                if (etwTracingEnabled) 
                {
                    EventTrace.EventProvider.TraceEvent( 
                            EventTrace.Event.WClientCompileSceneBegin, EventTrace.Keyword.KeywordGraphics | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Info, PerfService.GetPerfElementID(this));
                }

#if MEDIA_PERFORMANCE_COUNTERS 
                _renderRateTimer.Begin();
#endif 
 
                Compile(channel);
 
#if MEDIA_PERFORMANCE_COUNTERS
                _renderRateTimer.End();
#endif
 
                if (etwTracingEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent( 
                            EventTrace.Event.WClientCompileSceneEnd, EventTrace.Keyword.KeywordGraphics | EventTrace.Keyword.KeywordPerf, EventTrace.Level.Info);
                } 
            }


#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
        }
 
        #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; 
        }
 
        ///  
        /// 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); 

                ((DUCE.IResource)_rootVisual.Value).ReleaseOnChannel(channel);

                _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 

        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

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