Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix visual snapshot on headless #17565

Merged
merged 4 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Avalonia.Base/Rendering/Composition/Compositor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public async Task<Bitmap> CreateCompositionVisualSnapshot(CompositionVisual visu
throw new InvalidOperationException();
if (visual.Root == null)
throw new InvalidOperationException();
var impl = await InvokeServerJobAsync(() => _server.CreateCompositionVisualSnapshot(visual.Server, scaling), true);
var impl = await InvokeServerJobAsync(() => _server.CreateCompositionVisualSnapshot(visual.Server, scaling, true), true);
return new Bitmap(RefCountable.Create(impl));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ protected override void RenderCore(ServerVisualRenderContext context, LtrbRect c
{
base.RenderCore(context, currentTransformedClip);

foreach (var ch in Children)
if (context.RenderChildren)
{
ch.Render(context, currentTransformedClip);
foreach (var ch in Children)
{
ch.Render(context, currentTransformedClip);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ void RenderRootToContextWithClip(IDrawingContextImpl context, ServerCompositionV

using (var proxy = new CompositorDrawingContextProxy(context))
{
var ctx = new ServerVisualRenderContext(proxy, DirtyRects, false);
var ctx = new ServerVisualRenderContext(proxy, DirtyRects, false, true);
root.Render(ctx, null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public IReadOnlyDictionary<Type, object> RT_GetRenderInterfaceFeatures()
}

public IBitmapImpl CreateCompositionVisualSnapshot(ServerCompositionVisual visual,
double scaling)
double scaling, bool renderChildren)
{
using (RenderInterface.EnsureCurrent())
{
Expand All @@ -69,11 +69,12 @@ public IBitmapImpl CreateCompositionVisualSnapshot(ServerCompositionVisual visua
PostTransform = invertRootTransform * scaleTransform,
Transform = Matrix.Identity
};
var ctx = new ServerVisualRenderContext(proxy, null, true);
var ctx = new ServerVisualRenderContext(proxy, null, true, renderChildren);
visual.Render(ctx, null);
}

if (target is IDrawingContextLayerWithRenderContextAffinityImpl affined)
if (target is IDrawingContextLayerWithRenderContextAffinityImpl affined
&& affined.HasRenderContextAffinity)
return affined.CreateNonAffinedSnapshot();

// We are returning the original target, so prevent it from being disposed
Expand All @@ -87,4 +88,4 @@ public IBitmapImpl CreateCompositionVisualSnapshot(ServerCompositionVisual visua
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ internal class ServerVisualRenderContext
{
public IDirtyRectTracker? DirtyRects { get; }
public bool DetachedRendering { get; }
public bool RenderChildren { get; }
public CompositorDrawingContextProxy Canvas { get; }
private readonly Stack<Matrix>? _transformStack;

public ServerVisualRenderContext(CompositorDrawingContextProxy canvas, IDirtyRectTracker? dirtyRects,
bool detachedRendering)
bool detachedRendering, bool renderChildren)
{
Canvas = canvas;
DirtyRects = dirtyRects;
DetachedRendering = detachedRendering;
RenderChildren = renderChildren;
if (detachedRendering)
{
_transformStack = new();
Expand Down Expand Up @@ -72,4 +74,4 @@ public void Dispose()
}
}

}
}
36 changes: 35 additions & 1 deletion tests/Avalonia.Headless.UnitTests/RenderingTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Rendering.Composition;
using Avalonia.Threading;

namespace Avalonia.Headless.UnitTests;
Expand Down Expand Up @@ -37,7 +39,7 @@ public void Should_Render_Last_Frame_To_Bitmap()

Assert.NotNull(frame);
}

#if NUNIT
[AvaloniaTest, Timeout(10000)]
#elif XUNIT
Expand Down Expand Up @@ -136,4 +138,36 @@ public void Should_Not_Hang_With_Non_Trivial_Layout()
var frame = window.CaptureRenderedFrame();
Assert.NotNull(frame);
}

#if NUNIT
[AvaloniaTest, Timeout(10000)]
#elif XUNIT
[AvaloniaFact(Timeout = 10000)]
#endif
public async Task Should_Render_To_A_Compositor_Snapshot_Capture()
{
var window = new Window
{
Content = new ContentControl
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
Width = 100,
Height = 100,
Background = Brushes.Green
},
SizeToContent = SizeToContent.WidthAndHeight
};

window.Show();

var compositionVisual = ElementComposition.GetElementVisual(window)!;
var snapshot = await compositionVisual.Compositor.CreateCompositionVisualSnapshot(compositionVisual, 1);

Assert.NotNull(snapshot);
// ReSharper disable CompareOfFloatsByEqualityOperator
Assert.True(100 == snapshot.Size.Width);
Assert.True(100 == snapshot.Size.Height);
// ReSharper restore CompareOfFloatsByEqualityOperator
}
}