From 72fa47157cc525e7c33bf49ad6334c23d5b1455c Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Wed, 4 Jun 2025 12:52:42 +0500 Subject: [PATCH] [ANDROID] Skip glWaitClient/glWaitGL/glWaitNative (#18974) --- .../Platform/SkiaPlatform/TopLevelImpl.cs | 3 +- .../Egl/EglGlPlatformSurface.cs | 10 ++++++ .../Egl/EglGlPlatformSurfaceBase.cs | 32 +++++++++++++------ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index bd90a91483..26e1fe9ea0 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -30,7 +30,7 @@ using ClipboardManager = Android.Content.ClipboardManager; namespace Avalonia.Android.Platform.SkiaPlatform { - class TopLevelImpl : IAndroidView, ITopLevelImpl, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo + class TopLevelImpl : IAndroidView, ITopLevelImpl, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfoWithWaitPolicy { private readonly IGlPlatformSurface _gl; private readonly IFramebufferPlatformSurface _framebuffer; @@ -302,6 +302,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => new AcrylicPlatformCompensationLevels(1, 1, 1); IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => ((IPlatformHandle)_view).Handle; + bool EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfoWithWaitPolicy.SkipWaits => true; public PixelSize Size => _view.Size; diff --git a/src/Avalonia.OpenGL/Egl/EglGlPlatformSurface.cs b/src/Avalonia.OpenGL/Egl/EglGlPlatformSurface.cs index 59ef25b1a4..d8d48d0944 100644 --- a/src/Avalonia.OpenGL/Egl/EglGlPlatformSurface.cs +++ b/src/Avalonia.OpenGL/Egl/EglGlPlatformSurface.cs @@ -1,4 +1,5 @@ using System; +using Avalonia.Metadata; using Avalonia.OpenGL.Surfaces; namespace Avalonia.OpenGL.Egl @@ -12,6 +13,12 @@ namespace Avalonia.OpenGL.Egl double Scaling { get; } } + [PrivateApi] + public interface IEglWindowGlPlatformSurfaceInfoWithWaitPolicy : IEglWindowGlPlatformSurfaceInfo + { + public bool SkipWaits { get; } + } + private readonly IEglWindowGlPlatformSurfaceInfo _info; public EglGlPlatformSurface(IEglWindowGlPlatformSurfaceInfo info) @@ -40,8 +47,11 @@ namespace Avalonia.OpenGL.Egl _info = info; _currentSize = info.Size; _handle = _info.Handle; + SkipWaits = info is IEglWindowGlPlatformSurfaceInfoWithWaitPolicy { SkipWaits: true }; } + private protected override bool SkipWaits { get; } + public override void Dispose() => _glSurface?.Dispose(); public override IGlPlatformSurfaceRenderingSession BeginDrawCore() diff --git a/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs b/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs index 927e1253fc..6df293e033 100644 --- a/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs +++ b/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs @@ -30,6 +30,8 @@ namespace Avalonia.OpenGL.Egl return BeginDrawCore(); } + private protected virtual bool SkipWaits => false; + public abstract IGlPlatformSurfaceRenderingSession BeginDrawCore(); protected IGlPlatformSurfaceRenderingSession BeginDraw(EglSurface surface, @@ -41,14 +43,17 @@ namespace Avalonia.OpenGL.Egl try { var egli = Context.Display.EglInterface; - egli.WaitClient(); - egli.WaitGL(); - egli.WaitNative(EglConsts.EGL_CORE_NATIVE_ENGINE); - + if (!SkipWaits) + { + egli.WaitClient(); + egli.WaitGL(); + egli.WaitNative(EglConsts.EGL_CORE_NATIVE_ENGINE); + } + Context.GlInterface.BindFramebuffer(GlConsts.GL_FRAMEBUFFER, 0); success = true; - return new Session(Context.Display, Context, surface, size, scaling, restoreContext, onFinish, isYFlipped); + return new Session(Context.Display, Context, surface, size, scaling, restoreContext, onFinish, isYFlipped, SkipWaits); } finally { @@ -64,10 +69,11 @@ namespace Avalonia.OpenGL.Egl private readonly EglDisplay _display; private readonly IDisposable _restoreContext; private readonly Action? _onFinish; + private readonly bool _skipWaits; public Session(EglDisplay display, EglContext context, EglSurface glSurface, PixelSize size, double scaling, - IDisposable restoreContext, Action? onFinish, bool isYFlipped) + IDisposable restoreContext, Action? onFinish, bool isYFlipped, bool skipWaits) { Size = size; Scaling = scaling; @@ -77,16 +83,22 @@ namespace Avalonia.OpenGL.Egl _glSurface = glSurface; _restoreContext = restoreContext; _onFinish = onFinish; + _skipWaits = skipWaits; } public void Dispose() { _context.GlInterface.Flush(); - _display.EglInterface.WaitGL(); + if (!_skipWaits) + _display.EglInterface.WaitGL(); _glSurface.SwapBuffers(); - _display.EglInterface.WaitClient(); - _display.EglInterface.WaitGL(); - _display.EglInterface.WaitNative(EglConsts.EGL_CORE_NATIVE_ENGINE); + if (!_skipWaits) + { + _display.EglInterface.WaitClient(); + _display.EglInterface.WaitGL(); + _display.EglInterface.WaitNative(EglConsts.EGL_CORE_NATIVE_ENGINE); + } + _restoreContext.Dispose(); _onFinish?.Invoke(); }