Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / Media / RealizationContext.cs / 2 / RealizationContext.cs
//------------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
// Description:
// Accumulates state during a realization pass of the scene.
//
//-----------------------------------------------------------------------------
using System;
using System.Windows.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Composition;
using System.Runtime.InteropServices;
using MS.Internal;
using System.Windows.Media.Media3D;
namespace System.Windows.Media
{
///
/// Implemented by resources that need realizations.
///
internal interface IRealizationContextClient
{
void ExecuteRealizationsUpdate();
}
internal struct RealizationBrushHelper
{
internal RealizationBrushHelper(Pen stroke, Brush fill)
{
_stroke = null;
if (stroke != null)
{
_stroke = stroke.Brush;
}
_fill = fill;
}
internal bool NeedsRealizationUpdates
{
get
{
return (_stroke != null && _stroke.RequiresRealizationUpdates)
|| (_fill != null && _fill.RequiresRealizationUpdates);
}
}
internal void UpdateRealizations(Rect strokeBounds, Rect fillBounds, RealizationContext ctx)
{
if (_stroke != null)
{
_stroke.UpdateRealizations(strokeBounds, ctx);
}
if (_fill != null)
{
_fill.UpdateRealizations(fillBounds, ctx);
}
}
private Brush _fill;
private Brush _stroke;
}
///
/// This class accumulates state during a realization pass of the scene.
///
///
/// This class is to replace RenderContext during the realization pass.
///
internal sealed class RealizationContext
{
//---------------------------------------------------------------------
//
// Private Types
//
//---------------------------------------------------------------------
#region Private Types
///
/// Storage manager for the schedule finalization calls.
///
private class RealizationUpdateSchedule
{
// ----------------------------------------------------------------
// -- CONSTRUCTOR -------------------------------------------------
///
/// Creates a new schedule list.
///
internal RealizationUpdateSchedule()
{
_schedule = new List(INITIAL_SIZE);
}
// ---------------------------------------------------------------
// -- METHODS ------------------------------------------------------
///
/// Adds an object to the realization update schedule.
///
/// The object to be scheduled.
internal void Schedule(IRealizationContextClient client)
{
if (client != null)
{
_schedule.Add(client);
}
}
///
/// Executes the schedule list.
///
internal void Execute()
{
try
{
foreach (IRealizationContextClient scheduled in _schedule)
{
// guaranteed to be not null, see the Schedule method
scheduled.ExecuteRealizationsUpdate();
}
}
finally
{
_schedule.Clear();
}
}
///
/// Instead of allocating and releasing memory continuously while scheduling
/// and clearing the list, we call the optimize method after each frame
/// to readjust the internal list capacity.
///
///
internal void Optimize()
{
Debug.Assert(_schedule.Count == 0); // The list must be empty before this is called.
Debug.Assert(_highWaterMark <= _schedule.Capacity);
// After TRIM_COUNT calls to this method we check the past usage of the stack.
if (_observeCount == TRIM_COUNT)
{
int newSize = Math.Max(_highWaterMark, INITIAL_SIZE);
if (newSize * SHRINK_FACTOR <= _schedule.Capacity)
{
// If the water mark is less or equal to capacity divided by the shrink
// factor, then we shrink the stack. Usually the shrink factor is greater
// than the grow factor. This avoids an oscillation of shrinking and growing
// the list if the high water mark goes only slightly up and down.
// Note that we don't need to copy the contents because the list is empty.
_schedule = new List(newSize);
}
_highWaterMark = 0;
_observeCount = 0;
}
else
{
// Keep incrementing our observe count
_observeCount++;
}
}
// ----------------------------------------------------------------
// -- PROPERTIES --------------------------------------------------
///
/// Checks if the schedule is empty.
///
internal bool IsEmpty
{
get { return _schedule.Count == 0; }
}
// ---------------------------------------------------------------
// -- FIELDS ------------------------------------------------------
// The storage for the scheduled finalization calls.
private List _schedule;
// The following fields are used to lazily manage the memory
// allocated by the stack.
private int _highWaterMark;
private int _observeCount;
// ---------------------------------------------------------------
// -- CONSTANTS ---------------------------------------------------
// The initial size of the schedule storage.
#if _DEBUG
private const int INITIAL_SIZE = 40;
#else
private const int INITIAL_SIZE = 4;
#endif
// The shrink factor for the schedule storage.
private const int SHRINK_FACTOR = 3;
// This constant is used to lazily manage the memory allocated
// by the list.
private const int TRIM_COUNT = 10;
}
#endregion Private Types
//---------------------------------------------------------------------
//
// Internal Constructors
//
//----------------------------------------------------------------------
#region Internal Constructors
///
/// Creates a world transform matrix stack for reuse between frames
/// and a list for finalization calls scheduling.
///
internal RealizationContext()
{
_transformStack = new MatrixStack();
_transform3DStack = new Matrix3DStack();
_scheduleList = new RealizationUpdateSchedule();
_drawingContextWalker = new RealizationDrawingContextWalker(this);
_visualsRequiringNextFrameRealizations = new ArrayList();
_currentVisualRequiresNewRealizationNextFrame = false;
}
#endregion Internal Constructors
//---------------------------------------------------------------------
//
// Internal Methods
//
//----------------------------------------------------------------------
#region Internal Methods
///
/// BeginFrame must be called before a frame is rendered.
///
internal void BeginFrame(
bool incrementalWalk, bool walkForBitmapRenderTarget
)
{
Debug.Assert(_transformStack.IsEmpty, "Matrix stack must be empty.");
Debug.Assert(_transform3DStack.IsEmpty, "3D transform stack must be empty.");
Debug.Assert(
_scheduleList.IsEmpty,
"The schedule list must be empty.");
Debug.Assert(_visualsRequiringNextFrameRealizations.Count == 0);
Debug.Assert(!_currentVisualRequiresNewRealizationNextFrame);
_targetChannels = null;
_currentTime = Environment.TickCount;
_incrementalPass = incrementalWalk;
_incrementalDisableCount = 0;
_walkForBitmapRenderTarget = walkForBitmapRenderTarget;
//
// At the beginning of a frame assume that we won't need any more
// frames in the future for additional realization work. Only if
// a resource makes a request for more cycles during the realization
// pass will we ask the MediaContext for more. In the meantime, if
// we previously hooked the Rendering event then unhook it now,
// because if we experience an exception during the realization
// pass the MediaContext will let the realization context object go
// to garbage collection. Keeping the event hooked would prevent it
// from being collected, and it would also prevent the event from
// being unhooked, which would cause the MedaiContext to continually
// render frames forever from that point on.
//
_needAdditionalFrames = false;
if (_requestedAdditionalFrames)
{
MediaContext.From(Dispatcher.CurrentDispatcher).Rendering -= _additionalFramesDelegate;
_requestedAdditionalFrames = false;
}
}
///
/// This method should be called after a frame has been rendered.
///
///
/// This method should be called after the realization context is not
/// needed anymore. The method expects that all stacks have been
/// cleared by popping all items from the stack.
///
/// NOTE: If for whatever reason the render pass should fail, the
/// realization context is thrown away since it might be in an
/// inconsistent state. In such cases EndFrame must not be called!
/// (There are ways to implement this cleaner, but it requires more
/// infra-structure for which there isn't really any need).
///
internal void EndFrame()
{
Debug.Assert(_transformStack.IsEmpty, "Matrix stack must be empty. The remark to the EndFrame method has more detail.");
Debug.Assert(_transform3DStack.IsEmpty, "Matrix3D stack must be empty.");
Debug.Assert(_scheduleList.IsEmpty, "The schedule list must be empty. The remark to the EndFrame method has more detail.");
_transformStack.Optimize();
_scheduleList.Optimize();
Debug.Assert(_incrementalDisableCount == 0);
//
// If a resource requested additional cycles during the last
// realization pass, use the MediaContext.Rendering event to schedule
// additional frames.
//
if (_needAdditionalFrames)
{
if (_additionalFramesDelegate == null)
{
_additionalFramesDelegate = delegate(object sender, EventArgs e) { };
}
MediaContext.From(Dispatcher.CurrentDispatcher).Rendering += _additionalFramesDelegate;
_requestedAdditionalFrames = true;
}
foreach (Visual v in _visualsRequiringNextFrameRealizations)
{
v.PropagateChangedFlags();
}
_visualsRequiringNextFrameRealizations.Clear();
}
///
/// Schedules a call to the method ExecuteRealizationsUpdate() for given object.
/// This method will be called only after completing traversing the tree,
/// so the client can gather complete information about all visible instances.
///
///
/// The client object that needs to have ExecuteRealizationsUpdate() to be called.
///
///
/// Note that we do not check for duplicated entries on the schedule.
/// It is the responsibility of the caller to ensure that no object
/// will be scheduled more than once if it is undesiderable.
///
internal void ScheduleForRealizationsUpdate(IRealizationContextClient client)
{
_scheduleList.Schedule(client);
}
///
/// Executes the deferred realizations update schedule.
///
///
internal void ExecuteRealizationsUpdateSchedule()
{
_scheduleList.Execute();
}
///
/// Callback from client that found itself in "incomplete" state
/// and wants more MarkVisibleRealization() calls.
/// When this routine is being called in animated scenario,
/// it does not infer any additional burden. The essential is
/// the completion of animation pass. When everything have got
/// stabilized, this call forces additional rendering pass
/// that allow client to detect animation completion and
/// optimize their looking on the screen.
///
///
internal void ScheduleAdditionalFrames()
{
_needAdditionalFrames = true;
_currentVisualRequiresNewRealizationNextFrame = true;
}
///
/// Designed to be called from only within a Visual after it has
/// called UpdateRealizations on its content. This will check
/// if the content contained glyphs which require a new realization
/// on the next frame outside of normal realization affecting
/// changes to the tree. This is required at the end of an animation
/// to re-render text which has completed an animation at a higher
/// fidelity. If new realizations are required, the Visual is added to
/// a list of Visuals to have the appropriate flags set after the realization
/// pass completes.
///
///
internal void CheckVisualRequiresNextFrameRealizations(Visual v)
{
if (_currentVisualRequiresNewRealizationNextFrame)
{
_visualsRequiringNextFrameRealizations.Add(v);
_currentVisualRequiresNewRealizationNextFrame = false;
}
}
///
/// Sets or resets "in 3d mode" flag to notify traversed resources in subtree.
///
///
/// "in 3d mode" flag before the call
internal bool Set3DMode(bool mode)
{
bool oldMode = _3DMode;
_3DMode = mode;
return oldMode;
}
///
/// Checks "in 3d mode" flag recently set by Set3DMode.
///
///
internal bool IsIn3DMode()
{
return _3DMode;
}
#endregion Internal Methods
//----------------------------------------------------------------------
//
// Internal Properties
//
//---------------------------------------------------------------------
#region Internal Properties
///
/// Returns the current channels.
///
internal List Channels
{
get
{
Debug.Assert(_targetChannels.Count >= 1);
#if DEBUG
foreach (DUCE.ChannelSet channelSet in _targetChannels)
{
Debug.Assert(channelSet.Channel.IsConnected);
}
#endif
return _targetChannels;
}
set { _targetChannels = value; }
}
///
/// Returns the matrix stack for maintaining the world transform.
///
internal MatrixStack TransformStack
{
get { return _transformStack; }
}
///
/// Returns the 3d matrix stack for maintaining the 3d transform.
///
internal Matrix3DStack Transform3DStack
{
get { return _transform3DStack; }
}
///
/// Gets the number of milliseconds elapsed since the system started
/// till traversal pass has been started.
///
internal int CurrentTime
{
get { return _currentTime; }
}
///
/// Returns the cached realization drawing context walker.
///
///
/// Note that it is safe to re-use this walker as the only
/// state it has is the operation type stack used to balance
/// push and pop instructions.
///
internal RealizationDrawingContextWalker DrawingContextWalker
{
get
{
return _drawingContextWalker;
}
}
///
/// Gets the window clip
///
internal Rect WindowClip
{
get { return _windowClip; }
set { _windowClip = value; }
}
///
/// Get the base transform
///
internal Matrix BaseTransform
{
get { return _baseTransform; }
set { _baseTransform = value; }
}
///
/// Reports what type of walk is occurring at
/// the current time. The walk can be incremental (updated
/// nodes only, true) or complete (all nodes containing
/// realizations, false). This value can change within a single
/// realization pass. The reason for this is that when a node
/// which requires new realizations
/// (has NodeRequiresNewRealization flag set) is encountered,
/// all of its children which contain realizations are also dirty
/// for realization updates, whether they are marked so or not.
/// We refer to this as a "fan out" effect from the original
/// node.
///
internal bool IncrementalWalk
{
get { return _incrementalPass && (_incrementalDisableCount == 0); }
}
///
/// This is called pre-subgraph to temporarily disable the incremental
/// walk so that we can "fan out" and touch all the
/// realization requiring nodes underneath a node that
/// is marked dirty for realizations. See comment for
/// IncrementalWalk for detail.
///
internal void DisableIncrementalWalk()
{
_incrementalDisableCount++;
}
///
/// This is called post-subgraph to re-enable the
/// incremental walk after "fanning out" below
/// a node that requires new realizations. See comments
/// on IncrementalWalk and DisableIncrementalWalk() also.
///
internal void EnableIncrementalWalk()
{
if (_incrementalDisableCount > 0)
{
_incrementalDisableCount--;
}
}
///
/// (See DevDiv Bug 107454). WalkForBitmapRenderTarget indicates that in the current
/// frame, we are performing the Visual tree walk as part of a bitmap render as opposed
/// to a regular render visual tree walk. The purpose of this flag is to
/// prevent Visual flags (NodeRequiresNewRealization, NodeInSubtreeRequiresNewRealization)
/// from being reset at the end of the walk, which would cause realizations
/// to not be applied later when a "regular" render pass occurs.
///
internal bool WalkForBitmapRenderTarget
{
get
{
return _walkForBitmapRenderTarget;
}
}
#endregion Internal Properties
//----------------------------------------------------------------------
//
// Private Fields
//
//---------------------------------------------------------------------
#region Private Fields
// The channel we're operating on.
private List _targetChannels;
// Window clip
private Rect _windowClip;
// Base transform
private Matrix _baseTransform = Matrix.Identity;
// The transform stack.
private readonly MatrixStack _transformStack;
// 3D transform stack.
private readonly Matrix3DStack _transform3DStack;
// The list of objects scheduled for realization update finalization.
private readonly RealizationUpdateSchedule _scheduleList;
// Current time, in milliseconds
private int _currentTime;
// Cached realization drawing context walker
private readonly RealizationDrawingContextWalker _drawingContextWalker;
// True if we need to request additional future frames
private bool _needAdditionalFrames;
// True if we are previously requested additional frames from the MediaContext
private bool _requestedAdditionalFrames;
// True if are performing the visual walk for a BitmapRenderTarget (See DevDiv Bug 107454)
private bool _walkForBitmapRenderTarget;
// True if we need to mark the current Visual as requiring new realizations
// This is used when drawing glyphs in the content of a visual to allow them
// to be correctly updated after the final frame of an animation completes
private bool _currentVisualRequiresNewRealizationNextFrame;
// List of Visuals that require new realizations on the next frame. These
// are added after each Visual has its content
private ArrayList _visualsRequiringNextFrameRealizations;
// True while traversing Viewport3DVisual subtree
private bool _3DMode;
// The delegate we use to request frames from the MediaContext
private EventHandler _additionalFramesDelegate;
// State representing whether this is a full or incremental
// realization pass
private bool _incrementalPass;
// Stack counter for determining when we disable/enable incremental walk
private uint _incrementalDisableCount;
#endregion Private Fields
}
}
// 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
- RestClientProxyHandler.cs
- WebPartMenuStyle.cs
- HttpEncoder.cs
- PartialCachingAttribute.cs
- InputReportEventArgs.cs
- FreeFormDragDropManager.cs
- cookie.cs
- WebPartsPersonalization.cs
- MenuBindingsEditor.cs
- ProcessModelInfo.cs
- TextFormatterContext.cs
- FontStyles.cs
- DataGridRowDetailsEventArgs.cs
- ItemsPanelTemplate.cs
- UserPersonalizationStateInfo.cs
- RsaSecurityKey.cs
- NonVisualControlAttribute.cs
- TagMapCollection.cs
- HandleExceptionArgs.cs
- SqlReorderer.cs
- SoapSchemaImporter.cs
- TextAction.cs
- ModifiableIteratorCollection.cs
- Point3DKeyFrameCollection.cs
- SelectionItemProviderWrapper.cs
- CustomErrorCollection.cs
- DataGridViewColumnConverter.cs
- ApplicationDirectory.cs
- DocobjHost.cs
- MimeBasePart.cs
- PropertyManager.cs
- DesignerDataRelationship.cs
- HttpProfileBase.cs
- CalendarDay.cs
- PreviousTrackingServiceAttribute.cs
- XPathSelectionIterator.cs
- Table.cs
- XmlNamespaceDeclarationsAttribute.cs
- PassportAuthentication.cs
- InputMethod.cs
- SecurityTokenAuthenticator.cs
- SystemTcpStatistics.cs
- ConfigurationElementCollection.cs
- BoundColumn.cs
- PcmConverter.cs
- BlurEffect.cs
- ParameterModifier.cs
- LogEntrySerializer.cs
- SelectionListComponentEditor.cs
- BitmapEffectvisualstate.cs
- MonthCalendar.cs
- TextElementCollectionHelper.cs
- HierarchicalDataBoundControl.cs
- DetailsViewRow.cs
- basenumberconverter.cs
- IdentityModelStringsVersion1.cs
- MD5.cs
- UrlMapping.cs
- indexingfiltermarshaler.cs
- BuildResultCache.cs
- InputLangChangeEvent.cs
- HealthMonitoringSectionHelper.cs
- CapacityStreamGeometryContext.cs
- TextElementCollectionHelper.cs
- MenuItem.cs
- PrintDocument.cs
- UnauthorizedAccessException.cs
- SqlPersonalizationProvider.cs
- XmlUnspecifiedAttribute.cs
- ObjectNavigationPropertyMapping.cs
- PictureBox.cs
- HttpsTransportElement.cs
- WebPartVerbCollection.cs
- CodeDOMUtility.cs
- ScrollableControlDesigner.cs
- figurelength.cs
- NetCodeGroup.cs
- TcpHostedTransportConfiguration.cs
- TextBoxAutomationPeer.cs
- MimeImporter.cs
- SmtpSpecifiedPickupDirectoryElement.cs
- DecoderExceptionFallback.cs
- WindowsScrollBarBits.cs
- DataTableCollection.cs
- SHA384.cs
- ComEventsHelper.cs
- FormViewAutoFormat.cs
- RenamedEventArgs.cs
- ObjectSecurity.cs
- NonPrimarySelectionGlyph.cs
- LicenseProviderAttribute.cs
- EdmEntityTypeAttribute.cs
- XmlCharacterData.cs
- DynamicDataExtensions.cs
- TextUtf8RawTextWriter.cs
- TextWriterTraceListener.cs
- Quack.cs
- OdbcParameter.cs
- Qualifier.cs
- NavigateEvent.cs