diff --git a/build/ApiDiff.props b/build/ApiDiff.props index da59ad4bf2..666417addf 100644 --- a/build/ApiDiff.props +++ b/build/ApiDiff.props @@ -1,6 +1,6 @@  - 0.10.0-rc1 + 0.10.0 $(PackageId) Avalonia diff --git a/build/SharedVersion.props b/build/SharedVersion.props index 9a268a21e7..75bada4bfc 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -3,7 +3,7 @@ Avalonia 0.10.999 - Copyright 2020 © The AvaloniaUI Project + Copyright 2021 © The AvaloniaUI Project https://avaloniaui.net https://github.com/AvaloniaUI/Avalonia/ true diff --git a/readme.md b/readme.md index cfa08149cb..f73bdffaeb 100644 --- a/readme.md +++ b/readme.md @@ -12,8 +12,6 @@ Avalonia is a cross-platform XAML-based UI framework providing a flexible stylin ([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery)) -> **Note:** The UI theme you see in the picture above is still work-in-progress and will be available in the upcoming Avalonia 0.10.0 release. However, you can connect to our nightly build feed and install latest pre-release versions of Avalonia NuGet packages, if you are willing to help out with the development and testing. See [Using nightly build feed](https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed) for more info. - To see the status of some of our features, please see our [Roadmap](https://github.com/AvaloniaUI/Avalonia/issues/2239). You can also see what [breaking changes](https://github.com/AvaloniaUI/Avalonia/issues/3538) we have planned and what our [past breaking changes](https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes) have been. [Awesome Avalonia](https://github.com/AvaloniaCommunity/awesome-avalonia) is community-curated list of awesome Avalonia UI tools, libraries, projects and resources. Go and see what people are building with Avalonia! ## 🚀 Getting Started diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs index 2e6f4a67c3..e0ceb0c8b7 100644 --- a/src/Android/Avalonia.Android/AndroidPlatform.cs +++ b/src/Android/Avalonia.Android/AndroidPlatform.cs @@ -1,11 +1,13 @@ using System; + +using Avalonia.Android; using Avalonia.Android.Platform; using Avalonia.Android.Platform.Input; -using Avalonia.Android.Platform.SkiaPlatform; using Avalonia.Controls; using Avalonia.Controls.Platform; using Avalonia.Input; using Avalonia.Input.Platform; +using Avalonia.OpenGL.Egl; using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.Shared.PlatformSupport; @@ -17,7 +19,8 @@ namespace Avalonia { public static T UseAndroid(this T builder) where T : AppBuilderBase, new() { - builder.UseWindowingSubsystem(() => Android.AndroidPlatform.Initialize(builder.ApplicationType), "Android"); + var options = AvaloniaLocator.Current.GetService() ?? new AndroidPlatformOptions(); + builder.UseWindowingSubsystem(() => AndroidPlatform.Initialize(builder.ApplicationType, options), "Android"); builder.UseSkia(); return builder; } @@ -41,7 +44,7 @@ namespace Avalonia.Android _scalingFactor = global::Android.App.Application.Context.Resources.DisplayMetrics.ScaledDensity; } - public static void Initialize(Type appType) + public static void Initialize(Type appType, AndroidPlatformOptions options) { AvaloniaLocator.CurrentMutable .Bind().ToTransient() @@ -60,6 +63,11 @@ namespace Avalonia.Android SkiaPlatform.Initialize(); ((global::Android.App.Application) global::Android.App.Application.Context.ApplicationContext) .RegisterActivityLifecycleCallbacks(new ActivityTracker()); + + if (options.UseGpu) + { + EglPlatformOpenGlInterface.TryInitialize(); + } } public IWindowImpl CreateWindow() @@ -72,4 +80,9 @@ namespace Avalonia.Android throw new NotSupportedException(); } } + + public sealed class AndroidPlatformOptions + { + public bool UseGpu { get; set; } = true; + } } diff --git a/src/Android/Avalonia.Android/OpenGL/GlPlatformSurface.cs b/src/Android/Avalonia.Android/OpenGL/GlPlatformSurface.cs new file mode 100644 index 0000000000..4f4c03fe77 --- /dev/null +++ b/src/Android/Avalonia.Android/OpenGL/GlPlatformSurface.cs @@ -0,0 +1,32 @@ +using System.Linq; + +using Avalonia.OpenGL.Egl; +using Avalonia.OpenGL.Surfaces; + +namespace Avalonia.Android.OpenGL +{ + internal sealed class GlPlatformSurface : EglGlPlatformSurfaceBase + { + private readonly EglPlatformOpenGlInterface _egl; + private readonly IEglWindowGlPlatformSurfaceInfo _info; + + private GlPlatformSurface(EglPlatformOpenGlInterface egl, IEglWindowGlPlatformSurfaceInfo info) + { + _egl = egl; + _info = info; + } + + public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() => + new GlRenderTarget(_egl, _info, _egl.CreateWindowSurface(_info.Handle)); + + public static GlPlatformSurface TryCreate(IEglWindowGlPlatformSurfaceInfo info) + { + if (EglPlatformOpenGlInterface.TryCreate() is EglPlatformOpenGlInterface egl) + { + return new GlPlatformSurface(egl, info); + } + + return null; + } + } +} diff --git a/src/Android/Avalonia.Android/OpenGL/GlRenderTarget.cs b/src/Android/Avalonia.Android/OpenGL/GlRenderTarget.cs new file mode 100644 index 0000000000..75bbd15e3e --- /dev/null +++ b/src/Android/Avalonia.Android/OpenGL/GlRenderTarget.cs @@ -0,0 +1,23 @@ +using Avalonia.OpenGL.Egl; +using Avalonia.OpenGL.Surfaces; + +namespace Avalonia.Android.OpenGL +{ + internal sealed class GlRenderTarget : EglPlatformSurfaceRenderTargetBase + { + private readonly EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo _info; + private readonly EglSurface _surface; + + public GlRenderTarget( + EglPlatformOpenGlInterface egl, + EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo info, + EglSurface surface) + : base(egl) + { + _info = info; + _surface = surface; + } + + public override IGlPlatformSurfaceRenderingSession BeginDraw() => BeginDraw(_surface, _info); + } +} diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/FramebufferManager.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/FramebufferManager.cs new file mode 100644 index 0000000000..18c4796fae --- /dev/null +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/FramebufferManager.cs @@ -0,0 +1,17 @@ +using Avalonia.Controls.Platform.Surfaces; +using Avalonia.Platform; + +namespace Avalonia.Android.Platform.SkiaPlatform +{ + internal sealed class FramebufferManager : IFramebufferPlatformSurface + { + private readonly TopLevelImpl _topLevel; + + public FramebufferManager(TopLevelImpl topLevel) + { + _topLevel = topLevel; + } + + public ILockedFramebuffer Lock() => new AndroidFramebuffer(_topLevel.InternalView.Holder.Surface); + } +} diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 360e76b2dc..a8c7f7af9b 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -2,7 +2,10 @@ using System; using System.Collections.Generic; using Android.Content; using Android.Graphics; +using Android.Runtime; using Android.Views; + +using Avalonia.Android.OpenGL; using Avalonia.Android.Platform.Input; using Avalonia.Android.Platform.Specific; using Avalonia.Android.Platform.Specific.Helpers; @@ -10,13 +13,18 @@ using Avalonia.Controls; using Avalonia.Controls.Platform.Surfaces; using Avalonia.Input; using Avalonia.Input.Raw; +using Avalonia.OpenGL.Egl; +using Avalonia.OpenGL.Surfaces; using Avalonia.Platform; using Avalonia.Rendering; namespace Avalonia.Android.Platform.SkiaPlatform { - class TopLevelImpl : IAndroidView, ITopLevelImpl, IFramebufferPlatformSurface + class TopLevelImpl : IAndroidView, ITopLevelImpl, EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo { + private readonly IGlPlatformSurface _gl; + private readonly IFramebufferPlatformSurface _framebuffer; + private readonly AndroidKeyboardEventsHelper _keyboardHelper; private readonly AndroidTouchEventsHelper _touchHelper; @@ -29,7 +37,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform _touchHelper = new AndroidTouchEventsHelper(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p)); - Surfaces = new object[] { this }; + _gl = GlPlatformSurface.TryCreate(this); + _framebuffer = new FramebufferManager(this); MaxClientSize = new Size(_view.Resources.DisplayMetrics.WidthPixels, _view.Resources.DisplayMetrics.HeightPixels); @@ -48,7 +57,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform _keyboardHelper.HandleEvents = _handleEvents; } } - + public virtual Point GetAvaloniaPointFromEvent(MotionEvent e) => new Point(e.GetX(), e.GetY()); public IInputRoot InputRoot { get; private set; } @@ -63,7 +72,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform } set { - + } } @@ -83,9 +92,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform public View View => _view; + internal InvalidationAwareSurfaceView InternalView => _view; + public IPlatformHandle Handle => _view; - public IEnumerable Surfaces { get; } + public IEnumerable Surfaces => new object[] { _gl, _framebuffer }; public IRenderer CreateRenderer(IRenderRoot root) { @@ -96,7 +107,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform { _view.Visibility = ViewStates.Invisible; } - + public void Invalidate(Rect rect) { if (_view.Holder?.Surface?.IsValid == true) _view.Invalidate(); @@ -203,7 +214,12 @@ namespace Avalonia.Android.Platform.SkiaPlatform public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => new AcrylicPlatformCompensationLevels(1, 1, 1); - ILockedFramebuffer IFramebufferPlatformSurface.Lock() => new AndroidFramebuffer(_view.Holder.Surface); + IntPtr EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo.Handle => + AndroidFramebuffer.ANativeWindow_fromSurface(JNIEnv.Handle, _view.Holder.Surface.Handle); + + public PixelSize Size => new PixelSize(_view.Holder.SurfaceFrame.Width(), _view.Holder.SurfaceFrame.Height()); + + public double Scaling => RenderScaling; public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { diff --git a/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs b/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs index 752eedb68a..1d655bb691 100644 --- a/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs +++ b/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs @@ -2,6 +2,7 @@ using System; using System.Linq; using Avalonia.Controls.Templates; using Avalonia.Input; +using Avalonia.Media; using Avalonia.Rendering; using Avalonia.Styling; using Avalonia.VisualTree; @@ -17,6 +18,11 @@ namespace Avalonia.Controls.Primitives { public IInputElement? InputPassThroughElement { get; set; } + static LightDismissOverlayLayer() + { + BackgroundProperty.OverrideDefaultValue(Brushes.Transparent); + } + /// /// Returns the light dismiss overlay for a specified visual. /// diff --git a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs index d8d3450c6f..e5e27c169a 100644 --- a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs +++ b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs @@ -74,7 +74,6 @@ namespace Avalonia.Controls.Primitives { rv = new LightDismissOverlayLayer { - Background = Brushes.Transparent, IsVisible = false }; diff --git a/src/Avalonia.Dialogs/AboutAvaloniaDialog.xaml b/src/Avalonia.Dialogs/AboutAvaloniaDialog.xaml index c5e1d43d80..08e8798cd5 100644 --- a/src/Avalonia.Dialogs/AboutAvaloniaDialog.xaml +++ b/src/Avalonia.Dialogs/AboutAvaloniaDialog.xaml @@ -99,7 +99,7 @@ - + diff --git a/src/Avalonia.OpenGL/Egl/EglInterface.cs b/src/Avalonia.OpenGL/Egl/EglInterface.cs index 8055226042..cadd7cc1f2 100644 --- a/src/Avalonia.OpenGL/Egl/EglInterface.cs +++ b/src/Avalonia.OpenGL/Egl/EglInterface.cs @@ -30,8 +30,10 @@ namespace Avalonia.OpenGL.Egl static Func Load() { var os = AvaloniaLocator.Current.GetService().GetRuntimeInfo().OperatingSystem; - if(os == OperatingSystemType.Linux || os == OperatingSystemType.Android) + if(os == OperatingSystemType.Linux) return Load("libEGL.so.1"); + if (os == OperatingSystemType.Android) + return Load("libEGL.so"); throw new PlatformNotSupportedException(); } diff --git a/src/Avalonia.OpenGL/GlInterface.cs b/src/Avalonia.OpenGL/GlInterface.cs index 28b62136da..cae245732f 100644 --- a/src/Avalonia.OpenGL/GlInterface.cs +++ b/src/Avalonia.OpenGL/GlInterface.cs @@ -128,7 +128,7 @@ namespace Avalonia.OpenGL int dstY1, int mask, int filter); - [GlMinVersionEntryPoint("glBlitFramebuffer", 3, 0)] + [GlMinVersionEntryPoint("glBlitFramebuffer", 3, 0), GlOptionalEntryPoint] public GlBlitFramebuffer BlitFramebuffer { get; } public delegate void GlGenRenderbuffers(int count, int[] res); diff --git a/src/Avalonia.Themes.Fluent/Controls/Expander.xaml b/src/Avalonia.Themes.Fluent/Controls/Expander.xaml index ad0fd18ea5..a6371a5be9 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Expander.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Expander.xaml @@ -26,6 +26,9 @@ +