Browse Source

[MONOMAC] Fixed rendering artifacts on resize with DeferredRenderer

Nikita Tsukanov 8 years ago
parent
commit
0909a613f2

+ 45 - 42
src/OSX/Avalonia.MonoMac/EmulatedFramebuffer.cs

@@ -11,20 +11,29 @@ namespace Avalonia.MonoMac
     {
         private readonly TopLevelImpl.TopLevelView _view;
         private readonly CGSize _logicalSize;
+        private bool _isDeferred;
 
-        public EmulatedFramebuffer(TopLevelImpl.TopLevelView view, CGSize logicalSize, CGSize pixelSize)
+        [DllImport("libc")]
+        static extern void memset(IntPtr p, int c, IntPtr size);
+
+        public EmulatedFramebuffer(TopLevelImpl.TopLevelView view)
         {
             _view = view;
-            _logicalSize = logicalSize;
+
+            _isDeferred = !Dispatcher.UIThread.CheckAccess();
+            _logicalSize = _view.LogicalSize;
+            var pixelSize = _view.PixelSize;
             Width = (int)pixelSize.Width;
             Height = (int)pixelSize.Height;
             RowBytes = Width * 4;
             Dpi = new Vector(96 * pixelSize.Width / _logicalSize.Width, 96 * pixelSize.Height / _logicalSize.Height);
             Format = PixelFormat.Rgba8888;
-            Address = Marshal.AllocHGlobal(Height * RowBytes);
+            var size = Height * RowBytes;
+            Address = Marshal.AllocHGlobal(size);
+            memset(Address, 0, new IntPtr(size));
         }
 
-        class DeferredRenderingHelper : IDisposable
+        class CocoaDrawLock : IDisposable
         {
             private readonly NSView _view;
             public void Dispose()
@@ -32,17 +41,17 @@ namespace Avalonia.MonoMac
                 _view.NonUIUnlockFocus();
             }
 
-            public DeferredRenderingHelper(NSView view)
+            public CocoaDrawLock(NSView view)
             {
                 _view = view;
             }
         }
 
-        DeferredRenderingHelper SetupWindowContext()
+        CocoaDrawLock LockCocoaDrawing()
         {
             if (!_view.NonUILockFocusIfCanDraw())
                 return null;
-            return new DeferredRenderingHelper(_view);
+            return new CocoaDrawLock(_view);
         }
 
         public void Dispose()
@@ -50,51 +59,45 @@ namespace Avalonia.MonoMac
             if (Address == IntPtr.Zero)
                 return;
             var nfo = (int) CGBitmapFlags.ByteOrder32Big | (int) CGImageAlphaInfo.PremultipliedLast;
-
-            DeferredRenderingHelper deferred = null;
-            var isDeferred = !Dispatcher.UIThread.CheckAccess();
-            if (!isDeferred || (deferred = SetupWindowContext()) != null)
+            IDisposable drawLock = LockCocoaDrawing();
+            CGImage image = null;
+            try
             {
-                CGImage image = null;
-                try
+                using (var colorSpace = CGColorSpace.CreateDeviceRGB())
+                using (var bContext = new CGBitmapContext(Address, Width, Height, 8, Width * 4,
+                    colorSpace, (CGImageAlphaInfo)nfo))
+                    image = bContext.ToImage();
+                lock (_view.SyncRoot)
                 {
-                    lock (_view.SyncRoot)
+                    if (!_isDeferred || drawLock != null)
                     {
-                        using (deferred)
-                        using (var colorSpace = CGColorSpace.CreateDeviceRGB())
-                        using (var bContext = new CGBitmapContext(Address, Width, Height, 8, Width * 4,
-                            colorSpace, (CGImageAlphaInfo) nfo))
+                        using (var nscontext = NSGraphicsContext.CurrentContext)
+                        using (var context = nscontext.GraphicsPort)
                         {
-                            if (!isDeferred || deferred != null)
-                            {
-                                using (var nscontext = NSGraphicsContext.CurrentContext)
-                                using (var context = nscontext.GraphicsPort)
-                                {
-                                    image = bContext.ToImage();
-                                    context.SetFillColor(255, 255, 255, 255);
-                                    context.FillRect(new CGRect(default(CGPoint), _view.LogicalSize));
-                                    context.TranslateCTM(0, _view.LogicalSize.Height - _logicalSize.Height);
-                                    context.DrawImage(new CGRect(default(CGPoint), _logicalSize), image);
-                                    context.Flush();
-                                    nscontext.FlushGraphics();
-                                }
-                            }
+                            context.SetFillColor(255, 255, 255, 255);
+                            context.FillRect(new CGRect(default(CGPoint), _view.LogicalSize));
+                            context.TranslateCTM(0, _view.LogicalSize.Height - _logicalSize.Height);
+                            context.DrawImage(new CGRect(default(CGPoint), _logicalSize), image);
+                            context.Flush();
+                            nscontext.FlushGraphics();
                         }
                     }
                 }
-                finally
+            }
+            finally
+            {
+                if (image != null)
                 {
-                    if (image != null)
-                    {
-                        if (deferred == null)
-                            image.Dispose();
-                        else
-                            _view.SetBackBufferImage(new SavedImage(image, _logicalSize));
-                    }
+                    if (!_isDeferred)
+                        image.Dispose();
+                    else
+                        _view.SetBackBufferImage(new SavedImage(image, _logicalSize));
                 }
+                Marshal.FreeHGlobal(Address);
+                Address = IntPtr.Zero;
+                drawLock?.Dispose();
             }
-            Marshal.FreeHGlobal(Address);
-            Address = IntPtr.Zero;
+
 
         }
 

+ 1 - 1
src/OSX/Avalonia.MonoMac/TopLevelImpl.cs

@@ -413,6 +413,6 @@ namespace Avalonia.MonoMac
 
         public void SetInputRoot(IInputRoot inputRoot) => InputRoot = inputRoot;
 
-        public ILockedFramebuffer Lock() => new EmulatedFramebuffer(View, View.LogicalSize, View.PixelSize);
+        public ILockedFramebuffer Lock() => new EmulatedFramebuffer(View);
     }
 }