Browse Source

[MONOMAC] Fixed rendering artifacts on resize with DeferredRenderer

pull/1240/head
Nikita Tsukanov 8 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 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;
}

2
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);
}
}
Loading…
Cancel
Save