Skip to content

Commit b8a45df

Browse files
authored
Merge pull request #21353 from ramezgerges/skpicture_collapsing_invalidation_include_self
fix(visual): InvalidateParentChildrenPicture does not invalidate self even when includeSelf is true
2 parents 52a6f3e + ba60ef9 commit b8a45df

File tree

2 files changed

+103
-8
lines changed

2 files changed

+103
-8
lines changed

src/Uno.UI.Composition/Composition/Visual.skia.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Diagnostics;
88
using System.Numerics;
99
using System.Runtime.CompilerServices;
10+
using System.Text;
1011
using Microsoft.CodeAnalysis.PooledObjects;
1112
using SkiaSharp;
1213
using Uno.Disposables;
@@ -212,7 +213,7 @@ internal void InvalidatePaint()
212213

213214
internal void InvalidateParentChildrenPicture(bool includeSelf)
214215
{
215-
var parent = includeSelf ? Parent : this;
216+
var parent = includeSelf ? this : Parent;
216217
while (parent is not null && (parent._flags & VisualFlags.ChildrenSKPictureInvalid) == 0)
217218
{
218219
parent._childrenPicture?.Dispose();
@@ -614,6 +615,30 @@ private unsafe void CreateLocalSession(in PaintingSession parentSession, out Pai
614615
#endif
615616
}
616617

618+
internal void PrintSubtree(StringBuilder sb, int indent = 0)
619+
{
620+
var indentation = new string(' ', indent * 2);
621+
sb.Append(indentation);
622+
sb.Append('[');
623+
sb.Append(Comment);
624+
sb.Append("]: ");
625+
sb.Append("Subtree count: [");
626+
sb.Append(GetSubTreeVisualCount());
627+
sb.Append("], flags: [");
628+
sb.Append(_flags);
629+
sb.Append("], _totalMatrix: [");
630+
sb.Append(_totalMatrix.matrix);
631+
sb.Append(']');
632+
sb.Append("], _framesSinceSubtreeNotChanged: [");
633+
sb.Append(_framesSinceSubtreeNotChanged);
634+
sb.Append(']');
635+
sb.AppendLine();
636+
foreach (var child in GetChildrenInRenderOrder())
637+
{
638+
child.PrintSubtree(sb, indent + 1);
639+
}
640+
}
641+
617642
[Flags]
618643
internal enum VisualFlags : byte
619644
{

src/Uno.UI.RuntimeTests/Tests/Windows_UI_Composition/Given_ContainerVisual.cs

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
1-
using System;
2-
using System.Collections.Generic;
1+
#if __SKIA__
32
using System.Linq;
43
using System.Numerics;
5-
using System.Text;
64
using System.Threading.Tasks;
5+
using Windows.Foundation;
76
using Windows.UI;
8-
using Private.Infrastructure;
9-
using Microsoft.UI.Composition;
7+
using Microsoft.UI.Xaml;
108
using Microsoft.UI.Xaml.Controls;
9+
using Private.Infrastructure;
10+
using Microsoft.UI.Xaml.Controls.Primitives;
1111
using Microsoft.UI.Xaml.Media;
1212
using Microsoft.UI.Xaml.Shapes;
13+
using SamplesApp.UITests;
14+
using SkiaSharp;
15+
using Uno.Disposables;
16+
using Uno.Extensions.Specialized;
1317
using Uno.UI.RuntimeTests.Helpers;
18+
using Uno.WinUI.Graphics2DSK;
19+
using CollectionExtensions = Uno.Extensions.CollectionExtensions;
20+
using RectExtensions = Uno.Extensions.RectExtensions;
1421

1522
namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Composition;
1623

17-
#if __SKIA__
1824
[TestClass]
25+
[RunsOnUIThread]
1926
public class Given_ContainerVisual
2027
{
2128
[TestMethod]
@@ -47,7 +54,6 @@ public void When_Children_Change()
4754
}
4855

4956
[TestMethod]
50-
[RunsOnUIThread]
5157
public async Task When_Child_Removed_TotalMatrix_Updated()
5258
{
5359
var compositor = TestServices.WindowHelper.XamlRoot.Compositor;
@@ -63,5 +69,69 @@ public async Task When_Child_Removed_TotalMatrix_Updated()
6369
parent2.Children.InsertAtTop(child);
6470
Assert.IsFalse(child.TotalMatrix.IsIdentity);
6571
}
72+
73+
[TestMethod]
74+
public async Task When_SKPicture_Collapsing_Optimization()
75+
{
76+
var oldValues =
77+
(FeatureConfiguration.Rendering.EnableVisualSubtreeSkippingOptimization,
78+
FeatureConfiguration.Rendering.VisualSubtreeSkippingOptimizationCleanFramesThreshold,
79+
FeatureConfiguration.Rendering.VisualSubtreeSkippingOptimizationVisualCountThreshold);
80+
using var _ = Disposable.Create(() =>
81+
{
82+
(FeatureConfiguration.Rendering.EnableVisualSubtreeSkippingOptimization,
83+
FeatureConfiguration.Rendering.VisualSubtreeSkippingOptimizationCleanFramesThreshold,
84+
FeatureConfiguration.Rendering.VisualSubtreeSkippingOptimizationVisualCountThreshold) = oldValues;
85+
});
86+
(FeatureConfiguration.Rendering.EnableVisualSubtreeSkippingOptimization,
87+
FeatureConfiguration.Rendering.VisualSubtreeSkippingOptimizationCleanFramesThreshold,
88+
FeatureConfiguration.Rendering.VisualSubtreeSkippingOptimizationVisualCountThreshold) = (true, 50, 100);
89+
var popup = new Popup()
90+
{
91+
Child = new StackPanel().Apply(sp => Enumerable.Range(0, 100).ForEach(i =>
92+
sp.Children.Add(new Rectangle
93+
{
94+
Fill = new SolidColorBrush(Colors.Red),
95+
Width = 100,
96+
Height = 100
97+
})))
98+
};
99+
100+
var skce = new FrameCounterSKCanvasElement() { Width = 100, Height = 100 };
101+
popup.PlacementTarget = skce;
102+
popup.DesiredPlacement = PopupPlacementMode.Bottom;
103+
await UITestHelper.Load(new StackPanel { Children = { skce, popup } });
104+
105+
for (int i = 0; i < 200; i++)
106+
{
107+
popup.IsOpen = !popup.IsOpen;
108+
await UITestHelper.WaitForIdle();
109+
var count = skce.FrameCounter;
110+
await UITestHelper.WaitFor(() => skce.FrameCounter > count);
111+
}
112+
113+
popup.IsOpen = true;
114+
await UITestHelper.WaitForIdle();
115+
var p = (popup.Child as FrameworkElement).GetAbsoluteBoundsRect().GetLocation().Offset(50, 50);
116+
117+
var screenShot1 = await UITestHelper.ScreenShot(((FrameworkElement)TestServices.WindowHelper.XamlRoot.VisualTree.RootElement)!);
118+
ImageAssert.HasColorAt(screenShot1, p, Colors.Red);
119+
120+
popup.IsOpen = false;
121+
await UITestHelper.WaitForIdle();
122+
123+
var screenShot2 = await UITestHelper.ScreenShot(((FrameworkElement)TestServices.WindowHelper.XamlRoot.VisualTree.RootElement)!);
124+
ImageAssert.DoesNotHaveColorAt(screenShot2, p, Colors.Red);
125+
}
126+
127+
private class FrameCounterSKCanvasElement : SKCanvasElement
128+
{
129+
public int FrameCounter { get; private set; }
130+
protected override void RenderOverride(SKCanvas canvas, Size area)
131+
{
132+
FrameCounter++;
133+
Invalidate();
134+
}
135+
}
66136
}
67137
#endif

0 commit comments

Comments
 (0)