Browse Source

Remove ancient renderer support with Invalidate/Paint calls, drastically simplify InvalidationAwareSurfaceView

pull/19045/head
Max Katz 8 months ago
parent
commit
78b47a61ae
  1. 98
      src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
  2. 39
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

98
src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs

@ -1,30 +1,28 @@
using System;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Avalonia.Android.Platform.SkiaPlatform;
using Avalonia.Logging;
using Avalonia.Platform;
namespace Avalonia.Android
{
internal abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, INativePlatformHandleSurface
{
bool _invalidateQueued;
private bool _isDisposed;
private bool _isSurfaceValid;
readonly object _lock = new object();
private readonly Handler _handler;
private IntPtr _nativeWindowHandle = IntPtr.Zero;
private PixelSize _size = new(1, 1);
private double _scaling = 1;
internal event EventHandler? SurfaceWindowCreated;
public event EventHandler? SurfaceWindowCreated;
public PixelSize Size => _size;
public double Scaling => _scaling;
IntPtr IPlatformHandle.Handle => _isSurfaceValid && Holder?.Surface?.Handle is { } handle ?
AndroidFramebuffer.ANativeWindow_fromSurface(JNIEnv.Handle, handle) :
default;
IntPtr IPlatformHandle.Handle => _nativeWindowHandle;
string IPlatformHandle.HandleDescriptor => "SurfaceView";
public InvalidationAwareSurfaceView(Context context) : base(context)
protected InvalidationAwareSurfaceView(Context context) : base(context)
{
if (Holder is null)
throw new InvalidOperationException(
@ -32,71 +30,59 @@ namespace Avalonia.Android
Holder.AddCallback(this);
Holder.SetFormat(global::Android.Graphics.Format.Transparent);
_handler = new Handler(context.MainLooper!);
}
public override void Invalidate()
protected override void Dispose(bool disposing)
{
lock (_lock)
{
if (_invalidateQueued)
return;
_handler.Post(() =>
{
if (_isDisposed || Holder?.Surface?.IsValid != true)
return;
try
{
DoDraw();
}
catch (Exception e)
{
Log.WriteLine(LogPriority.Error, "Avalonia", e.ToString());
}
});
}
}
internal new void Dispose()
{
_isDisposed = true;
ReleaseNativeWindowHandle();
base.Dispose(disposing);
}
public void SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
public virtual void SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
{
_isSurfaceValid = true;
Log.Info("AVALONIA", "Surface Changed");
DoDraw();
CacheSurfaceProperties(holder);
Logger.TryGet(LogEventLevel.Verbose, LogArea.AndroidPlatform)?
.Log(this, "InvalidationAwareSurfaceView Changed");
}
public void SurfaceCreated(ISurfaceHolder holder)
{
_isSurfaceValid = true;
Log.Info("AVALONIA", "Surface Created");
CacheSurfaceProperties(holder);
Logger.TryGet(LogEventLevel.Verbose, LogArea.AndroidPlatform)?
.Log(this, "InvalidationAwareSurfaceView Created");
SurfaceWindowCreated?.Invoke(this, EventArgs.Empty);
DoDraw();
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
_isSurfaceValid = false;
Log.Info("AVALONIA", "Surface Destroyed");
ReleaseNativeWindowHandle();
_size = new PixelSize(1, 1);
_scaling = 1;
Logger.TryGet(LogEventLevel.Verbose, LogArea.AndroidPlatform)?
.Log(this, "InvalidationAwareSurfaceView Destroyed");
}
private void CacheSurfaceProperties(ISurfaceHolder holder)
{
ReleaseNativeWindowHandle();
var surface = holder?.Surface;
if (surface?.Handle is { } handle)
_nativeWindowHandle = AndroidFramebuffer.ANativeWindow_fromSurface(JNIEnv.Handle, handle);
else
_nativeWindowHandle = IntPtr.Zero;
var frame = holder?.SurfaceFrame;
_size = frame != null ? new PixelSize(frame.Width(), frame.Height()) : new PixelSize(1, 1);
_scaling = Resources?.DisplayMetrics?.Density ?? 1;
}
protected void DoDraw()
private void ReleaseNativeWindowHandle()
{
lock (_lock)
if (_nativeWindowHandle != IntPtr.Zero)
{
_invalidateQueued = false;
AndroidFramebuffer.ANativeWindow_release(_nativeWindowHandle);
_nativeWindowHandle = IntPtr.Zero;
}
Draw();
}
protected abstract void Draw();
public string HandleDescriptor => "SurfaceView";
public PixelSize Size => new(Holder?.SurfaceFrame?.Width() ?? 1, Holder?.SurfaceFrame?.Height() ?? 1);
public double Scaling => Resources?.DisplayMetrics?.Density ?? 1;
}
}

39
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -124,11 +124,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
InputRoot = inputRoot;
}
void Draw()
{
Paint?.Invoke(new Rect(new Point(0, 0), ClientSize));
}
public virtual void Dispose()
{
_systemNavigationManager.Dispose();
@ -146,10 +141,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform
Resized?.Invoke(size, WindowResizeReason.Layout);
}
class ViewImpl : InvalidationAwareSurfaceView, ISurfaceHolderCallback, IInitEditorInfo
sealed class ViewImpl : InvalidationAwareSurfaceView, IInitEditorInfo
{
private readonly TopLevelImpl _tl;
private Size _oldSize;
private double _oldScaling;
public ViewImpl(Context context, TopLevelImpl tl, bool placeOnTop) : base(context)
{
@ -158,13 +154,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
SetZOrderOnTop(true);
}
public TopLevelImpl TopLevelImpl => _tl;
protected override void Draw()
{
_tl.Draw();
}
protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
{
// Workaround issue #9230 on where screen remains gray after splash screen.
@ -211,17 +200,24 @@ namespace Avalonia.Android.Platform.SkiaPlatform
return res ?? baseResult;
}
void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
public override void SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
{
var newSize = new PixelSize(width, height).ToSize(_tl.RenderScaling);
base.SurfaceChanged(holder, format, width, height);
var newSize = Size.ToSize(Scaling);
var newScaling = Scaling;
if (newSize != _oldSize)
{
_oldSize = newSize;
_tl.OnResized(newSize);
}
base.SurfaceChanged(holder, format, width, height);
// ReSharper disable once CompareOfFloatsByEqualityOperator
if (newScaling != _oldScaling)
{
_oldScaling = newScaling;
_tl.ScalingChanged?.Invoke(newScaling);
}
}
public sealed override bool OnCheckIsTextEditor()
@ -236,11 +232,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform
_initEditorInfo = init;
}
public sealed override IInputConnection OnCreateInputConnection(EditorInfo? outAttrs)
public override IInputConnection OnCreateInputConnection(EditorInfo? outAttrs)
{
return _initEditorInfo?.Invoke(_tl, outAttrs!)!;
}
}
public IPopupImpl? CreatePopup() => null;
@ -280,10 +275,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform
IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => ((IPlatformHandle)_view).Handle;
bool EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfoWithWaitPolicy.SkipWaits => true;
public PixelSize Size => _view.Size;
public double Scaling => RenderScaling;
PixelSize EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Size => _view.Size;
double EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Scaling => _view.Scaling;
public void SetTransparencyLevelHint(IReadOnlyList<WindowTransparencyLevel> transparencyLevels)
{

Loading…
Cancel
Save