/// <summary> /// Disconnects a resource attached to this visual. /// </summary> internal void DisconnectAttachedResource( VisualProxyFlags correspondingFlag, DUCE.IResource attachedResource) { // // Iterate over the channels this visual is being marshaled to // for (int i = 0; i < _proxy.Count; i++) { VisualProxyFlags flags = _proxy.GetFlags(i); if ((flags & correspondingFlag) == 0) { DUCE.Channel channel = _proxy.GetChannel(i); // // Set the flag so that during render we send // update to the compositor. // SetFlags(channel, true, correspondingFlag); if (correspondingFlag == VisualProxyFlags.IsContentDirty) { _proxy.SetFlags(i, false, VisualProxyFlags.IsContentConnected); } attachedResource.ReleaseOnChannel(channel); } } }
internal void ReleaseResource(DUCE.IResource resource, DUCE.Channel channel) { if (resource != null) { resource.ReleaseOnChannel(channel); } }
/// <summary> /// Disconnects a resource attached to this visual. /// </summary> internal void DisconnectAttachedResource( VisualProxyFlags correspondingFlag, DUCE.IResource attachedResource) { // // We need a special case for the content (corresponding // to the IsContentConnected flag). // bool needToReleaseContent = correspondingFlag == VisualProxyFlags.IsContentConnected; // // Iterate over the channels this visual is being marshaled to // for (int i = 0; i < _proxy.Count; i++) { DUCE.Channel channel = _proxy.GetChannel(i); VisualProxyFlags flags = _proxy.GetFlags(i); // // See if the corresponding flag is set... // bool correspondingFlagSet = (flags & correspondingFlag) != 0; // // We want to perform an action if IsContentConnected // flag is set or a Is*Dirty flag is not set: // if (correspondingFlagSet == needToReleaseContent) { // // Set the flag so that during render we send // update to the compositor. // SetFlags(channel, true, correspondingFlag); attachedResource.ReleaseOnChannel(channel); if (needToReleaseContent) { // // Mark the content of this visual as disconnected. // _proxy.SetFlags(i, false, VisualProxyFlags.IsContentConnected); } } } }
/// <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; }