|
|
@@ -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;
|
|
|
+
|
|
|
|
|
|
}
|
|
|
|