internal void CreateChannels() { Invariant.Assert(_asyncChannel == null); Invariant.Assert(_asyncOutOfBandChannel == null); // Create a channel into the async composition device. // Pass in a reference to the global mediasystem channel so that it uses // the same partition. _asyncChannel = new DUCE.Channel( System.Windows.Media.MediaSystem.ServiceChannel, false, // not out of band System.Windows.Media.MediaSystem.Connection, false // [....] transport ); _asyncOutOfBandChannel = new DUCE.Channel( System.Windows.Media.MediaSystem.ServiceChannel, true, // out of band System.Windows.Media.MediaSystem.Connection, false // [....] transport ); }
internal abstract DUCE.ResourceHandle GetHandleCore(DUCE.Channel channel);
//------------------------------------------------------ // // Public Properties // //------------------------------------------------------ #region Public Properties #endregion Public Properties //------------------------------------------------------ // // Protected Methods // //------------------------------------------------------ #region Protected Methods #endregion ProtectedMethods //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods internal abstract DUCE.ResourceHandle AddRefOnChannelCore(DUCE.Channel channel);
protected abstract void UpdateResourceCore(DUCE.Channel channel);
/// <summary> /// This is only implemented by Visual and Visual3D. /// </summary> DUCE.ResourceHandle DUCE.IResource.Get3DHandle(DUCE.Channel channel) { throw new NotImplementedException(); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { base.UpdateResource(channel, skipOnChannelCheck); // Read values of properties into local variables Transform3D vTransform = Transform; // Obtain handles for properties that implement DUCE.IResource DUCE.ResourceHandle hTransform; if (vTransform == null || Object.ReferenceEquals(vTransform, Transform3D.Identity) ) { hTransform = DUCE.ResourceHandle.Null; } else { hTransform = ((DUCE.IResource)vTransform).GetHandle(channel); } // Obtain handles for animated properties DUCE.ResourceHandle hNearPlaneDistanceAnimations = GetAnimationResourceHandle(NearPlaneDistanceProperty, channel); DUCE.ResourceHandle hFarPlaneDistanceAnimations = GetAnimationResourceHandle(FarPlaneDistanceProperty, channel); DUCE.ResourceHandle hPositionAnimations = GetAnimationResourceHandle(PositionProperty, channel); DUCE.ResourceHandle hLookDirectionAnimations = GetAnimationResourceHandle(LookDirectionProperty, channel); DUCE.ResourceHandle hUpDirectionAnimations = GetAnimationResourceHandle(UpDirectionProperty, channel); DUCE.ResourceHandle hWidthAnimations = GetAnimationResourceHandle(WidthProperty, channel); // Pack & send command packet DUCE.MILCMD_ORTHOGRAPHICCAMERA data; unsafe { data.Type = MILCMD.MilCmdOrthographicCamera; data.Handle = _duceResource.GetHandle(channel); data.htransform = hTransform; if (hNearPlaneDistanceAnimations.IsNull) { data.nearPlaneDistance = NearPlaneDistance; } data.hNearPlaneDistanceAnimations = hNearPlaneDistanceAnimations; if (hFarPlaneDistanceAnimations.IsNull) { data.farPlaneDistance = FarPlaneDistance; } data.hFarPlaneDistanceAnimations = hFarPlaneDistanceAnimations; if (hPositionAnimations.IsNull) { data.position = CompositionResourceManager.Point3DToMilPoint3F(Position); } data.hPositionAnimations = hPositionAnimations; if (hLookDirectionAnimations.IsNull) { data.lookDirection = CompositionResourceManager.Vector3DToMilPoint3F(LookDirection); } data.hLookDirectionAnimations = hLookDirectionAnimations; if (hUpDirectionAnimations.IsNull) { data.upDirection = CompositionResourceManager.Vector3DToMilPoint3F(UpDirection); } data.hUpDirectionAnimations = hUpDirectionAnimations; if (hWidthAnimations.IsNull) { data.width = Width; } data.hWidthAnimations = hWidthAnimations; // Send packed command structure channel.SendCommand( (byte *)&data, sizeof(DUCE.MILCMD_ORTHOGRAPHICCAMERA)); } } }
internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { base.UpdateResource(channel, skipOnChannelCheck); // Read values of properties into local variables Transform3D vTransform = Transform; // Obtain handles for properties that implement DUCE.IResource DUCE.ResourceHandle hTransform; if (vTransform == null || Object.ReferenceEquals(vTransform, Transform3D.Identity) ) { hTransform = DUCE.ResourceHandle.Null; } else { hTransform = ((DUCE.IResource)vTransform).GetHandle(channel); } // Obtain handles for animated properties DUCE.ResourceHandle hColorAnimations = GetAnimationResourceHandle(ColorProperty, channel); DUCE.ResourceHandle hPositionAnimations = GetAnimationResourceHandle(PositionProperty, channel); DUCE.ResourceHandle hRangeAnimations = GetAnimationResourceHandle(RangeProperty, channel); DUCE.ResourceHandle hConstantAttenuationAnimations = GetAnimationResourceHandle(ConstantAttenuationProperty, channel); DUCE.ResourceHandle hLinearAttenuationAnimations = GetAnimationResourceHandle(LinearAttenuationProperty, channel); DUCE.ResourceHandle hQuadraticAttenuationAnimations = GetAnimationResourceHandle(QuadraticAttenuationProperty, channel); DUCE.ResourceHandle hDirectionAnimations = GetAnimationResourceHandle(DirectionProperty, channel); DUCE.ResourceHandle hOuterConeAngleAnimations = GetAnimationResourceHandle(OuterConeAngleProperty, channel); DUCE.ResourceHandle hInnerConeAngleAnimations = GetAnimationResourceHandle(InnerConeAngleProperty, channel); // Pack & send command packet DUCE.MILCMD_SPOTLIGHT data; unsafe { data.Type = MILCMD.MilCmdSpotLight; data.Handle = _duceResource.GetHandle(channel); data.htransform = hTransform; if (hColorAnimations.IsNull) { data.color = CompositionResourceManager.ColorToMilColorF(Color); } data.hColorAnimations = hColorAnimations; if (hPositionAnimations.IsNull) { data.position = CompositionResourceManager.Point3DToMilPoint3F(Position); } data.hPositionAnimations = hPositionAnimations; if (hRangeAnimations.IsNull) { data.range = Range; } data.hRangeAnimations = hRangeAnimations; if (hConstantAttenuationAnimations.IsNull) { data.constantAttenuation = ConstantAttenuation; } data.hConstantAttenuationAnimations = hConstantAttenuationAnimations; if (hLinearAttenuationAnimations.IsNull) { data.linearAttenuation = LinearAttenuation; } data.hLinearAttenuationAnimations = hLinearAttenuationAnimations; if (hQuadraticAttenuationAnimations.IsNull) { data.quadraticAttenuation = QuadraticAttenuation; } data.hQuadraticAttenuationAnimations = hQuadraticAttenuationAnimations; if (hDirectionAnimations.IsNull) { data.direction = CompositionResourceManager.Vector3DToMilPoint3F(Direction); } data.hDirectionAnimations = hDirectionAnimations; if (hOuterConeAngleAnimations.IsNull) { data.outerConeAngle = OuterConeAngle; } data.hOuterConeAngleAnimations = hOuterConeAngleAnimations; if (hInnerConeAngleAnimations.IsNull) { data.innerConeAngle = InnerConeAngle; } data.hInnerConeAngleAnimations = hInnerConeAngleAnimations; // Send packed command structure channel.SendCommand( (byte *)&data, sizeof(DUCE.MILCMD_SPOTLIGHT)); } } }
internal DUCE.ResourceHandle GetAnimationResourceHandle(DependencyProperty dp, DUCE.Channel channel) { if (channel != null && IAnimatable_HasAnimatedProperties) { return(IndependentAnimationStorage.GetResourceHandle(this, dp, channel)); } else { return(DUCE.ResourceHandle.Null); } }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { base.UpdateResource(channel, skipOnChannelCheck); // Read values of properties into local variables Transform vTransform = Transform; Transform vRelativeTransform = RelativeTransform; BitmapCache vBitmapCache = BitmapCache; Visual vInternalTarget = InternalTarget; // Obtain handles for properties that implement DUCE.IResource DUCE.ResourceHandle hTransform; if (vTransform == null || Object.ReferenceEquals(vTransform, Transform.Identity) ) { hTransform = DUCE.ResourceHandle.Null; } else { hTransform = ((DUCE.IResource)vTransform).GetHandle(channel); } DUCE.ResourceHandle hRelativeTransform; if (vRelativeTransform == null || Object.ReferenceEquals(vRelativeTransform, Transform.Identity) ) { hRelativeTransform = DUCE.ResourceHandle.Null; } else { hRelativeTransform = ((DUCE.IResource)vRelativeTransform).GetHandle(channel); } DUCE.ResourceHandle hBitmapCache = vBitmapCache != null ? ((DUCE.IResource)vBitmapCache).GetHandle(channel) : DUCE.ResourceHandle.Null; // Obtain handles for properties that implement DUCE.IResource DUCE.ResourceHandle hInternalTarget = vInternalTarget != null ? ((DUCE.IResource)vInternalTarget).GetHandle(channel) : DUCE.ResourceHandle.Null; // Obtain handles for animated properties DUCE.ResourceHandle hOpacityAnimations = GetAnimationResourceHandle(OpacityProperty, channel); // Pack & send command packet DUCE.MILCMD_BITMAPCACHEBRUSH data; unsafe { data.Type = MILCMD.MilCmdBitmapCacheBrush; data.Handle = _duceResource.GetHandle(channel); if (hOpacityAnimations.IsNull) { data.Opacity = Opacity; } data.hOpacityAnimations = hOpacityAnimations; data.hTransform = hTransform; data.hRelativeTransform = hRelativeTransform; data.hBitmapCache = hBitmapCache; data.hInternalTarget = hInternalTarget; // Send packed command structure channel.SendCommand( (byte *)&data, sizeof(DUCE.MILCMD_BITMAPCACHEBRUSH)); } } }
public void Invalidate(Int32Rect?dirtyRect) { SecurityHelper.DemandUnmanagedCode(); // A null dirty rect indicates the entire bitmap should be // invalidated, while a value indicates that only a dirty rect // should be invalidated. if (dirtyRect.HasValue) { dirtyRect.Value.ValidateForDirtyRect("dirtyRect", _pixelWidth, _pixelHeight); if (!dirtyRect.Value.HasArea) { // Nothing needs done. return; } } WritePreamble(); if (_unmanagedSource != null) { if (UsableWithoutCache) { // For bitmap sources that do not require caching on the // UI thread, we can just add a dirty rect to the // CWICWrapperBitmap. The render thread will respond by // updating the affected realizations by copying from this // bitmap. Since this bitmap is not cached, it will get // the most current bits. unsafe { for (int i = 0, numChannels = _duceResource.GetChannelCount(); i < numChannels; ++i) { DUCE.Channel channel = _duceResource.GetChannel(i); DUCE.MILCMD_BITMAP_INVALIDATE data; data.Type = MILCMD.MilCmdBitmapInvalidate; data.Handle = _duceResource.GetHandle(channel); bool useDirtyRect = dirtyRect.HasValue; if (useDirtyRect) { data.DirtyRect.left = dirtyRect.Value.X; data.DirtyRect.top = dirtyRect.Value.Y; data.DirtyRect.right = dirtyRect.Value.X + dirtyRect.Value.Width; data.DirtyRect.bottom = dirtyRect.Value.Y + dirtyRect.Value.Height; } data.UseDirtyRect = (uint)(useDirtyRect ? 1 : 0); channel.SendCommand((byte *)&data, sizeof(DUCE.MILCMD_BITMAP_INVALIDATE)); } } } else { // For bitmap sources that require caching on the // UI thread, we can't just add a dirty rect to the // CWICWrapperBitmap because it will just read the cached // contents again. We really need a caching bitmap // implementation that understands dirty rects and will // update its cache. Unfortunately, today the caching // bitmap is a standard WIC implementation, and does not // support this functionality. // // For now, we just recreate the caching bitmap. Setting // _needsUpdate to true will cause BitmapSource to throw // away the old DUCECompatiblePtr, and create a new caching // bitmap to send to the render thread. Since the render // thread sees a brand new bitmap, it will copy the bits out. _needsUpdate = true; RegisterForAsyncUpdateResource(); } } WritePostscript(); }
private void SendPresent(object sender, EventArgs args) { Debug.Assert(_isDirty); Debug.Assert(_isWaitingForPresent); Debug.Assert(_lockCount == 0); // // If we were waiting for present when the bitmap changed, SetBackBuffer removed // us from waiting for present. So if this is true then the NEW bitmap has been // dirtied before it has been sent to the render thread. We need to delay the // present until after the update resource because the D3DImage resource is still // referencing the old bitmap. // if (_waitingForUpdateResourceBecauseBitmapChanged) { return; } UnsubscribeFromCommittingBatch(); unsafe { DUCE.MILCMD_D3DIMAGE_PRESENT data; DUCE.Channel channel = sender as DUCE.Channel; Debug.Assert(_duceResource.IsOnChannel(channel)); data.Type = MILCMD.MilCmdD3DImagePresent; data.Handle = _duceResource.GetHandle(channel); // We need to make sure the event stays alive in case we get collected before // the composition thread processes the packet IntPtr hDuplicate; IntPtr hCurrentProc = MS.Win32.UnsafeNativeMethods.GetCurrentProcess(); if (!MS.Win32.UnsafeNativeMethods.DuplicateHandle( hCurrentProc, _canWriteEvent.SafeWaitHandle, hCurrentProc, out hDuplicate, 0, false, MS.Win32.UnsafeNativeMethods.DUPLICATE_SAME_ACCESS )) { throw new Win32Exception(); } data.hEvent = (ulong)hDuplicate.ToPointer(); // Send packed command structure // Note that the command is sent in its own batch (sendInSeparateBatch == true) because this method is called under the // context of the MediaContext.CommitChannel and the command needs to make it into the current set of changes which are // being commited to the compositor. If the command would not be added to a separate batch, it would go into the // "future" batch which would not get submitted this time around. This leads to a dead-lock situation which occurs when // the app calls Lock on the D3DImage because Lock waits on _canWriteEvent which the compositor sets when it sees the // Present command. However, since the compositor does not get the Present command, it will not set the event and the // UI thread will wait forever on the compositor which will cause the application to stop responding. channel.SendCommand( (byte *)&data, sizeof(DUCE.MILCMD_D3DIMAGE_PRESENT), true /* sendInSeparateBatch */ ); } _isDirty = false; // Block on next Lock _canWriteEvent.Reset(); }
/// <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); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { base.UpdateResource(channel, skipOnChannelCheck); // Read values of properties into local variables Point3DCollection vPositions = Positions; Vector3DCollection vNormals = Normals; PointCollection vTextureCoordinates = TextureCoordinates; Int32Collection vTriangleIndices = TriangleIndices; // Store the count of this resource's contained collections in local variables. int PositionsCount = (vPositions == null) ? 0 : vPositions.Count; int NormalsCount = (vNormals == null) ? 0 : vNormals.Count; int TextureCoordinatesCount = (vTextureCoordinates == null) ? 0 : vTextureCoordinates.Count; int TriangleIndicesCount = (vTriangleIndices == null) ? 0 : vTriangleIndices.Count; // Pack & send command packet DUCE.MILCMD_MESHGEOMETRY3D data; unsafe { data.Type = MILCMD.MilCmdMeshGeometry3D; data.Handle = _duceResource.GetHandle(channel); data.PositionsSize = (uint)(sizeof(MilPoint3F) * PositionsCount); data.NormalsSize = (uint)(sizeof(MilPoint3F) * NormalsCount); data.TextureCoordinatesSize = (uint)(sizeof(Point) * TextureCoordinatesCount); data.TriangleIndicesSize = (uint)(sizeof(Int32) * TriangleIndicesCount); channel.BeginCommand( (byte *)&data, sizeof(DUCE.MILCMD_MESHGEOMETRY3D), (int)(data.PositionsSize + data.NormalsSize + data.TextureCoordinatesSize + data.TriangleIndicesSize) ); // Copy this collection's elements (or their handles) to reserved data for (int i = 0; i < PositionsCount; i++) { MilPoint3F resource = CompositionResourceManager.Point3DToMilPoint3F(vPositions.Internal_GetItem(i)); channel.AppendCommandData( (byte *)&resource, sizeof(MilPoint3F) ); } // Copy this collection's elements (or their handles) to reserved data for (int i = 0; i < NormalsCount; i++) { MilPoint3F resource = CompositionResourceManager.Vector3DToMilPoint3F(vNormals.Internal_GetItem(i)); channel.AppendCommandData( (byte *)&resource, sizeof(MilPoint3F) ); } // Copy this collection's elements (or their handles) to reserved data for (int i = 0; i < TextureCoordinatesCount; i++) { Point resource = vTextureCoordinates.Internal_GetItem(i); channel.AppendCommandData( (byte *)&resource, sizeof(Point) ); } // Copy this collection's elements (or their handles) to reserved data for (int i = 0; i < TriangleIndicesCount; i++) { Int32 resource = vTriangleIndices.Internal_GetItem(i); channel.AppendCommandData( (byte *)&resource, sizeof(Int32) ); } channel.EndCommand(); } } }
private static void ConnectTransport() { if (IsTransportConnected) { throw new System.InvalidOperationException(SR.Get(SRID.MediaSystem_OutOfOrderConnectOrDisconnect)); } // // Create a default transport to be used by this media system. // If creation fails, fall back to a local transport. // HRESULT.Check(UnsafeNativeMethods.WgxConnection_Create( false, // false means asynchronous transport out s_pConnection)); // Create service channel used by global glyph cache. This channel is // the first channel created for the app, and by creating it with // a null channel reference it creates a new partition. // All subsequent channel creates will pass in a reference to this // channel thus using its partition. s_serviceChannel = new DUCE.Channel( null, false, // not out of band s_pConnection, false); IsTransportConnected = true; }
internal override DUCE.ResourceHandle GetHandleCore(DUCE.Channel channel) { // Note that we are in a lock here already. return(_duceResource.GetHandle(channel)); }
/// <summary> /// If the visual is on channel, its reference count is increased. /// Otherwise, a new resource is created on that channel. /// </summary> internal bool CreateOrAddRefOnChannel( object instance, DUCE.Channel channel, DUCE.ResourceType resourceType) { int index = Find(channel); int count = Count; if (index == PROXY_NOT_FOUND) { // // This is the case where we have to create a new resource. // if (_head.Channel == null) { // // We're adding the first proxy. // // Before: [empty] // After insert: [ head] // Debug.Assert(count == 0); _head.Channel = channel; _head.Flags = VisualProxyFlags.None; channel.CreateOrAddRefOnChannel( instance, ref _head.Handle, resourceType); } else { if (_tail == null) { // // We're adding the second proxy. // // Before: [head] // After resize: [head] [ empty] [empty] // After insert: [head] [tail 0] [empty] // ---------------- Debug.Assert(count == 1); _tail = new Proxy[2]; } else if (count > _tail.Length) { // // Increase the tail size by 2. // // Before: [head] [tail 0] ... [tail c-2] // After resize: [head] [tail 0] ... [tail c-2] [ empty] [empty] // After insert: [head] [tail 0] ... [tail c-3] [tail c-2] [empty] // ------------------------------------------ // ResizeTail(2); } // // Now that we have a tail, fill in the first free element. // Proxy proxy; proxy.Channel = channel; proxy.Flags = VisualProxyFlags.None; proxy.Handle = DUCE.ResourceHandle.Null; channel.CreateOrAddRefOnChannel( instance, ref proxy.Handle, resourceType); _tail[count - 1] = proxy; } return /* created */ (true); } else if (index == PROXY_STORED_INLINE) { // // We simply need to increase the reference count on head... // channel.CreateOrAddRefOnChannel( instance, ref _head.Handle, resourceType); } else { // // Increase the reference count on one of the tail proxies... // channel.CreateOrAddRefOnChannel( instance, ref _tail[index].Handle, resourceType); } return /* not created */ (false); }
/// <summary> /// If visual is on channel, its reference count is increased. /// Otherwise, a new resource is created on that channel. /// </summary> internal bool ReleaseOnChannel(DUCE.Channel channel) { int index = Find(channel); bool proxyRemoved = false; int count = Count; if (index == PROXY_STORED_INLINE) { if (channel.ReleaseOnChannel(_head.Handle)) { // // Need to move the last of the non-empty tail to head // or clear the head. Erase the head if that was the last // proxy. // if (count == 1) { _head = new Proxy(); } else { _head = _tail[count - 2]; } proxyRemoved = true; } } else if (index >= 0) { if (channel.ReleaseOnChannel(_tail[index].Handle)) { // // Need to move the last of the non-empty tail to the // removed index. Avoid in-place copying. // if (index != count - 2) { _tail[index] = _tail[count - 2]; } proxyRemoved = true; } } else { Debug.Assert(index != PROXY_NOT_FOUND); return(false); } if (proxyRemoved) { if (_tail != null) { // // Keep the tail short. We allow for one extra free element // in tail to avoid constant allocations / reallocations. // if (count == 2) { // ------------------ // Before removal: [head] [tail c-1] [empty] // Here and now: [head] [ deleted] [empty] // After removal: [head] // _tail = null; } else if (count == _tail.Length) { // --------------------------------------------------- // Before removal: [head] [tail 0] [tail 1] ... [tail c-3] [tail c-2] [empty] // Here and now: [head] [tail 0] [tail 1] ... [tail c-3] [ deleted] [empty] // After removal: [head] [tail 0] [tail 1] ... [tail c-3] // ResizeTail(-2); } else { // ------------------------------------------------------ // Before removal: [head] [tail 0] [tail 1] ... [tail c-4] [tail c-3] [tail c-2] // Here and now: [head] [tail 0] [tail 1] ... [tail c-4] [tail c-3] [ deleted] // After removal: [head] [tail 0] [tail 1] ... [tail c-4] [tail c-3] [ empty] // _tail[count - 2] = new Proxy(); } } } return(proxyRemoved); }
/// <summary> /// UpdateResource - this implements the prototype required by ResourcesUpdatedHandler /// The method which implements this prototype is also often called in situations where /// the resource is known to be "on channel" - in those cases, "true" is passed for the second /// parameter (allowing the implementation to skip the check). /// </summary> internal virtual void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { Animatable_IsResourceInvalidationNecessary = true; }
// ---------------------------------------------------------------- // // Internal Methods: resource handle getters // // ---------------------------------------------------------------- #region Internal Methods: resource handle getters /// <summary> /// Returns the handle the visual has on a specific channel. /// </summary> internal DUCE.ResourceHandle GetHandle(DUCE.Channel channel) { return(GetHandle(Find(channel) + 1)); // Find's results are -1 based, adjust by one. }
/// <summary> /// Render visual to printer. /// </summary> /// <param name="visual">Root of the visual to render</param> /// <param name="worldTransform">World transform to apply to the root visual</param> /// <param name="windowClip">The window clip of the outermost window or Empty</param> /// <param name="fRenderForBitmapEffect">True if we are rendering the visual /// to apply an effect to it</param> /// internal void Render(Visual visual, Matrix worldTransform, Rect windowClip) { if (visual == null) { throw new ArgumentNullException("visual"); } // If the bitmapTarget we're writing to is frozen then we can't proceed. Note that // it's possible for the BitmapVisualManager to be constructed with a mutable BitmapImage // and for the app to later freeze it. Such an application is misbehaving if // they subsequently try to render to the BitmapImage. if (_bitmapTarget.IsFrozen) { throw new ArgumentException(SR.Get(SRID.Image_CantBeFrozen)); } int sizeX = _bitmapTarget.PixelWidth; int sizeY = _bitmapTarget.PixelHeight; double dpiX = _bitmapTarget.DpiX; double dpiY = _bitmapTarget.DpiY; Debug.Assert((sizeX > 0) && (sizeY > 0)); Debug.Assert((dpiX > 0) && (dpiY > 0)); // validate the data if ((sizeX <= 0) || (sizeY <= 0)) { return; // nothing to draw } if ((dpiX <= 0) || (dpiY <= 0)) { dpiX = 96; dpiY = 96; } SafeMILHandle renderTargetBitmap = _bitmapTarget.MILRenderTarget; Debug.Assert(renderTargetBitmap != null, "Render Target is null"); IntPtr pIRenderTargetBitmap = IntPtr.Zero; try { // // Allocate a fresh synchronous channel. // MediaContext mctx = MediaContext.CurrentMediaContext; DUCE.Channel channel = mctx.AllocateSyncChannel(); // // Acquire the target bitmap. // Guid iidRTB = MILGuidData.IID_IMILRenderTargetBitmap; HRESULT.Check(UnsafeNativeMethods.MILUnknown.QueryInterface( renderTargetBitmap, ref iidRTB, out pIRenderTargetBitmap)); // // Render the visual on the synchronous channel. // Renderer.Render( pIRenderTargetBitmap, channel, visual, sizeX, sizeY, dpiX, dpiY, worldTransform, windowClip); // // Release the synchronous channel. This way we can // re-use that channel later. // mctx.ReleaseSyncChannel(channel); } finally { UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref pIRenderTargetBitmap); } _bitmapTarget.RenderTargetContentsChanged(); }
// ---------------------------------------------------------------- // // Internal Methods: visual proxy flags // // ---------------------------------------------------------------- #region Internal Methods: visual proxy flags /// <summary> /// Returns the flags the visual has on a specific channel. /// </summary> internal VisualProxyFlags GetFlags(DUCE.Channel channel) { return(GetFlags(Find(channel) + 1)); // Find's results are -1 based, adjust by one. }
/// <summary> /// This is only implemented by Visual and Visual3D. /// </summary> void DUCE.IResource.RemoveChildFromParent(DUCE.IResource parent, DUCE.Channel channel) { throw new NotImplementedException(); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { base.UpdateResource(channel, skipOnChannelCheck); // Read values of properties into local variables Transform vTransform = Transform; Transform vRelativeTransform = RelativeTransform; Visual vVisual = Visual; // Obtain handles for properties that implement DUCE.IResource DUCE.ResourceHandle hTransform; if (vTransform == null || Object.ReferenceEquals(vTransform, Transform.Identity) ) { hTransform = DUCE.ResourceHandle.Null; } else { hTransform = ((DUCE.IResource)vTransform).GetHandle(channel); } DUCE.ResourceHandle hRelativeTransform; if (vRelativeTransform == null || Object.ReferenceEquals(vRelativeTransform, Transform.Identity) ) { hRelativeTransform = DUCE.ResourceHandle.Null; } else { hRelativeTransform = ((DUCE.IResource)vRelativeTransform).GetHandle(channel); } // Obtain handles for properties that implement DUCE.IResource DUCE.ResourceHandle hVisual = vVisual != null ? ((DUCE.IResource)vVisual).GetHandle(channel) : DUCE.ResourceHandle.Null; // Obtain handles for animated properties DUCE.ResourceHandle hOpacityAnimations = GetAnimationResourceHandle(OpacityProperty, channel); DUCE.ResourceHandle hViewportAnimations = GetAnimationResourceHandle(ViewportProperty, channel); DUCE.ResourceHandle hViewboxAnimations = GetAnimationResourceHandle(ViewboxProperty, channel); // Pack & send command packet DUCE.MILCMD_VISUALBRUSH data; unsafe { data.Type = MILCMD.MilCmdVisualBrush; data.Handle = _duceResource.GetHandle(channel); if (hOpacityAnimations.IsNull) { data.Opacity = Opacity; } data.hOpacityAnimations = hOpacityAnimations; data.hTransform = hTransform; data.hRelativeTransform = hRelativeTransform; data.ViewportUnits = ViewportUnits; data.ViewboxUnits = ViewboxUnits; if (hViewportAnimations.IsNull) { data.Viewport = Viewport; } data.hViewportAnimations = hViewportAnimations; if (hViewboxAnimations.IsNull) { data.Viewbox = Viewbox; } data.hViewboxAnimations = hViewboxAnimations; data.Stretch = Stretch; data.TileMode = TileMode; data.AlignmentX = AlignmentX; data.AlignmentY = AlignmentY; data.CachingHint = (CachingHint)GetValue(RenderOptions.CachingHintProperty); data.CacheInvalidationThresholdMinimum = (double)GetValue(RenderOptions.CacheInvalidationThresholdMinimumProperty); data.CacheInvalidationThresholdMaximum = (double)GetValue(RenderOptions.CacheInvalidationThresholdMaximumProperty); data.hVisual = hVisual; // Send packed command structure channel.SendCommand( (byte *)&data, sizeof(DUCE.MILCMD_VISUALBRUSH)); } } }
internal static DUCE.ResourceHandle GetResourceHandle(DependencyObject d, DependencyProperty dp, DUCE.Channel channel) { Debug.Assert(d != null); Debug.Assert(dp != null); Debug.Assert(d is Animatable ? ((Animatable)d).HasAnimatedProperties : true); IndependentAnimationStorage storage = AnimationStorage.GetStorage(d, dp) as IndependentAnimationStorage; if (storage == null) { return(DUCE.ResourceHandle.Null); } else { Debug.Assert(storage._duceResource.IsOnChannel(channel)); return(((DUCE.IResource)storage).GetHandle(channel)); } }
private void ManualUpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { Transform vTransform = Transform; Transform vRelativeTransform = RelativeTransform; GradientStopCollection vGradientStops = GradientStops; DUCE.ResourceHandle hTransform; if (vTransform == null || Object.ReferenceEquals(vTransform, Transform.Identity) ) { hTransform = DUCE.ResourceHandle.Null; } else { hTransform = ((DUCE.IResource)vTransform).GetHandle(channel); } DUCE.ResourceHandle hRelativeTransform; if (vRelativeTransform == null || Object.ReferenceEquals(vRelativeTransform, Transform.Identity) ) { hRelativeTransform = DUCE.ResourceHandle.Null; } else { hRelativeTransform = ((DUCE.IResource)vRelativeTransform).GetHandle(channel); } DUCE.ResourceHandle hOpacityAnimations = GetAnimationResourceHandle(OpacityProperty, channel); DUCE.ResourceHandle hCenterAnimations = GetAnimationResourceHandle(CenterProperty, channel); DUCE.ResourceHandle hRadiusXAnimations = GetAnimationResourceHandle(RadiusXProperty, channel); DUCE.ResourceHandle hRadiusYAnimations = GetAnimationResourceHandle(RadiusYProperty, channel); DUCE.ResourceHandle hGradientOriginAnimations = GetAnimationResourceHandle(GradientOriginProperty, channel); DUCE.MILCMD_RADIALGRADIENTBRUSH data; unsafe { data.Type = MILCMD.MilCmdRadialGradientBrush; data.Handle = _duceResource.GetHandle(channel); double tempOpacity = Opacity; DUCE.CopyBytes((byte *)&data.Opacity, (byte *)&tempOpacity, 8); data.hOpacityAnimations = hOpacityAnimations; data.hTransform = hTransform; data.hRelativeTransform = hRelativeTransform; data.ColorInterpolationMode = ColorInterpolationMode; data.MappingMode = MappingMode; data.SpreadMethod = SpreadMethod; Point tempCenter = Center; DUCE.CopyBytes((byte *)&data.Center, (byte *)&tempCenter, 16); data.hCenterAnimations = hCenterAnimations; double tempRadiusX = RadiusX; DUCE.CopyBytes((byte *)&data.RadiusX, (byte *)&tempRadiusX, 8); data.hRadiusXAnimations = hRadiusXAnimations; double tempRadiusY = RadiusY; DUCE.CopyBytes((byte *)&data.RadiusY, (byte *)&tempRadiusY, 8); data.hRadiusYAnimations = hRadiusYAnimations; Point tempGradientOrigin = GradientOrigin; DUCE.CopyBytes((byte *)&data.GradientOrigin, (byte *)&tempGradientOrigin, 16); data.hGradientOriginAnimations = hGradientOriginAnimations; // NTRAID#Longhorn-1011154-2004/8/12-asecchia GradientStopCollection: Need to enforce upper-limit of gradient stop capacity int count = (vGradientStops == null) ? 0 : vGradientStops.Count; data.GradientStopsSize = (UInt32)(sizeof(DUCE.MIL_GRADIENTSTOP) * count); channel.BeginCommand( (byte *)&data, sizeof(DUCE.MILCMD_RADIALGRADIENTBRUSH), sizeof(DUCE.MIL_GRADIENTSTOP) * count ); for (int i = 0; i < count; i++) { DUCE.MIL_GRADIENTSTOP stopCmd; GradientStop gradStop = vGradientStops.Internal_GetItem(i); double temp = gradStop.Offset; DUCE.CopyBytes((byte *)&stopCmd.Position, (byte *)&temp, sizeof(double)); stopCmd.Color = CompositionResourceManager.ColorToMilColorF(gradStop.Color); channel.AppendCommandData( (byte *)&stopCmd, sizeof(DUCE.MIL_GRADIENTSTOP) ); } channel.EndCommand(); } } }
internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { ManualUpdateResource(channel, skipOnChannelCheck); base.UpdateResource(channel, skipOnChannelCheck); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { base.UpdateResource(channel, skipOnChannelCheck); // Obtain handles for animated properties DUCE.ResourceHandle hScaleXAnimations = GetAnimationResourceHandle(ScaleXProperty, channel); DUCE.ResourceHandle hScaleYAnimations = GetAnimationResourceHandle(ScaleYProperty, channel); DUCE.ResourceHandle hScaleZAnimations = GetAnimationResourceHandle(ScaleZProperty, channel); DUCE.ResourceHandle hCenterXAnimations = GetAnimationResourceHandle(CenterXProperty, channel); DUCE.ResourceHandle hCenterYAnimations = GetAnimationResourceHandle(CenterYProperty, channel); DUCE.ResourceHandle hCenterZAnimations = GetAnimationResourceHandle(CenterZProperty, channel); // Pack & send command packet DUCE.MILCMD_SCALETRANSFORM3D data; unsafe { data.Type = MILCMD.MilCmdScaleTransform3D; data.Handle = _duceResource.GetHandle(channel); if (hScaleXAnimations.IsNull) { data.scaleX = ScaleX; } data.hScaleXAnimations = hScaleXAnimations; if (hScaleYAnimations.IsNull) { data.scaleY = ScaleY; } data.hScaleYAnimations = hScaleYAnimations; if (hScaleZAnimations.IsNull) { data.scaleZ = ScaleZ; } data.hScaleZAnimations = hScaleZAnimations; if (hCenterXAnimations.IsNull) { data.centerX = CenterX; } data.hCenterXAnimations = hCenterXAnimations; if (hCenterYAnimations.IsNull) { data.centerY = CenterY; } data.hCenterYAnimations = hCenterYAnimations; if (hCenterZAnimations.IsNull) { data.centerZ = CenterZ; } data.hCenterZAnimations = hCenterZAnimations; // Send packed command structure channel.SendCommand( (byte *)&data, sizeof(DUCE.MILCMD_SCALETRANSFORM3D)); } } }
internal abstract void ReleaseOnChannelCore(DUCE.Channel channel);
/// <summary> /// Derived classes implement this function. /// </summary> void DUCE.IResource.ReleaseOnChannel(DUCE.Channel channel) { // Just return instead of throwing an exception, since some // derived classes like BitmapEffect do their own addref/release. }
internal override void UpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { base.UpdateResource(channel, skipOnChannelCheck); // Read values of properties into local variables DrawingCollection vChildren = Children; Geometry vClipGeometry = ClipGeometry; Brush vOpacityMask = OpacityMask; Transform vTransform = Transform; GuidelineSet vGuidelineSet = GuidelineSet; // Obtain handles for properties that implement DUCE.IResource DUCE.ResourceHandle hClipGeometry = vClipGeometry != null ? ((DUCE.IResource)vClipGeometry).GetHandle(channel) : DUCE.ResourceHandle.Null; DUCE.ResourceHandle hOpacityMask = vOpacityMask != null ? ((DUCE.IResource)vOpacityMask).GetHandle(channel) : DUCE.ResourceHandle.Null; DUCE.ResourceHandle hTransform; if (vTransform == null || Object.ReferenceEquals(vTransform, Transform.Identity) ) { hTransform = DUCE.ResourceHandle.Null; } else { hTransform = ((DUCE.IResource)vTransform).GetHandle(channel); } DUCE.ResourceHandle hGuidelineSet = vGuidelineSet != null ? ((DUCE.IResource)vGuidelineSet).GetHandle(channel) : DUCE.ResourceHandle.Null; // Obtain handles for animated properties DUCE.ResourceHandle hOpacityAnimations = GetAnimationResourceHandle(OpacityProperty, channel); // Store the count of this resource's contained collections in local variables. int ChildrenCount = (vChildren == null) ? 0 : vChildren.Count; // Pack & send command packet DUCE.MILCMD_DRAWINGGROUP data; unsafe { data.Type = MILCMD.MilCmdDrawingGroup; data.Handle = _duceResource.GetHandle(channel); data.ChildrenSize = (uint)(sizeof(DUCE.ResourceHandle) * ChildrenCount); data.hClipGeometry = hClipGeometry; if (hOpacityAnimations.IsNull) { data.Opacity = Opacity; } data.hOpacityAnimations = hOpacityAnimations; data.hOpacityMask = hOpacityMask; data.hTransform = hTransform; data.hGuidelineSet = hGuidelineSet; data.EdgeMode = (EdgeMode)GetValue(RenderOptions.EdgeModeProperty); data.bitmapScalingMode = (BitmapScalingMode)GetValue(RenderOptions.BitmapScalingModeProperty); data.ClearTypeHint = (ClearTypeHint)GetValue(RenderOptions.ClearTypeHintProperty); channel.BeginCommand( (byte *)&data, sizeof(DUCE.MILCMD_DRAWINGGROUP), (int)(data.ChildrenSize) ); // Copy this collection's elements (or their handles) to reserved data for (int i = 0; i < ChildrenCount; i++) { DUCE.ResourceHandle resource = ((DUCE.IResource)vChildren.Internal_GetItem(i)).GetHandle(channel);; channel.AppendCommandData( (byte *)&resource, sizeof(DUCE.ResourceHandle) ); } channel.EndCommand(); } } }
/// <summary> /// Derived classes implement this function. /// </summary> DUCE.ResourceHandle DUCE.IResource.GetHandle(DUCE.Channel channel) { // Just return null instead of throwing an exception, since some // derived classes like BitmapEffect do their own addref/release. return(DUCE.ResourceHandle.Null); }
//------------------------------------------------------ // // 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; } DrawingGroup target = ((DrawingGroup)d); // If this is both non-null and mutable, we need to unhook the Changed event. DrawingCollection oldCollection = null; DrawingCollection newCollection = null; if ((e.OldValueSource != BaseValueSourceInternal.Default) || e.IsOldValueModified) { oldCollection = (DrawingCollection)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 = (DrawingCollection)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); }
internal DUCE.Channel AllocateSyncChannel() { DUCE.Channel syncChannel; if (_pSyncConnection == IntPtr.Zero) { HRESULT.Check(UnsafeNativeMethods.WgxConnection_Create( true, // true means synchronous transport out _pSyncConnection)); } if (_freeSyncChannels == null) { // // Ensure the free [....] channels queue... // _freeSyncChannels = new Queue<DUCE.Channel>(3); } if (_freeSyncChannels.Count > 0) { // // If there is a free [....] channel in the queue, we're done: // return _freeSyncChannels.Dequeue(); } else { // // Otherwise, create a new channel. We will try to cache it // when the ReleaseSyncChannel call is made. Also ensure the // synchronous service channel and glyph cache. // if (_syncServiceChannel == null) { _syncServiceChannel = new DUCE.Channel( null, false, // not out of band _pSyncConnection, true // synchronous ); } syncChannel = new DUCE.Channel( _syncServiceChannel, false, // not out of band _pSyncConnection, true // synchronous ); return syncChannel; } }