Ver código fonte

OpenGL synchronization and separation

Nikita Tsukanov 7 anos atrás
pai
commit
e45d55cfb3

+ 13 - 14
src/Avalonia.Native.OSX/gl.mm

@@ -102,17 +102,21 @@ public:
 class GlFeature : public virtual ComSingleObject<IAvnGlFeature, &IID_IAvnGlFeature>
 {
     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 ComSingleObject<IAvnGlSurfaceRenderTarget, &IID
 {
     NSView* _view;
     NSWindow* _window;
+    NSOpenGLContext* _context;
 public:
     FORWARD_IUNKNOWN()
     AvnGlRenderTarget(NSWindow* window, NSView*view)
     {
         _window = window;
         _view = view;
+        _context = GetFeature()->CreateContext();
     }
     
     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];

+ 16 - 0
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

+ 0 - 3
src/Avalonia.Native/AvaloniaNativePlatform.cs

@@ -77,9 +77,6 @@ namespace Avalonia.Native
                 .Bind<IRenderTimer>().ToConstant(new DefaultRenderTimer(60))
                 .Bind<ISystemDialogImpl>().ToConstant(new SystemDialogs(_factory.CreateSystemDialogs()))
                 .Bind<AvaloniaNativeOptions>().ToConstant(opts);
-            if (opts.UseGpu)
-                AvaloniaLocator.CurrentMutable
-                    .Bind<IWindowingPlatformGlFeature>().ToConstant(new GlPlatformFeature(_factory.ObtainGlFeature()));
         }
 
         public IWindowImpl CreateWindow()

+ 35 - 10
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<IRenderLoop>().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<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> 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();
             }
         }
     }

+ 2 - 2
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);
         }
 

+ 2 - 0
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