Browse Source

[MONOMAC] Fixed rendering artifacts on resize with DeferredRenderer

pull/1240/head
Nikita Tsukanov 9 years ago
parent
commit
0909a613f2
  1. 87
      src/OSX/Avalonia.MonoMac/EmulatedFramebuffer.cs
  2. 2
      src/OSX/Avalonia.MonoMac/TopLevelImpl.cs

87
src/OSX/Avalonia.MonoMac/EmulatedFramebuffer.cs

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

2
src/OSX/Avalonia.MonoMac/TopLevelImpl.cs

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