Browse Source

Merge pull request #12146 from MrJul/fixes/composition-resources-invalidation

Fix composition render resources invalidation
pull/12177/head
Nikita Tsukanov 3 years ago
committed by GitHub
parent
commit
124f124617
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      src/Avalonia.Base/Rendering/Composition/Drawing/ServerCompositionRenderData.cs
  2. 16
      src/Avalonia.Base/Utilities/SmallDictionary.cs
  3. 53
      tests/Avalonia.Base.UnitTests/Utilities/InlineDictionaryTests.cs

21
src/Avalonia.Base/Rendering/Composition/Drawing/ServerCompositionRenderData.cs

@ -42,22 +42,31 @@ class ServerCompositionRenderData : SimpleServerRenderResource
_items.Add(reader.ReadObject<IRenderDataItem>()); _items.Add(reader.ReadObject<IRenderDataItem>());
var collector = s_resourceHashSetPool.Get(); var collector = s_resourceHashSetPool.Get();
foreach(var item in _items) CollectResources(_items, collector);
if (item is IRenderDataItemWithServerResources resourceItem)
resourceItem.Collect(collector);
foreach (var r in collector.Resources) foreach (var r in collector.Resources)
{ {
_referencedResources.Add(r); _referencedResources.Add(r);
r.AddObserver(this); r.AddObserver(this);
} }
collector.Resources.Clear(); collector.Resources.Clear();
s_resourceHashSetPool.ReturnAndSetNull(ref collector); s_resourceHashSetPool.ReturnAndSetNull(ref collector);
base.DeserializeChangesCore(reader, committedAt); base.DeserializeChangesCore(reader, committedAt);
} }
private static void CollectResources(PooledInlineList<IRenderDataItem> items, IRenderDataServerResourcesCollector collector)
{
foreach (var item in items)
{
if (item is IRenderDataItemWithServerResources resourceItem)
resourceItem.Collect(collector);
else if (item is RenderDataPushNode pushNode)
CollectResources(pushNode.Children, collector);
}
}
public Rect? Bounds public Rect? Bounds
{ {
get get
@ -133,4 +142,4 @@ class ServerCompositionRenderData : SimpleServerRenderResource
Reset(); Reset();
base.Dispose(); base.Dispose();
} }
} }

16
src/Avalonia.Base/Utilities/SmallDictionary.cs

@ -51,7 +51,7 @@ internal struct InlineDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey,
throw new ArgumentException("Key already exists in dictionary"); throw new ArgumentException("Key already exists in dictionary");
} }
if (arr[c].Key == null) if (arr[c].Key == null && free == -1)
free = c; free = c;
} }
@ -337,11 +337,15 @@ internal struct InlineDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey,
} }
else if (_type == Type.Array) else if (_type == Type.Array)
{ {
var next = _index + 1; for (var next = _index + 1; next < _arr!.Length; ++next)
if (_arr!.Length - 1 < next || _arr[next].Key == null) {
return false; if (_arr[next].Key != null)
_index = next; {
return true; _index = next;
return true;
}
}
return false;
} }
else if (_type == Type.Dictionary) else if (_type == Type.Dictionary)
return _inner.MoveNext(); return _inner.MoveNext();

53
tests/Avalonia.Base.UnitTests/Utilities/InlineDictionaryTests.cs

@ -0,0 +1,53 @@
#nullable enable
using System.Collections.Generic;
using Avalonia.Utilities;
using Xunit;
namespace Avalonia.Base.UnitTests.Utilities;
public class InlineDictionaryTests
{
[Fact]
public void Enumeration_After_Add_With_Internal_Array_Works()
{
var dic = new InlineDictionary<string, int>();
dic.Add("foo", 1);
dic.Add("bar", 2);
dic.Add("baz", 3);
Assert.Equal(
new[] {
new KeyValuePair<string, int>("foo", 1),
new KeyValuePair<string, int>("bar", 2),
new KeyValuePair<string, int>("baz", 3)
},
dic);
}
[Fact]
public void Enumeration_After_Remove_With_Internal_Array_Works()
{
var dic = new InlineDictionary<string, int>();
dic.Add("foo", 1);
dic.Add("bar", 2);
dic.Add("baz", 3);
Assert.Equal(
new[] {
new KeyValuePair<string, int>("foo", 1),
new KeyValuePair<string, int>("bar", 2),
new KeyValuePair<string, int>("baz", 3)
},
dic);
dic.Remove("bar");
Assert.Equal(
new[] {
new KeyValuePair<string, int>("foo", 1),
new KeyValuePair<string, int>("baz", 3)
},
dic);
}
}
Loading…
Cancel
Save