Browse Source

[DRAFT] Send dispose command for CompositionTarget as an OOB batch (#18119)

* Send dispose command for CompositionTarget as an OOB batch

* Make Close_Should_Remove_PointerOver to provide some render interface stub

* why ins't reactive stuff using our headless testing?

* fix?

---------

Co-authored-by: Dan Walmsley <dan@walms.co.uk>
release/11.2.5
Nikita Tsukanov 12 months ago
committed by Julien Lebosquain
parent
commit
c1b1a1c2a9
  1. 20
      src/Avalonia.Base/Media/MediaContext.Compositor.cs
  2. 22
      src/Avalonia.Base/Rendering/Composition/Compositor.cs
  3. 4
      tests/Avalonia.Base.UnitTests/Input/PointerOverTests.cs
  4. 4
      tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs

20
src/Avalonia.Base/Media/MediaContext.Compositor.cs

@ -98,6 +98,13 @@ partial class MediaContext
if (AvaloniaLocator.Current.GetService<IPlatformRenderInterface>() == null)
return;
using var _ = NonPumpingLockHelper.Use();
SyncWaitCompositorBatch(compositor, CommitCompositor(compositor), waitFullRender, catchExceptions);
}
private void SyncWaitCompositorBatch(Compositor compositor, CompositionBatch batch,
bool waitFullRender, bool catchExceptions)
{
using var _ = NonPumpingLockHelper.Use();
if (compositor is
{
@ -105,12 +112,10 @@ partial class MediaContext
Loop.RunsInBackground: true
})
{
var batch = CommitCompositor(compositor);
(waitFullRender ? batch.Rendered : batch.Processed).Wait();
}
else
{
CommitCompositor(compositor);
compositor.Server.Render(catchExceptions);
}
}
@ -132,10 +137,15 @@ partial class MediaContext
/// </summary>
public void SyncDisposeCompositionTarget(CompositionTarget compositionTarget)
{
compositionTarget.Dispose();
using var _ = NonPumpingLockHelper.Use();
// TODO: We are sending a dispose command outside of the normal commit cycle and we might
// want to ask the compositor to skip any actual rendering and return the control ASAP
// Not sure if we should do that for background thread rendering since it might affect the animation
// smoothness of other windows
// TODO: introduce a way to skip any actual rendering for other targets and only do a dispose?
SyncCommit(compositionTarget.Compositor, false, true);
var oobBatch = compositionTarget.Compositor.OobDispose(compositionTarget);
SyncWaitCompositorBatch(compositionTarget.Compositor, oobBatch, false, true);
}
/// <summary>

22
src/Avalonia.Base/Rendering/Composition/Compositor.cs

@ -211,6 +211,28 @@ namespace Avalonia.Rendering.Composition
return commit;
}
}
/// <summary>
/// This method submits a composition with a single dispose command outside the normal
/// commit cycle. This is currently used for disposing CompositionTargets since we need to do that ASAP
/// and without affecting the not yet completed composition batch
/// </summary>
internal CompositionBatch OobDispose(CompositionObject obj)
{
using var _ = NonPumpingLockHelper.Use();
obj.Dispose();
var batch = new CompositionBatch();
using (var writer = new BatchStreamWriter(batch.Changes, _batchMemoryPool, _batchObjectPool))
{
writer.WriteObject(ServerCompositor.RenderThreadDisposeStartMarker);
writer.Write(1);
writer.WriteObject(obj.Server);
}
batch.CommittedAt = Server.Clock.Elapsed;
_server.EnqueueBatch(batch);
return batch;
}
internal void RegisterForSerialization(ICompositorSerializable compositionObject)
{

4
tests/Avalonia.Base.UnitTests/Input/PointerOverTests.cs

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Headless;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Rendering;
@ -22,7 +23,8 @@ namespace Avalonia.Base.UnitTests.Input
{
using var app = UnitTestApplication.Start(new TestServices(
inputManager: new InputManager(),
focusManager: new FocusManager()));
focusManager: new FocusManager(),
renderInterface: new HeadlessPlatformRenderInterface()));
var renderer = new Mock<IHitTester>();
var device = CreatePointerDeviceMock().Object;

4
tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs

@ -153,7 +153,7 @@ namespace Avalonia.ReactiveUI.UnitTests
[Fact]
public void Activation_For_View_Fetcher_Should_Support_Windows()
{
using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var window = new TestWindowWithWhenActivated();
Assert.False(window.Active);
@ -171,7 +171,7 @@ namespace Avalonia.ReactiveUI.UnitTests
[Fact]
public void Activatable_Window_View_Model_Is_Activated_And_Deactivated()
{
using (UnitTestApplication.Start(TestServices.MockWindowingPlatform))
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var viewModel = new ActivatableViewModel();
var window = new ActivatableWindow { ViewModel = viewModel };

Loading…
Cancel
Save