Browse Source
Wayland-specific handling for platform surface readiness (#21382)
pull/21393/head
Nikita Tsukanov
4 months ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with
31 additions and
1 deletions
-
src/Avalonia.Base/Platform/RenderTargetProperties.cs
-
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
-
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositor.UserApis.cs
-
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositor.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] |
|
|
|
|
|
|
|
@ -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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -83,4 +83,10 @@ internal partial class ServerCompositor |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public void InvalidateAllCompositionTargets() |
|
|
|
{ |
|
|
|
foreach(var target in _activeTargets) |
|
|
|
target.RequestFullRedraw(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -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
|
|
|
|
|