Пример #1
0
        private static void BrushPropertyChanged(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;
            }


            SpecularMaterial target = ((SpecularMaterial)d);


            Brush oldV = (Brush)e.OldValue;
            Brush newV = (Brush)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(BrushProperty);
        }
Пример #2
0
        /// <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;
                }
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #6
0
        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);
                }
            }
        }
Пример #7
0
        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);
                        }
                    }
                }
            }
        }
Пример #8
0
        /// <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));
            }
        }
Пример #9
0
        //------------------------------------------------------
        //
        //  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);
        }
Пример #10
0
        //----------------------------------------------------------------------
        //
        //  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
                        );
                }
            }
        }
        /// <summary>
        /// This should be called at the end of any method that alters the
        /// storage in any way.  This method will make sure the peer dp is
        /// set correctly and notify Animatables if something changes.
        /// </summary>
        internal void WritePostscript()
        {
            DependencyObject d = (DependencyObject)_dependencyObject.Target;

            if (d == null)
            {
                return;
            }

            FrugalMap animatedPropertyMap = AnimatedPropertyMapField.GetValue(d);

            if (animatedPropertyMap.Count == 0 ||
                animatedPropertyMap[_dependencyProperty.GlobalIndex] == DependencyProperty.UnsetValue)
            {
                if (!IsEmpty)
                {
                    // This is kind of tricky:
                    //
                    // Because FrugalMap is a struct instead of a class, we must
                    // be sure to add this AnimationStorage to the map before
                    // setting the FrugalMap into the UncommonField storage. If
                    // we don't and the FrugalMap is empty then an empty FrugalMap
                    // will be set into the UncommonField storage. If we were to
                    // then add our AnimationStorage to the local FrugalMap, it
                    // would only allocate its own internal storage at that point
                    // which would not apply to the FrugalMap we set into the
                    // UncommonField storage. Once a FrugalMap has allocated its
                    // internal storage, though, that storage is copied with the
                    // FrugalMap. This is what will happen when we add our
                    // AnimationStorage to the FrugalMap first as we do below:

                    animatedPropertyMap[_dependencyProperty.GlobalIndex] = this;

                    // Since FrugalMap is a struct and adding a new value to it
                    // may re-allocate the storage, we need to set this value
                    // each time we make a change to the map.

                    AnimatedPropertyMapField.SetValue(d, animatedPropertyMap);

                    if (animatedPropertyMap.Count == 1)
                    {
                        d.IAnimatable_HasAnimatedProperties = true;
                    }

                    // If this the target is an Animatable we'll need to
                    // invalidate it so that the animation resource for this
                    // newly animated property will be passed across to the UCE.
                    Animatable a = d as Animatable;

                    if (a != null)
                    {
                        a.RegisterForAsyncUpdateResource();
                    }

                    // If this AnimationStorage is a resource, add it to the
                    // channel now.
                    DUCE.IResource animationResource = this as DUCE.IResource;

                    if (animationResource != null)
                    {
                        DUCE.IResource targetResource = d as DUCE.IResource;

                        if (targetResource != null)
                        {
                            using (CompositionEngineLock.Acquire())
                            {
                                int channelCount = targetResource.GetChannelCount();

                                for (int i = 0; i < channelCount; i++)
                                {
                                    DUCE.Channel channel = targetResource.GetChannel(i);
                                    if (!targetResource.GetHandle(channel).IsNull)
                                    {
                                        animationResource.AddRefOnChannel(channel);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                Debug.Assert(animatedPropertyMap.Count > 0);
                Debug.Assert(animatedPropertyMap[_dependencyProperty.GlobalIndex] != DependencyProperty.UnsetValue);

                if (IsEmpty)
                {
                    // If this AnimationStorage is a resource, release it from
                    // the channel now.
                    DUCE.IResource animationResource = this as DUCE.IResource;

                    if (animationResource != null)
                    {
                        DUCE.IResource targetResource = d as DUCE.IResource;

                        if (targetResource != null)
                        {
                            using (CompositionEngineLock.Acquire())
                            {
                                int channelCount = targetResource.GetChannelCount();

                                for (int i = 0; i < channelCount; i++)
                                {
                                    DUCE.Channel channel = targetResource.GetChannel(i);
                                    if (!targetResource.GetHandle(channel).IsNull)
                                    {
                                        animationResource.ReleaseOnChannel(channel);
                                    }
                                }
                            }
                        }
                    }

                    // If this the target is an Animatable we'll need to
                    // invalidate it so that the animation resource for this
                    // no longer animated property will no longer be passed
                    // across to the UCE.
                    Animatable a = d as Animatable;

                    if (a != null)
                    {
                        a.RegisterForAsyncUpdateResource();
                    }

                    animatedPropertyMap[_dependencyProperty.GlobalIndex] = DependencyProperty.UnsetValue;

                    if (animatedPropertyMap.Count == 0)
                    {
                        AnimatedPropertyMapField.ClearValue(d);

                        d.IAnimatable_HasAnimatedProperties = false;
                    }
                    else
                    {
                        AnimatedPropertyMapField.SetValue(d, animatedPropertyMap);
                    }

                    // We've removed animation storage for this DP, so if we were storing the local
                    // base value here then it has to go back to its non-animated storage spot.
                    if (_baseValue != DependencyProperty.UnsetValue)
                    {
                        d.SetValue(_dependencyProperty, _baseValue);
                    }
                }
            }

            // recompute animated value
            d.InvalidateProperty(_dependencyProperty);
        }