diff --git a/src/Avalonia.Native.OSX/gl.mm b/src/Avalonia.Native.OSX/gl.mm index dbe373b26f..f3e6be5cb3 100644 --- a/src/Avalonia.Native.OSX/gl.mm +++ b/src/Avalonia.Native.OSX/gl.mm @@ -102,17 +102,21 @@ public: class GlFeature : public virtual ComSingleObject { IAvnGlDisplay* _display; - IAvnGlContext *_immediate; + AvnGlContext *_immediate; public: FORWARD_IUNKNOWN() - AvnGlContext* ViewContext; - GlFeature(IAvnGlDisplay* display, IAvnGlContext* immediate, AvnGlContext* viewContext) + NSOpenGLPixelFormat* _format; + GlFeature(IAvnGlDisplay* display, AvnGlContext* immediate, NSOpenGLPixelFormat* format) { _display = display; _immediate = immediate; - ViewContext = viewContext; + _format = format; } + NSOpenGLContext* CreateContext() + { + return [[NSOpenGLContext alloc] initWithFormat:_format shareContext:nil]; + } virtual HRESULT ObtainDisplay(IAvnGlDisplay**retOut) { @@ -146,12 +150,7 @@ GlFeature* CreateGlFeature() NSLog(@"Unable to create NSOpenGLContext"); return NULL; } - NSOpenGLContext* viewContext = [[NSOpenGLContext alloc] initWithFormat: format shareContext: immediateContext]; - if(viewContext == nil) - { - NSLog(@"Unable to create shared NSOpenGLContext"); - return NULL; - } + int stencilBits = 0, sampleCount = 0; auto fmt = CGLGetPixelFormat([immediateContext CGLContextObj]); @@ -159,10 +158,9 @@ GlFeature* CreateGlFeature() CGLDescribePixelFormat(fmt, 0, kCGLPFAStencilSize, &stencilBits); auto offscreen = new AvnGlContext(immediateContext, true); - auto view = new AvnGlContext(viewContext, false); auto display = new AvnGlDisplay(sampleCount, stencilBits); - return new GlFeature(display, offscreen, view); + return new GlFeature(display, offscreen, format); } @@ -218,12 +216,14 @@ class AvnGlRenderTarget : public ComSingleObjectCreateContext(); } virtual HRESULT BeginDrawing(IAvnGlSurfaceRenderingSession** ret) @@ -234,8 +234,7 @@ public: if(![_view lockFocusIfCanDraw]) return E_ABORT; - - auto gl = f->ViewContext->GlContext; + auto gl = _context; [gl setView: _view]; [gl makeCurrentContext]; auto frame = [_view frame]; diff --git a/src/Avalonia.Native.OSX/window.mm b/src/Avalonia.Native.OSX/window.mm index c5f68f3741..9fa2b9affc 100644 --- a/src/Avalonia.Native.OSX/window.mm +++ b/src/Avalonia.Native.OSX/window.mm @@ -225,6 +225,22 @@ public: } } + virtual bool TryLock() + { + @autoreleasepool + { + return [View lockFocusIfCanDraw] == YES; + } + } + + virtual void Unlock() + { + @autoreleasepool + { + [View unlockFocus]; + } + } + virtual HRESULT BeginMoveDrag () { @autoreleasepool diff --git a/src/Avalonia.Native/AvaloniaNativePlatform.cs b/src/Avalonia.Native/AvaloniaNativePlatform.cs index a8e290b551..381697a99b 100644 --- a/src/Avalonia.Native/AvaloniaNativePlatform.cs +++ b/src/Avalonia.Native/AvaloniaNativePlatform.cs @@ -77,9 +77,6 @@ namespace Avalonia.Native .Bind().ToConstant(new DefaultRenderTimer(60)) .Bind().ToConstant(new SystemDialogs(_factory.CreateSystemDialogs())) .Bind().ToConstant(opts); - if (opts.UseGpu) - AvaloniaLocator.CurrentMutable - .Bind().ToConstant(new GlPlatformFeature(_factory.ObtainGlFeature())); } public IWindowImpl CreateWindow() diff --git a/src/Avalonia.Native/DeferredRendererProxy.cs b/src/Avalonia.Native/DeferredRendererProxy.cs index 2abc371b21..126a395f73 100644 --- a/src/Avalonia.Native/DeferredRendererProxy.cs +++ b/src/Avalonia.Native/DeferredRendererProxy.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Avalonia.Native.Interop; using Avalonia.Rendering; using Avalonia.VisualTree; @@ -10,7 +11,18 @@ namespace Avalonia.Native { public class DeferredRendererProxy : IRenderer, IRenderLoopTask, IRenderLoop { - object _lock = new object(); + public DeferredRendererProxy(IRenderRoot root, IAvnWindowBase window) + { + if (window != null) + { + _useLock = true; + window.AddRef(); +_window = new IAvnWindowBase(window.NativePointer); + } + _renderer = new DeferredRenderer(root, this); + _rendererTask = (IRenderLoopTask)_renderer; + } + void IRenderLoop.Add(IRenderLoopTask i) { AvaloniaLocator.Current.GetService().Add(this); @@ -23,12 +35,8 @@ namespace Avalonia.Native private DeferredRenderer _renderer; private IRenderLoopTask _rendererTask; - - public DeferredRendererProxy(IRenderRoot root) - { - _renderer = new DeferredRenderer(root, this); - _rendererTask = (IRenderLoopTask)_renderer; - } + private IAvnWindowBase _window; + private bool _useLock; public bool DrawFps{ get => _renderer.DrawFps; @@ -44,8 +52,12 @@ namespace Avalonia.Native public void AddDirty(IVisual visual) => _renderer.AddDirty(visual); - public void Dispose() => _renderer.Dispose(); - + public void Dispose() + { + _renderer.Dispose(); + _window?.Dispose(); + _window = null; + } public IEnumerable HitTest(Point p, IVisual root, Func filter) { return _renderer.HitTest(p, root, filter); @@ -74,9 +86,22 @@ namespace Avalonia.Native public void Render() { - lock(_lock) + if(_useLock) { _rendererTask.Render(); + return; + } + if (_window == null) + return; + if (!_window.TryLock()) + return; + try + { + _rendererTask.Render(); + } + finally + { + _window.Unlock(); } } } diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 0e90a284d7..995e279b9a 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -247,8 +247,8 @@ namespace Avalonia.Native public IRenderer CreateRenderer(IRenderRoot root) { - if(_deferredRendering) - return new DeferredRendererProxy(root); + if (_deferredRendering) + return new DeferredRendererProxy(root, _gpu ? _native : null); return new ImmediateRenderer(root); } diff --git a/src/headers/avalonia-native.h b/src/headers/avalonia-native.h index 8afd69e422..0c965b7498 100644 --- a/src/headers/avalonia-native.h +++ b/src/headers/avalonia-native.h @@ -196,6 +196,8 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown virtual HRESULT SetCursor(IAvnCursor* cursor) = 0; virtual HRESULT CreateGlRenderTarget(IAvnGlSurfaceRenderTarget** ret) = 0; virtual HRESULT GetSoftwareFramebuffer(AvnFramebuffer*ret) = 0; + virtual bool TryLock() = 0; + virtual void Unlock() = 0; }; AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase