Browse Source

Introduced counting of rendered visuals in ServerCompositionVisual and added relevant unit tests in CompositorInvalidationClippingTests. The new tests ensure that visuals that are not in dirty rect are rendered correctly with different ClipToBounds and Clip geometry parameters.

pull/12568/head
stepan_govorko 3 years ago
parent
commit
77dc35bf46
  1. 2
      src/Avalonia.Base/Rendering/Composition/ICompositionTargetDebugEvents.cs
  2. 1
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
  3. 60
      tests/Avalonia.Base.UnitTests/Rendering/CompositorInvalidationClippingTests.cs
  4. 17
      tests/Avalonia.UnitTests/CompositorTestServices.cs

2
src/Avalonia.Base/Rendering/Composition/ICompositionTargetDebugEvents.cs

@ -2,5 +2,7 @@ namespace Avalonia.Rendering.Composition;
internal interface ICompositionTargetDebugEvents internal interface ICompositionTargetDebugEvents
{ {
public int RenderedVisuals { get; }
void IncrementRenderedVisuals();
void RectInvalidated(Rect rc); void RectInvalidated(Rect rc);
} }

1
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs

@ -38,6 +38,7 @@ namespace Avalonia.Rendering.Composition.Server
return; return;
Root!.RenderedVisuals++; Root!.RenderedVisuals++;
Root!.DebugEvents?.IncrementRenderedVisuals();
var boundsRect = new Rect(new Size(Size.X, Size.Y)); var boundsRect = new Rect(new Size(Size.X, Size.Y));

60
tests/Avalonia.Base.UnitTests/Rendering/CompositorInvalidationClippingTests.cs

@ -0,0 +1,60 @@
using Avalonia.Controls;
using Avalonia.Media;
using Xunit;
namespace Avalonia.Base.UnitTests.Rendering;
public class CompositorInvalidationClippingTests : CompositorTestsBase
{
[Fact]
public void Siblings_Should_Be_Rendered_On_Invalidate_Without_ClipToBounds()
{
AssertRenderedVisuals(clipToBounds: false, clipGeometry: false, expectedRenderedVisualsCount: 4);
}
[Fact]
public void Siblings_Should_Not_Be_Rendered_On_Invalidate_With_ClipToBounds()
{
AssertRenderedVisuals(clipToBounds: true, clipGeometry: false, expectedRenderedVisualsCount: 3);
}
[Fact]
public void Siblings_Should_Not_Be_Rendered_On_Invalidate_With_Clip()
{
AssertRenderedVisuals(clipToBounds: false, clipGeometry: true, expectedRenderedVisualsCount: 3);
}
private void AssertRenderedVisuals(bool clipToBounds, bool clipGeometry, int expectedRenderedVisualsCount)
{
using (var s = new CompositorCanvas())
{
//#1 visual to render is root
//#2 visual to render is s.Canvas
//#3 visual to render
s.Canvas.Children.Add(new Border()
{
[Canvas.LeftProperty] = 0, [Canvas.TopProperty] = 0,
Width = 20, Height = 10,
Background = Brushes.Red,
ClipToBounds = clipToBounds,
Clip = clipGeometry ? new RectangleGeometry(new Rect(new Size(20, 10))) : null
});
//#4 visual to render
s.Canvas.Children.Add(new Border()
{
[Canvas.LeftProperty] = 30, [Canvas.TopProperty] = 50,
Width = 20, Height = 10,
Background = Brushes.Red,
ClipToBounds = clipToBounds,
Clip = clipGeometry ? new RectangleGeometry(new Rect(new Size(20, 10))) : null
});
s.RunJobs();
s.Events.Reset();
s.Canvas.Children[0].IsVisible = false;
s.RunJobs();
s.AssertRenderedVisuals(expectedRenderedVisualsCount);
}
}
}

17
tests/Avalonia.UnitTests/CompositorTestServices.cs

@ -89,6 +89,13 @@ public class CompositorTestServices : IDisposable
Events.Rects.Clear(); Events.Rects.Clear();
} }
public void AssertRenderedVisuals(int renderVisuals)
{
RunJobs();
Assert.Equal(Events.RenderedVisuals, renderVisuals);
Events.Rects.Clear();
}
public void AssertHitTest(double x, double y, Func<Visual, bool> filter, params object[] expected) public void AssertHitTest(double x, double y, Func<Visual, bool> filter, params object[] expected)
=> AssertHitTest(new Point(x, y), filter, expected); => AssertHitTest(new Point(x, y), filter, expected);
@ -110,6 +117,13 @@ public class CompositorTestServices : IDisposable
{ {
public List<Rect> Rects = new(); public List<Rect> Rects = new();
public int RenderedVisuals { get; private set; }
public void IncrementRenderedVisuals()
{
RenderedVisuals++;
}
public void RectInvalidated(Rect rc) public void RectInvalidated(Rect rc)
{ {
Rects.Add(rc); Rects.Add(rc);
@ -118,6 +132,7 @@ public class CompositorTestServices : IDisposable
public void Reset() public void Reset()
{ {
Rects.Clear(); Rects.Clear();
RenderedVisuals = 0;
} }
} }
@ -218,4 +233,4 @@ public class DispatcherCompositorScheduler : ICompositorScheduler
{ {
Dispatcher.UIThread.Post(() => compositor.Commit(), DispatcherPriority.UiThreadRender); Dispatcher.UIThread.Post(() => compositor.Commit(), DispatcherPriority.UiThreadRender);
} }
} }

Loading…
Cancel
Save