Browse Source

Wayland-specific handling for platform surface readiness (#21382)

pull/21393/head
Nikita Tsukanov 4 months ago
committed by GitHub
parent
commit
471ead8127
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 13
      src/Avalonia.Base/Platform/RenderTargetProperties.cs
  2. 10
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
  3. 6
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositor.UserApis.cs
  4. 3
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositor.cs

13
src/Avalonia.Base/Platform/RenderTargetProperties.cs

@ -16,6 +16,13 @@ public readonly struct PlatformRenderTargetState
/// </summary>
public bool IsReady { get; init; }
/// <summary>
/// Indicates that the render target is currently not ready but will wake up the render loop
/// when it becomes ready (e.g. waiting for a compositor frame callback).
/// When true, the compositor should not keep polling for readiness.
/// </summary>
public bool WillWakeUpRenderLoopWhenReady { get; init; }
/// <summary>
/// Indicates if the render target is no longer usable and needs to be recreated
/// </summary>
@ -31,6 +38,12 @@ public readonly struct PlatformRenderTargetState
public static PlatformRenderTargetState Corrupted => new() { IsCorrupted = true, IsReady = true};
public static PlatformRenderTargetState Disposed => new() { IsCorrupted = true};
public static PlatformRenderTargetState NotReadyWillWakeupRenderLoop => new PlatformRenderTargetState()
{
WillWakeUpRenderLoopWhenReady = true
};
}
[PrivateApi]

10
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs

@ -44,6 +44,12 @@ namespace Avalonia.Rendering.Composition.Server
/// Returns true if the target is enabled and has pending work but its render target was not ready.
/// </summary>
internal bool IsWaitingForReadyRenderTarget { get; private set; }
/// <summary>
/// Returns true if the target's render target is waiting for a render loop wakeup
/// (i.e. the platform will call Wakeup() when ready, no need to keep polling).
/// </summary>
internal bool IsWaitingForRenderLoopWakeup { get; private set; }
public ServerCompositionTarget(ServerCompositor compositor, Func<IEnumerable<IPlatformRenderSurface>> surfaces)
: base(compositor)
@ -131,6 +137,7 @@ namespace Avalonia.Rendering.Composition.Server
public void Render()
{
IsWaitingForReadyRenderTarget = false;
IsWaitingForRenderLoopWakeup = false;
if (_disposed)
return;
@ -181,6 +188,7 @@ namespace Avalonia.Rendering.Composition.Server
if (!_renderTarget.PlatformRenderTargetState.IsReady)
{
IsWaitingForReadyRenderTarget = IsEnabled;
IsWaitingForRenderLoopWakeup = IsEnabled && _renderTarget.PlatformRenderTargetState.WillWakeUpRenderLoopWhenReady;
return;
}
@ -310,5 +318,7 @@ namespace Avalonia.Rendering.Composition.Server
if (_attachedVisuals.Remove(visual) && IsEnabled)
visual.Deactivate();
}
public void RequestFullRedraw() => _redrawRequested = true;
}
}

6
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositor.UserApis.cs

@ -83,4 +83,10 @@ internal partial class ServerCompositor
}
}
}
public void InvalidateAllCompositionTargets()
{
foreach(var target in _activeTargets)
target.RequestFullRedraw();
}
}

3
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositor.cs

@ -281,8 +281,9 @@ namespace Avalonia.Rendering.Composition.Server
return true;
// Request a tick if we had unready targets in the last tick, to check if they are ready next time
// But skip targets that are waiting for a render loop wakeup from the platform
foreach (var target in _activeTargets)
if (target.IsWaitingForReadyRenderTarget)
if (target.IsWaitingForReadyRenderTarget && !target.IsWaitingForRenderLoopWakeup)
return true;
// Otherwise there is no need to waste CPU cycles, tell the timer to pause

Loading…
Cancel
Save