Browse Source

OpenGL synchronization and separation

pull/1977/head
Nikita Tsukanov 7 years ago
parent
commit
e45d55cfb3
  1. 27
      src/Avalonia.Native.OSX/gl.mm
  2. 16
      src/Avalonia.Native.OSX/window.mm
  3. 3
      src/Avalonia.Native/AvaloniaNativePlatform.cs
  4. 45
      src/Avalonia.Native/DeferredRendererProxy.cs
  5. 4
      src/Avalonia.Native/WindowImplBase.cs
  6. 2
      src/headers/avalonia-native.h

27
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
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

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()

45
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();
}
}
}

4
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
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

Loading…
Cancel
Save