Parcourir la source

Merge branch 'master' into refactor/pixelsize

danwalmsley il y a 7 ans
Parent
commit
28d73e7e7c

+ 6 - 0
azure-pipelines.yml

@@ -57,10 +57,13 @@ jobs:
     inputs:
       pathToPublish: '$(Build.SourcesDirectory)/Build/Products/Release/'
       artifactName: 'Avalonia.Native.OSX'
+    condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
+
   - task: PublishBuildArtifacts@1
     inputs:
       pathToPublish: '$(Build.SourcesDirectory)/artifacts/bin'
       artifactName: 'BinariesOSX'
+    condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
 
 - job: Windows
   pool:
@@ -79,11 +82,14 @@ jobs:
     inputs:
       pathtoPublish: '$(Build.SourcesDirectory)/artifacts/nuget'
       artifactName: 'NuGet'
+    condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
   - task: PublishBuildArtifacts@1
     inputs:
       pathToPublish: '$(Build.SourcesDirectory)/artifacts/zip'
       artifactName: 'Samples'
+    condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
   - task: PublishBuildArtifacts@1
     inputs:
       pathToPublish: '$(Build.SourcesDirectory)/artifacts/bin'
       artifactName: 'BinariesWindows'
+    condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))

+ 3 - 3
readme.md

@@ -2,9 +2,9 @@
 
 # Avalonia
 
-| Gitter Chat | Build Status | Windows Build Status | Linux/Mac Build Status | Open Collective |
-|---|---|---|---|---|
-|  [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Build Status](https://travis-ci.org/AvaloniaUI/Avalonia.svg?branch=master)](https://travis-ci.org/AvaloniaUI/Avalonia) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) |
+| Gitter Chat | Build Status (Win, Linux, OSX) | Appveyor Build Status | Open Collective |
+|---|---|---|---|
+|  [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) |
 
 ## About
 

+ 0 - 3
src/Avalonia.Base/Platform/IRuntimePlatform.cs

@@ -5,10 +5,7 @@ namespace Avalonia.Platform
 {
     public interface IRuntimePlatform
     {
-        Assembly[] GetLoadedAssemblies();
-        void PostThreadPoolItem(Action cb);
         IDisposable StartSystemTimer(TimeSpan interval, Action tick);
-        string GetStackTrace();
         RuntimePlatformInfo GetRuntimeInfo();
         IUnmanagedBlob AllocBlob(int size);
     }

+ 1 - 1
src/Avalonia.Controls/AppBuilderBase.cs

@@ -222,7 +222,7 @@ namespace Avalonia.Controls
 
         private void SetupAvaloniaModules()
         {
-            var moduleInitializers = from assembly in AvaloniaLocator.Current.GetService<IRuntimePlatform>().GetLoadedAssemblies()
+            var moduleInitializers = from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                      from attribute in assembly.GetCustomAttributes<ExportAvaloniaModuleAttribute>()
                                      where attribute.ForWindowingSubsystem == ""
                                       || attribute.ForWindowingSubsystem == WindowingSubsystemName

+ 2 - 2
src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs

@@ -55,7 +55,7 @@ namespace Avalonia
 
             LoadAssembliesInDirectory();
 
-            var windowingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies()
+            var windowingSubsystemAttribute = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                                from attribute in assembly.GetCustomAttributes<ExportWindowingSubsystemAttribute>()
                                                where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker)
                                                orderby attribute.Priority ascending
@@ -65,7 +65,7 @@ namespace Avalonia
                 throw new InvalidOperationException("No windowing subsystem found. Are you missing assembly references?");
             }
 
-            var renderingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies()
+            var renderingSubsystemAttribute = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                                from attribute in assembly.GetCustomAttributes<ExportRenderingSubsystemAttribute>()
                                                where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker)
                                                where attribute.RequiresWindowingSubsystem == null

+ 1 - 1
src/Avalonia.Native/AvaloniaNativePlatform.cs

@@ -120,7 +120,7 @@ namespace Avalonia.Native
     {
         public AvaloniaNativeMacOptions MacOptions { get; set; }
         public bool UseDeferredRendering { get; set; } = true;
-        public bool UseGpu { get; set; } = false;
+        public bool UseGpu { get; set; } = true;
         internal AvaloniaNativeOptions(IAvaloniaNativeFactory factory)
         {
             var mac = factory.GetMacOptions();

+ 5 - 0
src/Avalonia.Visuals/Platform/IBitmapImpl.cs

@@ -20,6 +20,11 @@ namespace Avalonia.Platform
         /// Gets the size of the bitmap, in device pixels.
         /// </summary>
         PixelSize PixelSize { get; }
+        
+        /// <summary>
+        /// Version of the pixel data
+        /// </summary>
+        int Version { get; }
 
         /// <summary>
         /// Saves the bitmap to a file.

+ 7 - 2
src/Avalonia.Visuals/Rendering/SceneGraph/ImageNode.cs

@@ -30,6 +30,7 @@ namespace Avalonia.Rendering.SceneGraph
             SourceRect = sourceRect;
             DestRect = destRect;
             BitmapInterpolationMode = bitmapInterpolationMode;
+            SourceVersion = Source.Item.Version;
         }        
 
         /// <summary>
@@ -42,6 +43,11 @@ namespace Avalonia.Rendering.SceneGraph
         /// </summary>
         public IRef<IBitmapImpl> Source { get; }
 
+        /// <summary>
+        /// Source bitmap Version
+        /// </summary>
+        public int SourceVersion { get; }
+
         /// <summary>
         /// Gets the draw opacity.
         /// </summary>
@@ -83,6 +89,7 @@ namespace Avalonia.Rendering.SceneGraph
         {
             return transform == Transform &&
                 Equals(source.Item, Source.Item) &&
+                source.Item.Version == SourceVersion &&
                 opacity == Opacity &&
                 sourceRect == SourceRect &&
                 destRect == DestRect &&
@@ -92,8 +99,6 @@ namespace Avalonia.Rendering.SceneGraph
         /// <inheritdoc/>
         public override void Render(IDrawingContextImpl context)
         {
-            // TODO: Probably need to introduce some kind of locking mechanism in the case of
-            // WriteableBitmap.
             context.Transform = Transform;
             context.DrawImage(Source, Opacity, SourceRect, DestRect, BitmapInterpolationMode);
         }

+ 1 - 1
src/Linux/Avalonia.LinuxFramebuffer/Mice.cs

@@ -22,7 +22,7 @@ namespace Avalonia.LinuxFramebuffer
             _height = height;
         }
 
-        public void Start() => AvaloniaLocator.Current.GetService<IRuntimePlatform>().PostThreadPoolItem(Worker);
+        public void Start() => ThreadPool.UnsafeQueueUserWorkItem(_ => Worker(), null);
 
         private void Worker()
         {

+ 1 - 3
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaRuntimeTypeProvider.cs

@@ -91,9 +91,7 @@ namespace Avalonia.Markup.Xaml.Context
 
         private void ScanNewAssemblies()
         {
-            IEnumerable<Assembly> assemblies = AvaloniaLocator.Current
-                .GetService<IRuntimePlatform>()
-                ?.GetLoadedAssemblies();
+            IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies();
 
             if (assemblies != null)
             {

+ 1 - 1
src/Shared/PlatformSupport/AssetLoader.cs

@@ -157,7 +157,7 @@ namespace Avalonia.Shared.PlatformSupport
             AssemblyDescriptor rv;
             if (!AssemblyNameCache.TryGetValue(name, out rv))
             {
-                var loadedAssemblies = AvaloniaLocator.Current.GetService<IRuntimePlatform>().GetLoadedAssemblies();
+                var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
                 var match = loadedAssemblies.FirstOrDefault(a => a.GetName().Name == name);
                 if (match != null)
                 {

+ 0 - 4
src/Shared/PlatformSupport/StandardRuntimePlatform.cs

@@ -13,15 +13,11 @@ namespace Avalonia.Shared.PlatformSupport
 {
     internal partial class StandardRuntimePlatform : IRuntimePlatform
     {
-        public void PostThreadPoolItem(Action cb) => ThreadPool.UnsafeQueueUserWorkItem(_ => cb(), null);
-        public Assembly[] GetLoadedAssemblies() => AppDomain.CurrentDomain.GetAssemblies();
         public IDisposable StartSystemTimer(TimeSpan interval, Action tick)
         {
             return new Timer(_ => tick(), null, interval, interval);
         }
 
-        public string GetStackTrace() => Environment.StackTrace;
-
         public IUnmanagedBlob AllocBlob(int size) => new UnmanagedBlob(this, size);
         
         class UnmanagedBlob : IUnmanagedBlob

+ 2 - 0
src/Skia/Avalonia.Skia/ImmutableBitmap.cs

@@ -64,6 +64,8 @@ namespace Avalonia.Skia
         public Vector Dpi { get; }
         public PixelSize PixelSize { get; }
 
+        public int Version { get; } = 1;
+
         /// <inheritdoc />
         public void Dispose()
         {

+ 4 - 1
src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs

@@ -3,6 +3,7 @@
 
 using System;
 using System.IO;
+using System.Reactive.Disposables;
 using Avalonia.Platform;
 using Avalonia.Rendering;
 using Avalonia.Skia.Helpers;
@@ -78,7 +79,7 @@ namespace Avalonia.Skia
                 GrContext = _grContext
             };
 
-            return new DrawingContextImpl(createInfo);
+            return new DrawingContextImpl(createInfo, Disposable.Create(() => Version++));
         }
 
         /// <inheritdoc />
@@ -87,6 +88,8 @@ namespace Avalonia.Skia
         /// <inheritdoc />
         public PixelSize PixelSize { get; }
 
+        public int Version { get; private set; } = 1;
+
         /// <inheritdoc />
         public void Save(string fileName)
         {

+ 10 - 7
src/Skia/Avalonia.Skia/TypefaceCache.cs

@@ -12,7 +12,7 @@ namespace Avalonia.Skia
     /// </summary>
     internal static class TypefaceCache
     {
-        public static SKTypeface Default = SKTypeface.FromFamilyName(FontFamily.Default.Name);
+        public static SKTypeface Default = CreateDefaultTypeface();
         static readonly Dictionary<string, Dictionary<FontKey, SKTypeface>> Cache = new Dictionary<string, Dictionary<FontKey, SKTypeface>>();
 
         struct FontKey
@@ -49,6 +49,13 @@ namespace Avalonia.Skia
             // Equals and GetHashCode ommitted
         }
 
+        private static SKTypeface CreateDefaultTypeface()
+        {
+            var defaultTypeface = SKTypeface.FromFamilyName(FontFamily.Default.Name) ?? SKTypeface.FromFamilyName(null);
+
+            return defaultTypeface;
+        }
+
         private static SKTypeface GetTypeface(string name, FontKey key)
         {
             var familyKey = name;
@@ -60,12 +67,8 @@ namespace Avalonia.Skia
 
             if (!entry.TryGetValue(key, out var typeface))
             {
-                typeface = SKTypeface.FromFamilyName(familyKey, key.Weight, SKFontStyleWidth.Normal, key.Slant);
-
-                if (typeface.FamilyName != name)
-                {
-                    typeface = Default;
-                }
+                typeface = SKTypeface.FromFamilyName(familyKey, key.Weight, SKFontStyleWidth.Normal, key.Slant)
+                           ?? Default;
 
                 entry[key] = typeface;
             }

+ 16 - 4
src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs

@@ -3,6 +3,7 @@
 
 using System;
 using System.IO;
+using System.Threading;
 using Avalonia.Platform;
 using Avalonia.Skia.Helpers;
 using SkiaSharp;
@@ -16,6 +17,7 @@ namespace Avalonia.Skia
     {
         private static readonly SKBitmapReleaseDelegate s_releaseDelegate = ReleaseProc;
         private readonly SKBitmap _bitmap;
+        private readonly object _lock = new object();
 
         /// <summary>
         /// Create new writeable bitmap.
@@ -54,10 +56,13 @@ namespace Avalonia.Skia
         /// <inheritdoc />
         public PixelSize PixelSize { get; }
 
+        public int Version { get; private set; } = 1;
+
         /// <inheritdoc />
         public void Draw(DrawingContextImpl context, SKRect sourceRect, SKRect destRect, SKPaint paint)
         {
-            context.Canvas.DrawBitmap(_bitmap, sourceRect, destRect, paint);
+            lock (_lock)
+                context.Canvas.DrawBitmap(_bitmap, sourceRect, destRect, paint);
         }
 
         /// <inheritdoc />
@@ -85,7 +90,7 @@ namespace Avalonia.Skia
         }
 
         /// <inheritdoc />
-        public ILockedFramebuffer Lock() => new BitmapFramebuffer(_bitmap);
+        public ILockedFramebuffer Lock() => new BitmapFramebuffer(this, _bitmap);
 
         /// <summary>
         /// Get snapshot as image.
@@ -93,7 +98,8 @@ namespace Avalonia.Skia
         /// <returns>Image snapshot.</returns>
         public SKImage GetSnapshot()
         {
-            return SKImage.FromPixels(_bitmap.Info, _bitmap.GetPixels(), _bitmap.RowBytes);
+            lock (_lock)
+                return SKImage.FromPixels(_bitmap.Info, _bitmap.GetPixels(), _bitmap.RowBytes);
         }
 
         /// <summary>
@@ -111,22 +117,28 @@ namespace Avalonia.Skia
         /// </summary>
         private class BitmapFramebuffer : ILockedFramebuffer
         {
+            private WriteableBitmapImpl _parent;
             private SKBitmap _bitmap;
 
             /// <summary>
             /// Create framebuffer from given bitmap.
             /// </summary>
             /// <param name="bitmap">Bitmap.</param>
-            public BitmapFramebuffer(SKBitmap bitmap)
+            public BitmapFramebuffer(WriteableBitmapImpl parent, SKBitmap bitmap)
             {
+                _parent = parent;
                 _bitmap = bitmap;
+                Monitor.Enter(parent._lock);
             }
 
             /// <inheritdoc />
             public void Dispose()
             {
                 _bitmap.NotifyPixelsChanged();
+                _parent.Version++;
+                Monitor.Exit(_parent._lock);
                 _bitmap = null;
+                _parent = null;
             }
             
             /// <inheritdoc />

+ 1 - 0
src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs

@@ -9,6 +9,7 @@ namespace Avalonia.Direct2D1.Media
     {
         public abstract Vector Dpi { get; }
         public abstract PixelSize PixelSize { get; }
+        public int Version { get; protected set; } = 1;
 
         public abstract OptionalDispose<D2DBitmap> GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target);
 

+ 1 - 1
src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs

@@ -32,7 +32,7 @@ namespace Avalonia.Direct2D1.Media.Imaging
 
         public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
         {
-            return new DrawingContextImpl(visualBrushRenderer, this, _renderTarget);
+            return new DrawingContextImpl(visualBrushRenderer, this, _renderTarget, null, () => Version++);
         }
 
         public IRenderTargetBitmapImpl CreateLayer(Size size)

+ 5 - 1
src/Windows/Avalonia.Direct2D1/Media/Imaging/WicRenderTargetBitmapImpl.cs

@@ -42,7 +42,11 @@ namespace Avalonia.Direct2D1.Media
 
         public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer, Action finishedCallback)
         {
-            return new DrawingContextImpl(visualBrushRenderer, null, _renderTarget, finishedCallback: finishedCallback);
+            return new DrawingContextImpl(visualBrushRenderer, null, _renderTarget, finishedCallback: () =>
+                {
+                    Version++;
+                    finishedCallback?.Invoke();
+                });
         }
     }
 }

+ 6 - 2
src/Windows/Avalonia.Direct2D1/Media/Imaging/WriteableWicBitmapImpl.cs

@@ -17,11 +17,13 @@ namespace Avalonia.Direct2D1.Media.Imaging
 
         class LockedBitmap : ILockedFramebuffer
         {
+            private readonly WriteableWicBitmapImpl _parent;
             private readonly BitmapLock _lock;
             private readonly PixelFormat _format;
 
-            public LockedBitmap(BitmapLock l, PixelFormat format)
+            public LockedBitmap(WriteableWicBitmapImpl parent, BitmapLock l, PixelFormat format)
             {
+                _parent = parent;
                 _lock = l;
                 _format = format;
             }
@@ -30,6 +32,7 @@ namespace Avalonia.Direct2D1.Media.Imaging
             public void Dispose()
             {
                 _lock.Dispose();
+                _parent.Version++;
             }
 
             public IntPtr Address => _lock.Data.DataPointer;
@@ -40,6 +43,7 @@ namespace Avalonia.Direct2D1.Media.Imaging
 
         }
 
-        public ILockedFramebuffer Lock() => new LockedBitmap(WicImpl.Lock(BitmapLockFlags.Write), PixelFormat.Value);
+        public ILockedFramebuffer Lock() =>
+            new LockedBitmap(this, WicImpl.Lock(BitmapLockFlags.Write), PixelFormat.Value);
     }
 }

+ 0 - 3
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@@ -756,9 +756,6 @@ namespace Avalonia.Win32.Interop
         [DllImport("kernel32.dll")]
         public static extern IntPtr GetModuleHandle(string lpModuleName);
 
-        [DllImport("kernel32.dll")]
-        public static extern uint GetCurrentThreadId();
-
         [DllImport("user32.dll")]
         public static extern int GetSystemMetrics(SystemMetric smIndex);
 

+ 3 - 3
src/Windows/Avalonia.Win32/Win32Platform.cs

@@ -42,7 +42,7 @@ namespace Avalonia.Win32
     class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader
     {
         private static readonly Win32Platform s_instance = new Win32Platform();
-        private static uint _uiThread;
+        private static Thread _uiThread;
         private UnmanagedMethods.WndProc _wndProcDelegate;
         private IntPtr _hwnd;
         private readonly List<Delegate> _delegates = new List<Delegate>();
@@ -82,7 +82,7 @@ namespace Avalonia.Win32
                 .Bind<IPlatformIconLoader>().ToConstant(s_instance);
             Win32GlManager.Initialize();
             UseDeferredRendering = deferredRendering;
-            _uiThread = UnmanagedMethods.GetCurrentThreadId();
+            _uiThread = Thread.CurrentThread;
 
             if (OleContext.Current != null)
                 AvaloniaLocator.CurrentMutable.Bind<IPlatformDragSource>().ToSingleton<DragSource>();
@@ -146,7 +146,7 @@ namespace Avalonia.Win32
                 new IntPtr(SignalL));
         }
 
-        public bool CurrentThreadIsLoopThread => _uiThread == UnmanagedMethods.GetCurrentThreadId();
+        public bool CurrentThreadIsLoopThread => _uiThread == Thread.CurrentThread;
 
         public event Action<DispatcherPriority?> Signaled;