/// <summary> /// AddRefOnChannel /// </summary> DUCE.ResourceHandle DUCE.IResource.AddRefOnChannel(DUCE.Channel channel) { // Reconsider the need for this lock when removing the MultiChannelResource. using (CompositionEngineLock.Acquire()) { return(AddRefOnChannelCore(channel)); } }
/// <summary> /// ReleaseOnChannel /// </summary> void DUCE.IResource.ReleaseOnChannel(DUCE.Channel channel) { // Reconsider the need for this lock when removing the MultiChannelResource. using (CompositionEngineLock.Acquire()) { ReleaseOnChannelCore(channel); } }
void DUCE.IResource.ReleaseOnChannel(DUCE.Channel channel) { using (CompositionEngineLock.Acquire()) { Debug.Assert(_duceResource.IsOnChannel(channel)); _duceResource.ReleaseOnChannel(channel); } }
/// <summary> /// Callback to disconnect on the right thread /// </summary> private object DoDisconnectHostedVisual(object arg) { using (CompositionEngineLock.Acquire()) { DoPendingDisconnect((DUCE.Channel)arg); } return(null); }
/// <summary> /// ReleaseOnChannel /// </summary> void DUCE.IResource.ReleaseOnChannel(DUCE.Channel channel) { EnsureState(); using (CompositionEngineLock.Acquire()) { ReleaseOnChannelCore(channel); } }
// Ensures that _samplerData is extended to 'position', and that // the specified value is inserted there. private void StashSamplerDataInPosition(int position, SamplerData newSampler, int maxIndex) { if (_samplerData == null) { _samplerData = new List <SamplerData?>(maxIndex); } if (_samplerData.Count <= position) { int numToAdd = position - _samplerData.Count + 1; for (int i = 0; i < numToAdd; i++) { _samplerData.Add((SamplerData?)null); } } if (!_samplerData[position].HasValue) { // Going from null to having a value, so increment count _samplerCount++; } System.Windows.Threading.Dispatcher dispatcher = this.Dispatcher; // Release the old value if it is a resource on channel. AddRef the // new value. if (dispatcher != null) { SamplerData?oldSampler = _samplerData[position]; Brush oldBrush = null; if (oldSampler.HasValue) { SamplerData ss = oldSampler.Value; oldBrush = ss._brush; } Brush newBrush = newSampler._brush; DUCE.IResource targetResource = (DUCE.IResource) this; using (CompositionEngineLock.Acquire()) { int channelCount = targetResource.GetChannelCount(); for (int channelIndex = 0; channelIndex < channelCount; channelIndex++) { DUCE.Channel channel = targetResource.GetChannel(channelIndex); Debug.Assert(!channel.IsOutOfBandChannel); Debug.Assert(!targetResource.GetHandle(channel).IsNull); ReleaseResource(oldBrush, channel); AddRefResource(newBrush, channel); } } } _samplerData[position] = newSampler; }
/// <summary> /// GetHandle /// </summary> DUCE.ResourceHandle DUCE.IResource.GetHandle(DUCE.Channel channel) { EnsureState(); using (CompositionEngineLock.Acquire()) { return(GetHandleCore(channel)); } }
DUCE.ResourceHandle DUCE.IResource.AddRefOnChannel(DUCE.Channel channel) { EnsureState(); using (CompositionEngineLock.Acquire()) { return(AddRefOnChannelCore(channel)); } }
DUCE.ResourceHandle DUCE.IResource.GetHandle(DUCE.Channel channel) { DUCE.ResourceHandle h; // Reconsider the need for this lock when removing the MultiChannelResource. using (CompositionEngineLock.Acquire()) { h = _duceResource.GetHandle(channel); } return(h); }
//------------------------------------------------------ // // Public Properties // //------------------------------------------------------ private static void VisualPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { VisualBrush target = ((VisualBrush)d); Visual oldV = (Visual)e.OldValue; // // If the Visual required layout but it is changed before we do Layout // on that Visual, then we dont want the async LayoutCallback method to run, // nor do we want the LayoutUpdated handler to run. So we abort/remove them. // if (target._pendingLayout) { // // Visual has to be a UIElement since _pendingLayout flag is // true only if we added the LayoutUpdated handler which can // only be done on UIElement. // UIElement element = (UIElement)oldV; Debug.Assert(element != null); element.LayoutUpdated -= target.OnLayoutUpdated; Debug.Assert(target._DispatcherLayoutResult != null); Debug.Assert(target._DispatcherLayoutResult.Status == System.Windows.Threading.DispatcherOperationStatus.Pending); bool abortStatus = target._DispatcherLayoutResult.Abort(); Debug.Assert(abortStatus); target._pendingLayout = false; } Visual newV = (Visual)e.NewValue; System.Windows.Threading.Dispatcher dispatcher = target.Dispatcher; if (dispatcher != null) { DUCE.IResource targetResource = (DUCE.IResource)target; using (CompositionEngineLock.Acquire()) { int channelCount = targetResource.GetChannelCount(); for (int channelIndex = 0; channelIndex < channelCount; channelIndex++) { DUCE.Channel channel = targetResource.GetChannel(channelIndex); Debug.Assert(!channel.IsOutOfBandChannel); Debug.Assert(!targetResource.GetHandle(channel).IsNull); target.ReleaseResource(oldV, channel); target.AddRefResource(newV, channel); } } } target.PropertyChanged(VisualProperty); }
/// <summary> /// GetHandle /// </summary> DUCE.ResourceHandle DUCE.IResource.GetHandle(DUCE.Channel channel) { DUCE.ResourceHandle handle; using (CompositionEngineLock.Acquire()) { handle = GetHandleCore(channel); } return(handle); }
DUCE.ResourceHandle DUCE.IResource.AddRefOnChannel(DUCE.Channel channel) { using (CompositionEngineLock.Acquire()) { if (_duceResource.CreateOrAddRefOnChannel(this, channel, ResourceType)) { UpdateResource(_duceResource.GetHandle(channel), channel); } return(_duceResource.GetHandle(channel)); } }
internal static void NotifyRedirectionEnvironmentChanged() { using (CompositionEngineLock.Acquire()) { // Check to see if we need to force software for the Vista Magnifier s_forceSoftareForGraphicsStreamMagnifier = UnsafeNativeMethods.WgxConnection_ShouldForceSoftwareForGraphicsStreamClient(); foreach (MediaContext mc in _mediaContexts) { mc.PostInvalidateRenderMode(); } } }
//------------------------------------------------------ // // Public Properties // //------------------------------------------------------ private static void PixelShaderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ShaderEffect target = ((ShaderEffect)d); target.PixelShaderPropertyChangedHook(e); // The first change to the default value of a mutable collection property (e.g. GeometryGroup.Children) // will promote the property value from a default value to a local value. This is technically a sub-property // change because the collection was changed and not a new collection set (GeometryGroup.Children. // Add versus GeometryGroup.Children = myNewChildrenCollection). However, we never marshalled // the default value to the compositor. If the property changes from a default value, the new local value // needs to be marshalled to the compositor. We detect this scenario with the second condition // e.OldValueSource != e.NewValueSource. Specifically in this scenario the OldValueSource will be // Default and the NewValueSource will be Local. if (e.IsASubPropertyChange && (e.OldValueSource == e.NewValueSource)) { return; } PixelShader oldV = (PixelShader)e.OldValue; PixelShader newV = (PixelShader)e.NewValue; System.Windows.Threading.Dispatcher dispatcher = target.Dispatcher; if (dispatcher != null) { DUCE.IResource targetResource = (DUCE.IResource)target; using (CompositionEngineLock.Acquire()) { int channelCount = targetResource.GetChannelCount(); for (int channelIndex = 0; channelIndex < channelCount; channelIndex++) { DUCE.Channel channel = targetResource.GetChannel(channelIndex); Debug.Assert(!channel.IsOutOfBandChannel); Debug.Assert(!targetResource.GetHandle(channel).IsNull); target.ReleaseResource(oldV, channel); target.AddRefResource(newV, channel); } } } target.PropertyChanged(PixelShaderProperty); }
/// <summary> /// /// </summary> internal override void FreeContent(DUCE.Channel channel) { // // Disconnect hosted visual from this channel. // using (CompositionEngineLock.Acquire()) { DisconnectHostedVisual( channel, /* removeChannelFromCollection */ true); } base.FreeContent(channel); }
internal static bool ConnectChannels(MediaContext mc) { bool fCreated = false; using (CompositionEngineLock.Acquire()) { if (IsTransportConnected) { mc.CreateChannels(); fCreated = true; } } return(fCreated); }
DUCE.ResourceHandle DUCE.IResource.AddRefOnChannel(DUCE.Channel channel) { using (CompositionEngineLock.Acquire()) { if (_duceResource.CreateOrAddRefOnChannel(this, channel, System.Windows.Media.Composition.DUCE.ResourceType.TYPE_GUIDELINESET)) { AddRefOnChannelAnimations(channel); UpdateResource(channel, true /* skip "on channel" check - we already know that we're on channel */); } return(_duceResource.GetHandle(channel)); } }
/// <summary> /// /// </summary> internal void EndHosting() { // // This method is executed on the visual target thread. // using (CompositionEngineLock.Acquire()) { Debug.Assert(_target != null); Debug.Assert(_target.Dispatcher.Thread == Thread.CurrentThread); DisconnectHostedVisualOnAllChannels(); _target = null; } }
/// <summary> /// Should be called from the VisualTarget thread /// when it is safe to access the composition node /// and out of band channel from the VisualTarget thread /// to allow for the handle duplication/channel commit /// </summary> internal object DoHandleDuplication(object channel) { DUCE.ResourceHandle targetsHandle = DUCE.ResourceHandle.Null; using (CompositionEngineLock.Acquire()) { targetsHandle = _target._contentRoot.DuplicateHandle(_target.OutOfBandChannel, (DUCE.Channel)channel); Debug.Assert(!targetsHandle.IsNull); _target.OutOfBandChannel.CloseBatch(); _target.OutOfBandChannel.Commit(); } return(targetsHandle); }
/// <summary> /// /// </summary> internal void BeginHosting(VisualTarget target) { // // This method is executed on the visual target thread. // Debug.Assert(target != null); Debug.Assert(target.Dispatcher.Thread == Thread.CurrentThread); using (CompositionEngineLock.Acquire()) { // // Check if another target is already hosted by this // visual and throw exception if this is the case. // if (_target != null) { throw new InvalidOperationException( SR.Get(SRID.VisualTarget_AnotherTargetAlreadyConnected) ); } _target = target; // // If HostVisual and VisualTarget on same thread, then call Invalidate // directly. Otherwise post invalidate message to the host visual thread // indicating that content update is required. // if (this.CheckAccess()) { Invalidate(); } else { Dispatcher.BeginInvoke( DispatcherPriority.Normal, (DispatcherOperationCallback) delegate(object args) { Invalidate(); return(null); }, null ); } } }
DUCE.ResourceHandle DUCE.IResource.GetHandle(DUCE.Channel channel) { DUCE.ResourceHandle handle; // Reconsider the need for this lock when removing the MultiChannelResource. using (CompositionEngineLock.Acquire()) { // This method is a short cut and must only be called while the ref count // of this resource on this channel is non-zero. Thus we assert that this // resource is already on this channel. Debug.Assert(_duceResource.IsOnChannel(channel)); handle = _duceResource.GetHandle(channel); } return(handle); }
/// <summary> /// ReleaseOnChannel /// </summary> void DUCE.IResource.ReleaseOnChannel(DUCE.Channel channel) { // reconsider the need for this lock using (CompositionEngineLock.Acquire()) { Debug.Assert(_duceResource.IsOnChannel(channel)); //release from this channel _duceResource.ReleaseOnChannel(channel); if (!_duceResource.IsOnAnyChannel) { // If this was the last reference on the channel then clear up our state. // Again, we assume here that if the target DependencyObject is animated that // it will be associated with a Dispatcher and that this animation resource // will also be associated with that Dispatcher's channel. DependencyObject d = (DependencyObject)_dependencyObject.Target; // DependencyObject shouldn't have been garbage collected before we've // released all of its property animation resources. Debug.Assert(d != null); // The target DependencyObject should be associated with a Dispatcher. Debug.Assert(d.Dispatcher != null); // Make sure the target belongs to this thread Debug.Assert(d.CheckAccess()); // If we're invalid, that means we've added our _updateResourceHandler to the // MediaContext's ResourcesUpdated event. Since we've been entirely released // from the channel we can cancel this update by removing the handler. if (!_isValid) { MediaContext mediaContext = MediaContext.From(d.Dispatcher); mediaContext.ResourcesUpdated -= _updateResourceHandler; _isValid = true; } _updateResourceHandler = null; } } }
public static bool Startup(MediaContext mc) { // // Note to stress triagers: // // This call will fail if PresentationCore.dll and milcore.dll have mismatched // versions -- please make sure that both binaries have been properly built // and deployed. // // *** Failure here does NOT indicate a bug in MediaContext.Startup! *** // HRESULT.Check(UnsafeNativeMethods.MilVersionCheck(MS.Internal.Composition.Version.MilSdkVersion)); using (CompositionEngineLock.Acquire()) { _mediaContexts.Add(mc); //Is this the first startup? if (0 == s_refCount) { HRESULT.Check(SafeNativeMethods.MilCompositionEngine_InitializePartitionManager( 0 // THREAD_PRIORITY_NORMAL )); s_forceSoftareForGraphicsStreamMagnifier = UnsafeNativeMethods.WgxConnection_ShouldForceSoftwareForGraphicsStreamClient(); ConnectTransport(); // Read a flag from the registry to determine whether we should run // animation smoothing code. ReadAnimationSmoothingSetting(); } s_refCount++; } // Consider making MediaSystem.ConnectTransport return the state of transport connectedness so // that we can initialize the media system to a disconnected state. return(true); }
internal static void Shutdown(MediaContext mc) { using (CompositionEngineLock.Acquire()) { Debug.Assert(s_refCount > 0); _mediaContexts.Remove(mc); s_refCount--; if (0 == s_refCount) { // We can shut-down. // Debug.WriteLine("MediSystem::NotifyDisconnect Stop Transport\n"); if (IsTransportConnected) { DisconnectTransport(); } HRESULT.Check(SafeNativeMethods.MilCompositionEngine_DeinitializePartitionManager()); } } }
/// <summary> /// /// </summary> internal override void FreeContent(DUCE.Channel channel) { // // Disconnect hosted visual from this channel. // using (CompositionEngineLock.Acquire()) { // if there's a pending disconnect, do it now preemptively; // otherwise do the disconnect the normal way. // This ensures we do the disconnect before calling base, // as required. if (!DoPendingDisconnect(channel)) { DisconnectHostedVisual( channel, /* removeChannelFromCollection */ true); } } base.FreeContent(channel); }
void DUCE.IResource.ReleaseOnChannel(DUCE.Channel channel) { using (CompositionEngineLock.Acquire()) { Debug.Assert(_duceResource.IsOnChannel(channel)); // AddRef'ing or Releasing the renderdata itself doesn't propgate through the dependents, // unless our ref goes from or to 0. This is why we have this if statement guarding // the inner loop. if (_duceResource.ReleaseOnChannel(channel)) { for (int i = 0; i < _dependentResources.Count; i++) { DUCE.IResource resource = _dependentResources[i] as DUCE.IResource; if (resource != null) { resource.ReleaseOnChannel(channel); } } } } }
void DUCE.IResource.ReleaseOnChannel(DUCE.Channel channel) { using (CompositionEngineLock.Acquire()) { Debug.Assert(_duceResource.IsOnChannel(channel)); if (_duceResource.ReleaseOnChannel(channel)) { Brush vBrush = Brush; if (vBrush != null) { ((DUCE.IResource)vBrush).ReleaseOnChannel(channel); } DashStyle vDashStyle = DashStyle; if (vDashStyle != null) { ((DUCE.IResource)vDashStyle).ReleaseOnChannel(channel); } ReleaseOnChannelAnimations(channel); } } }
/// <summary> /// AddRefOnChannel /// </summary> DUCE.ResourceHandle DUCE.IResource.AddRefOnChannel(DUCE.Channel channel) { // reconsider the need for this lock using (CompositionEngineLock.Acquire()) { #if DEBUG // We assume that a multi-channel resource can only be multi-channel // if it is Frozen and does not have animated properties. In this case we know // the target resource has at least one animated property so we expect that this // independently animated property resource will only be added to the channel // associated with the MediaContext associated with the target object's Dispatcher. DependencyObject d = (DependencyObject)_dependencyObject.Target; // I'm not sure how our target animated DependencyObject would get garbage // collected before we call AddRefOnChannel on one of its animated property // resources, but if it happens it will be a bad thing. Debug.Assert(d != null); // Any animated DependencyObject must be associated with a Dispatcher because the // AnimationClocks doing the animating must be associated with a Dispatcher. Debug.Assert(d.Dispatcher != null); // Make sure the target belongs to this thread Debug.Assert(d.CheckAccess()); #endif if (_duceResource.CreateOrAddRefOnChannel(this, channel, ResourceType)) { _updateResourceHandler = new MediaContext.ResourcesUpdatedHandler(UpdateResource); UpdateResourceCore(channel); } return(_duceResource.GetHandle(channel)); } }
//------------------------------------------------------ // // Public Properties // //------------------------------------------------------ private static void ChildrenPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // The first change to the default value of a mutable collection property (e.g. GeometryGroup.Children) // will promote the property value from a default value to a local value. This is technically a sub-property // change because the collection was changed and not a new collection set (GeometryGroup.Children. // Add versus GeometryGroup.Children = myNewChildrenCollection). However, we never marshalled // the default value to the compositor. If the property changes from a default value, the new local value // needs to be marshalled to the compositor. We detect this scenario with the second condition // e.OldValueSource != e.NewValueSource. Specifically in this scenario the OldValueSource will be // Default and the NewValueSource will be Local. if (e.IsASubPropertyChange && (e.OldValueSource == e.NewValueSource)) { return; } Model3DGroup target = ((Model3DGroup)d); // If this is both non-null and mutable, we need to unhook the Changed event. Model3DCollection oldCollection = null; Model3DCollection newCollection = null; if ((e.OldValueSource != BaseValueSourceInternal.Default) || e.IsOldValueModified) { oldCollection = (Model3DCollection)e.OldValue; if ((oldCollection != null) && !oldCollection.IsFrozen) { oldCollection.ItemRemoved -= target.ChildrenItemRemoved; oldCollection.ItemInserted -= target.ChildrenItemInserted; } } // If this is both non-null and mutable, we need to hook the Changed event. if ((e.NewValueSource != BaseValueSourceInternal.Default) || e.IsNewValueModified) { newCollection = (Model3DCollection)e.NewValue; if ((newCollection != null) && !newCollection.IsFrozen) { newCollection.ItemInserted += target.ChildrenItemInserted; newCollection.ItemRemoved += target.ChildrenItemRemoved; } } if (oldCollection != newCollection && target.Dispatcher != null) { using (CompositionEngineLock.Acquire()) { DUCE.IResource targetResource = (DUCE.IResource)target; int channelCount = targetResource.GetChannelCount(); for (int channelIndex = 0; channelIndex < channelCount; channelIndex++) { DUCE.Channel channel = targetResource.GetChannel(channelIndex); Debug.Assert(!channel.IsOutOfBandChannel); Debug.Assert(!targetResource.GetHandle(channel).IsNull); // resource shouldn't be null because // 1) If the field is one of our collections, we don't allow null elements // 2) Codegen already made sure the collection contains DUCE.IResources // ... so we'll Assert it if (newCollection != null) { int count = newCollection.Count; for (int i = 0; i < count; i++) { DUCE.IResource resource = newCollection.Internal_GetItem(i) as DUCE.IResource; Debug.Assert(resource != null); resource.AddRefOnChannel(channel); } } if (oldCollection != null) { int count = oldCollection.Count; for (int i = 0; i < count; i++) { DUCE.IResource resource = oldCollection.Internal_GetItem(i) as DUCE.IResource; Debug.Assert(resource != null); resource.ReleaseOnChannel(channel); } } } } } target.PropertyChanged(ChildrenProperty); }
//---------------------------------------------------------------------- // // Private Methods // //---------------------------------------------------------------------- #region Private Methods /// <summary> /// Connects the hosted visual on a channel if necessary. /// </summary> private void EnsureHostedVisualConnected(DUCE.Channel channel) { // // Conditions for connecting VisualTarget to Host Visual:- // 1. The channel on which we are rendering should not be synchronous. This // scenario is not supported currently. // 2. VisualTarget should not be null. // 3. They should not be already connected. // if (!(channel.IsSynchronous) && _target != null && !_connectedChannels.Contains(channel)) { Debug.Assert(IsOnChannel(channel)); DUCE.ResourceHandle targetsHandle = DUCE.ResourceHandle.Null; bool doDuplication = true; // // If HostVisual and VisualTarget are on same thread, then we just addref // VisualTarget. Otherwise, if on different threads, then we duplicate // VisualTarget onto Hostvisual's channel. // if (_target.CheckAccess()) { Debug.Assert(_target._contentRoot.IsOnChannel(channel)); Debug.Assert(_target.OutOfBandChannel == MediaContext.CurrentMediaContext.OutOfBandChannel); bool created = _target._contentRoot.CreateOrAddRefOnChannel(this, channel, VisualTarget.s_contentRootType); Debug.Assert(!created); targetsHandle = _target._contentRoot.GetHandle(channel); } else { // // Duplicate the target's handle onto our channel. // // We must wait synchronously for the _targets Dispatcher to call // back and do handle duplication. We can't do handle duplication // on this thread because access to the _target CompositionNode // is not synchronized. If we duplicated here, we could potentially // corrupt the _target OutOfBandChannel or the CompositionNode // MultiChannelResource. We have to wait synchronously because // we need the resulting duplicated handle to hook up as a child // to this HostVisual. // object returnValue = _target.Dispatcher.Invoke( DispatcherPriority.Normal, TimeSpan.FromMilliseconds(1000), new DispatcherOperationCallback(DoHandleDuplication), channel ); // // Duplication and flush is complete, we can resume processing // Only if the Invoke succeeded will we have a handle returned. // if (returnValue != null) { targetsHandle = (DUCE.ResourceHandle)returnValue; } else { // The Invoke didn't complete doDuplication = false; } } if (doDuplication) { if (!targetsHandle.IsNull) { using (CompositionEngineLock.Acquire()) { DUCE.CompositionNode.InsertChildAt( _proxy.GetHandle(channel), targetsHandle, 0, channel); } _connectedChannels.Add(channel); // // Indicate that that content composition root has been // connected, this needs to be taken into account to // properly manage children of this visual. // SetFlags(channel, true, VisualProxyFlags.IsContentNodeConnected); } } else { // // We didn't get a handle, because _target belongs to a // different thread, and the Invoke operation failed. We can't do // anything except try again in the next render pass. We can't // call Invalidate during the render pass because it pushes up // flags that are being modified within the render pass, so get // the local Dispatcher to do it for us later. // Dispatcher.BeginInvoke( DispatcherPriority.Normal, (DispatcherOperationCallback) delegate(object args) { Invalidate(); return(null); }, null ); } } }