diff --git a/scripts/ReplaceNugetCache.sh b/scripts/ReplaceNugetCache.sh
index d50f4152e8..4cc11edd60 100755
--- a/scripts/ReplaceNugetCache.sh
+++ b/scripts/ReplaceNugetCache.sh
@@ -4,5 +4,6 @@
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia/$1/lib/netstandard2.0/
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia.gtk3/$1/lib/netstandard2.0/
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia.skia/$1/lib/netstandard2.0/
+ cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp2.0/Avalonia**.dll ~/.nuget/packages/avalonia.native/$1/lib/netstandard2.0/
diff --git a/src/Avalonia.Native/GlPlatformFeature.cs b/src/Avalonia.Native/GlPlatformFeature.cs
index 97785e4a81..e39680bdee 100644
--- a/src/Avalonia.Native/GlPlatformFeature.cs
+++ b/src/Avalonia.Native/GlPlatformFeature.cs
@@ -58,10 +58,8 @@ namespace Avalonia.Native
public IGlDisplay Display { get; }
- public void MakeCurrent(IGlSurface surface)
+ public void MakeCurrent()
{
- if (surface != null)
- throw new ArgumentException(nameof(surface));
Context.MakeCurrent();
}
}
diff --git a/src/Avalonia.OpenGL/EglContext.cs b/src/Avalonia.OpenGL/EglContext.cs
new file mode 100644
index 0000000000..27b1abe411
--- /dev/null
+++ b/src/Avalonia.OpenGL/EglContext.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Reactive.Disposables;
+using System.Threading;
+
+namespace Avalonia.OpenGL
+{
+ public class EglContext : IGlContext
+ {
+ private readonly EglDisplay _disp;
+ private readonly EglInterface _egl;
+ private readonly object _lock = new object();
+
+ public EglContext(EglDisplay display, EglInterface egl, IntPtr ctx, IntPtr offscreenSurface)
+ {
+ _disp = display;
+ _egl = egl;
+ Context = ctx;
+ OffscreenSurface = offscreenSurface;
+ }
+
+ public IntPtr Context { get; }
+ public IntPtr OffscreenSurface { get; }
+ public IGlDisplay Display => _disp;
+
+ public IDisposable Lock()
+ {
+ Monitor.Enter(_lock);
+ return Disposable.Create(() => Monitor.Exit(_lock));
+ }
+
+ public void MakeCurrent()
+ {
+ if (!_egl.MakeCurrent(_disp.Handle, IntPtr.Zero, IntPtr.Zero, Context))
+ throw new OpenGlException("eglMakeCurrent failed");
+ }
+
+ public void MakeCurrent(EglSurface surface)
+ {
+ var surf = ((EglSurface)surface)?.DangerousGetHandle() ?? OffscreenSurface;
+ if (!_egl.MakeCurrent(_disp.Handle, surf, surf, Context))
+ throw new OpenGlException("eglMakeCurrent failed");
+ }
+ }
+}
diff --git a/src/Avalonia.OpenGL/EglDisplay.cs b/src/Avalonia.OpenGL/EglDisplay.cs
index ea0a9bf087..90a70adcb7 100644
--- a/src/Avalonia.OpenGL/EglDisplay.cs
+++ b/src/Avalonia.OpenGL/EglDisplay.cs
@@ -12,7 +12,8 @@ namespace Avalonia.OpenGL
private readonly IntPtr _display;
private readonly IntPtr _config;
private readonly int[] _contextAttributes;
-
+
+ public IntPtr Handle => _display;
public EglDisplay(EglInterface egl)
{
_egl = egl;
@@ -121,7 +122,7 @@ namespace Avalonia.OpenGL
});
if (surf == IntPtr.Zero)
throw new OpenGlException("eglCreatePbufferSurface failed");
- var rv = new EglContext(this, ctx, surf);
+ var rv = new EglContext(this, _egl, ctx, surf);
rv.MakeCurrent(null);
return rv;
}
@@ -132,12 +133,12 @@ namespace Avalonia.OpenGL
throw new OpenGlException("eglMakeCurrent failed");
}
- public IGlSurface CreateWindowSurface(IntPtr window)
+ public EglSurface CreateWindowSurface(IntPtr window)
{
var s = _egl.CreateWindowSurface(_display, _config, window, new[] {EGL_NONE, EGL_NONE});
if (s == IntPtr.Zero)
throw new OpenGlException("eglCreateWindowSurface failed");
- return new EglSurface(this, s);
+ return new EglSurface(this, _egl, s);
}
public int SampleCount
@@ -157,49 +158,5 @@ namespace Avalonia.OpenGL
return rv;
}
}
-
- class EglSurface : SafeHandle, IGlSurface
- {
- private readonly EglDisplay _display;
-
- public EglSurface(EglDisplay display, IntPtr surface) : base(surface, true)
- {
- _display = display;
- }
-
- protected override bool ReleaseHandle()
- {
- _display._egl.DestroySurface(_display._display, handle);
- return true;
- }
-
- public override bool IsInvalid => handle == IntPtr.Zero;
-
- public IGlDisplay Display => _display;
- public void SwapBuffers() => _display._egl.SwapBuffers(_display._display, handle);
- }
-
- class EglContext : IGlContext
- {
- private readonly EglDisplay _disp;
-
- public EglContext(EglDisplay display, IntPtr ctx, IntPtr offscreenSurface)
- {
- _disp = display;
- Context = ctx;
- OffscreenSurface = offscreenSurface;
- }
-
- public IntPtr Context { get; }
- public IntPtr OffscreenSurface { get; }
- public IGlDisplay Display => _disp;
-
- public void MakeCurrent(IGlSurface surface)
- {
- var surf = ((EglSurface)surface)?.DangerousGetHandle() ?? OffscreenSurface;
- if (!_disp._egl.MakeCurrent(_disp._display, surf, surf, Context))
- throw new OpenGlException("eglMakeCurrent failed");
- }
- }
}
}
diff --git a/src/Avalonia.OpenGL/EglGlPlatformFeature.cs b/src/Avalonia.OpenGL/EglGlPlatformFeature.cs
index 535e32924e..86411b89da 100644
--- a/src/Avalonia.OpenGL/EglGlPlatformFeature.cs
+++ b/src/Avalonia.OpenGL/EglGlPlatformFeature.cs
@@ -7,7 +7,7 @@ namespace Avalonia.OpenGL
{
public IGlDisplay Display { get; set; }
public IGlContext ImmediateContext { get; set; }
- public IGlContext DeferredContext { get; set; }
+ public EglContext DeferredContext { get; set; }
public static void TryInitialize()
{
@@ -26,7 +26,7 @@ namespace Avalonia.OpenGL
{
Display = disp,
ImmediateContext = ctx,
- DeferredContext = disp.CreateContext(ctx)
+ DeferredContext = (EglContext)disp.CreateContext(ctx)
};
}
catch(Exception e)
diff --git a/src/Avalonia.OpenGL/EglGlPlatformSurface.cs b/src/Avalonia.OpenGL/EglGlPlatformSurface.cs
index c99c869c4f..f5dd413b0f 100644
--- a/src/Avalonia.OpenGL/EglGlPlatformSurface.cs
+++ b/src/Avalonia.OpenGL/EglGlPlatformSurface.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading;
namespace Avalonia.OpenGL
{
@@ -12,10 +13,10 @@ namespace Avalonia.OpenGL
}
private readonly EglDisplay _display;
- private readonly IGlContext _context;
+ private readonly EglContext _context;
private readonly IEglWindowGlPlatformSurfaceInfo _info;
- public EglGlPlatformSurface(EglDisplay display, IGlContext context, IEglWindowGlPlatformSurfaceInfo info)
+ public EglGlPlatformSurface(EglDisplay display, EglContext context, IEglWindowGlPlatformSurfaceInfo info)
{
_display = display;
_context = context;
@@ -30,11 +31,11 @@ namespace Avalonia.OpenGL
class RenderTarget : IGlPlatformSurfaceRenderTarget
{
- private readonly IGlContext _context;
- private readonly IGlSurface _glSurface;
+ private readonly EglContext _context;
+ private readonly EglSurface _glSurface;
private readonly IEglWindowGlPlatformSurfaceInfo _info;
- public RenderTarget(IGlContext context, IGlSurface glSurface, IEglWindowGlPlatformSurfaceInfo info)
+ public RenderTarget(EglContext context, EglSurface glSurface, IEglWindowGlPlatformSurfaceInfo info)
{
_context = context;
_glSurface = glSurface;
@@ -45,21 +46,33 @@ namespace Avalonia.OpenGL
public IGlPlatformSurfaceRenderingSession BeginDraw()
{
- _context.MakeCurrent(_glSurface);
- return new Session(_context, _glSurface, _info);
+ var l = _context.Lock();
+ try
+ {
+ _context.MakeCurrent(_glSurface);
+ return new Session(_context, _glSurface, _info, l);
+ }
+ catch
+ {
+ l.Dispose();
+ throw;
+ }
}
class Session : IGlPlatformSurfaceRenderingSession
{
private readonly IGlContext _context;
- private readonly IGlSurface _glSurface;
+ private readonly EglSurface _glSurface;
private readonly IEglWindowGlPlatformSurfaceInfo _info;
+ private IDisposable _lock;
- public Session(IGlContext context, IGlSurface glSurface, IEglWindowGlPlatformSurfaceInfo info)
+ public Session(IGlContext context, EglSurface glSurface, IEglWindowGlPlatformSurfaceInfo info,
+ IDisposable @lock)
{
_context = context;
_glSurface = glSurface;
_info = info;
+ _lock = @lock;
}
public void Dispose()
@@ -67,6 +80,7 @@ namespace Avalonia.OpenGL
_context.Display.GlInterface.Flush();
_glSurface.SwapBuffers();
_context.Display.ClearContext();
+ _lock.Dispose();
}
public IGlDisplay Display => _context.Display;
diff --git a/src/Avalonia.OpenGL/EglSurface.cs b/src/Avalonia.OpenGL/EglSurface.cs
new file mode 100644
index 0000000000..90bb1e36d0
--- /dev/null
+++ b/src/Avalonia.OpenGL/EglSurface.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Avalonia.OpenGL
+{
+ public class EglSurface : SafeHandle
+ {
+ private readonly EglDisplay _display;
+ private readonly EglInterface _egl;
+
+ public EglSurface(EglDisplay display, EglInterface egl, IntPtr surface) : base(surface, true)
+ {
+ _display = display;
+ _egl = egl;
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ _egl.DestroySurface(_display.Handle, handle);
+ return true;
+ }
+
+ public override bool IsInvalid => handle == IntPtr.Zero;
+
+ public IGlDisplay Display => _display;
+ public void SwapBuffers() => _egl.SwapBuffers(_display.Handle, handle);
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.OpenGL/IGlContext.cs b/src/Avalonia.OpenGL/IGlContext.cs
index 954567fe2e..04aa1b98e4 100644
--- a/src/Avalonia.OpenGL/IGlContext.cs
+++ b/src/Avalonia.OpenGL/IGlContext.cs
@@ -3,6 +3,6 @@ namespace Avalonia.OpenGL
public interface IGlContext
{
IGlDisplay Display { get; }
- void MakeCurrent(IGlSurface surface);
+ void MakeCurrent();
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.OpenGL/IGlSurface.cs b/src/Avalonia.OpenGL/IGlSurface.cs
deleted file mode 100644
index 499d0a3c90..0000000000
--- a/src/Avalonia.OpenGL/IGlSurface.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System;
-
-namespace Avalonia.OpenGL
-{
- public interface IGlSurface : IDisposable
- {
- IGlDisplay Display { get; }
- void SwapBuffers();
- }
-}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
index 40be0055d3..a268eff78a 100644
--- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
+++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
@@ -144,7 +144,7 @@ namespace Avalonia.Rendering
var t = (IRenderLoopTask)this;
if(t.NeedsUpdate)
UpdateScene();
- t.Render();
+ Render(true);
}
///
@@ -176,12 +176,7 @@ namespace Avalonia.Rendering
void IRenderLoopTask.Update(TimeSpan time) => UpdateScene();
- void IRenderLoopTask.Render()
- {
- using (var l = _lock.TryLock())
- if (l != null)
- Render();
- }
+ void IRenderLoopTask.Render() => Render(false);
///
Size IVisualBrushRenderer.GetRenderTargetSize(IVisualBrush brush)
@@ -202,17 +197,19 @@ namespace Avalonia.Rendering
internal void UnitTestUpdateScene() => UpdateScene();
- internal void UnitTestRender() => Render(_scene.Item);
+ internal void UnitTestRender() => Render(_scene.Item, false);
- private void Render()
+ private void Render(bool forceComposite)
{
- using (var scene = _scene?.Clone())
- {
- Render(scene?.Item);
- }
+ using (var l = _lock.TryLock())
+ if (l != null)
+ using (var scene = _scene?.Clone())
+ {
+ Render(scene?.Item, forceComposite);
+ }
}
- private void Render(Scene scene)
+ private void Render(Scene scene, bool forceComposite)
{
bool renderOverlay = DrawDirtyRects || DrawFps;
bool composite = false;
@@ -256,7 +253,7 @@ namespace Avalonia.Rendering
RenderOverlay(scene, context);
RenderComposite(scene, context);
}
- else if (composite)
+ else if (composite || forceComposite)
{
context = context ?? RenderTarget.CreateDrawingContext(this);
RenderComposite(scene, context);
diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
index dfd277ec86..9b10d74c64 100644
--- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
+++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
@@ -28,7 +28,7 @@ namespace Avalonia.Skia
var iface = display.Type == GlDisplayType.OpenGL2
? GRGlInterface.AssembleGlInterface((_, proc) => display.GlInterface.GetProcAddress(proc))
: GRGlInterface.AssembleGlesInterface((_, proc) => display.GlInterface.GetProcAddress(proc));
- gl.ImmediateContext.MakeCurrent(null);
+ gl.ImmediateContext.MakeCurrent();
GrContext = GRContext.Create(GRBackend.OpenGL, iface);
}
}