Browse Source

Refactored GL version and context management

pull/3386/head
Nikita Tsukanov 7 years ago
parent
commit
e2bde7155f
  1. 8
      samples/ControlCatalog.NetCore/Program.cs
  2. 6
      samples/ControlCatalog/Pages/OpenGlPage.xaml.cs
  3. 56
      src/Avalonia.Native/GlPlatformFeature.cs
  4. 3
      src/Avalonia.Native/PopupImpl.cs
  5. 5
      src/Avalonia.Native/WindowImpl.cs
  6. 6
      src/Avalonia.Native/WindowImplBase.cs
  7. 15
      src/Avalonia.OpenGL/EglContext.cs
  8. 45
      src/Avalonia.OpenGL/EglDisplay.cs
  9. 5
      src/Avalonia.OpenGL/EglGlPlatformFeature.cs
  10. 8
      src/Avalonia.OpenGL/EglGlPlatformSurface.cs
  11. 4
      src/Avalonia.OpenGL/EglSurface.cs
  12. 8
      src/Avalonia.OpenGL/GlDisplayType.cs
  13. 22
      src/Avalonia.OpenGL/GlVersion.cs
  14. 5
      src/Avalonia.OpenGL/IGlContext.cs
  15. 10
      src/Avalonia.OpenGL/IGlDisplay.cs
  16. 2
      src/Avalonia.OpenGL/IGlPlatformSurfaceRenderingSession.cs
  17. 2
      src/Avalonia.OpenGL/IWindowingPlatformGlFeature.cs
  18. 18
      src/Avalonia.OpenGL/OpenGlControlBase.cs
  19. 14
      src/Avalonia.X11/Glx/Glx.cs
  20. 2
      src/Avalonia.X11/Glx/GlxConsts.cs
  21. 15
      src/Avalonia.X11/Glx/GlxContext.cs
  22. 99
      src/Avalonia.X11/Glx/GlxDisplay.cs
  23. 4
      src/Avalonia.X11/Glx/GlxGlPlatformSurface.cs
  24. 12
      src/Avalonia.X11/Glx/GlxPlatformFeature.cs
  25. 13
      src/Avalonia.X11/X11Platform.cs
  26. 2
      src/Avalonia.X11/X11Window.cs
  27. 15
      src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
  28. 2
      src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs
  29. 12
      src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs
  30. 3
      src/Windows/Avalonia.Win32/WindowImpl.cs

8
samples/ControlCatalog.NetCore/Program.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
@ -6,6 +7,7 @@ using System.Threading;
using Avalonia; using Avalonia;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
using Avalonia.Dialogs; using Avalonia.Dialogs;
using Avalonia.OpenGL;
namespace ControlCatalog.NetCore namespace ControlCatalog.NetCore
{ {
@ -58,7 +60,11 @@ namespace ControlCatalog.NetCore
.With(new X11PlatformOptions .With(new X11PlatformOptions
{ {
EnableMultiTouch = true, EnableMultiTouch = true,
UseDBusMenu = true UseDBusMenu = true,
GlProfiles = new List<GlVersion>
{
new GlVersion(GlProfileType.OpenGLES, 2, 0)
}
}) })
.With(new Win32PlatformOptions .With(new Win32PlatformOptions
{ {

6
samples/ControlCatalog/Pages/OpenGlPage.xaml.cs

@ -91,12 +91,12 @@ namespace ControlCatalog.Pages
private string GetShader(bool fragment, string shader) private string GetShader(bool fragment, string shader)
{ {
var version = (DisplayType == GlDisplayType.OpenGl ? var version = (GlVersion.Type == GlProfileType.OpenGL ?
RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? 150 : 120 : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? 150 : 120 :
100); 100);
var data = "#version " + version + "\n"; var data = "#version " + version + "\n";
if (DisplayType == GlDisplayType.OpenGLES) if (GlVersion.Type == GlProfileType.OpenGLES)
data += "precision mediump float\n"; data += "precision mediump float;\n";
if (version >= 150) if (version >= 150)
{ {
shader = shader.Replace("attribute", "in"); shader = shader.Replace("attribute", "in");

56
src/Avalonia.Native/GlPlatformFeature.cs

@ -16,21 +16,30 @@ namespace Avalonia.Native
var immediate = display.CreateContext(null); var immediate = display.CreateContext(null);
var deferred = display.CreateContext(immediate); var deferred = display.CreateContext(immediate);
GlDisplay = new GlDisplay(display, immediate.SampleCount, immediate.StencilSize); GlDisplay = new GlDisplay(display, immediate.SampleCount, immediate.StencilSize);
ImmediateContext = new GlContext(GlDisplay, immediate); int major, minor;
DeferredContext = new GlContext(GlDisplay, deferred); using (immediate.MakeCurrent())
{
GlDisplay.GlInterface.GetIntegerv(GlConsts.GL_MAJOR_VERSION, out major);
GlDisplay.GlInterface.GetIntegerv(GlConsts.GL_MINOR_VERSION, out minor);
}
_version = new GlVersion(GlProfileType.OpenGL, major, minor);
ImmediateContext = new GlContext(GlDisplay, immediate, _version);
DeferredContext = new GlContext(GlDisplay, deferred, _version);
} }
public IGlContext ImmediateContext { get; } internal IGlContext ImmediateContext { get; }
public IGlContext MainContext => DeferredContext;
internal GlContext DeferredContext { get; } internal GlContext DeferredContext { get; }
internal GlDisplay GlDisplay; internal GlDisplay GlDisplay;
public IGlDisplay Display => GlDisplay; private readonly GlVersion _version;
public IGlContext CreateContext() => new GlContext(GlDisplay, public IGlContext CreateContext() => new GlContext(GlDisplay,
_display.CreateContext(((GlContext)ImmediateContext).Context)); _display.CreateContext(((GlContext)ImmediateContext).Context), _version);
} }
class GlDisplay : IGlDisplay class GlDisplay
{ {
private readonly IAvnGlDisplay _display; private readonly IAvnGlDisplay _display;
@ -48,8 +57,6 @@ namespace Avalonia.Native
}); });
} }
public GlDisplayType Type => GlDisplayType.OpenGl;
public GlInterface GlInterface { get; } public GlInterface GlInterface { get; }
public int SampleCount { get; } public int SampleCount { get; }
@ -61,16 +68,20 @@ namespace Avalonia.Native
class GlContext : IGlContext class GlContext : IGlContext
{ {
private readonly GlDisplay _display;
public IAvnGlContext Context { get; private set; } public IAvnGlContext Context { get; private set; }
public GlContext(GlDisplay display, IAvnGlContext context) public GlContext(GlDisplay display, IAvnGlContext context, GlVersion version)
{ {
Display = display; _display = display;
Context = context; Context = context;
Version = version;
} }
public IGlDisplay Display { get; } public GlVersion Version { get; }
public GlInterface GlInterface => _display.GlInterface;
public int SampleCount => _display.SampleCount;
public int StencilSize => _display.StencilSize;
public IDisposable MakeCurrent() => Context.MakeCurrent(); public IDisposable MakeCurrent() => Context.MakeCurrent();
public void Dispose() public void Dispose()
@ -84,15 +95,18 @@ namespace Avalonia.Native
class GlPlatformSurfaceRenderTarget : IGlPlatformSurfaceRenderTarget class GlPlatformSurfaceRenderTarget : IGlPlatformSurfaceRenderTarget
{ {
private IAvnGlSurfaceRenderTarget _target; private IAvnGlSurfaceRenderTarget _target;
public GlPlatformSurfaceRenderTarget(IAvnGlSurfaceRenderTarget target) private readonly IGlContext _context;
public GlPlatformSurfaceRenderTarget(IAvnGlSurfaceRenderTarget target, IGlContext context)
{ {
_target = target; _target = target;
_context = context;
} }
public IGlPlatformSurfaceRenderingSession BeginDraw() public IGlPlatformSurfaceRenderingSession BeginDraw()
{ {
var feature = (GlPlatformFeature)AvaloniaLocator.Current.GetService<IWindowingPlatformGlFeature>(); var feature = (GlPlatformFeature)AvaloniaLocator.Current.GetService<IWindowingPlatformGlFeature>();
return new GlPlatformSurfaceRenderingSession(feature.GlDisplay, _target.BeginDrawing()); return new GlPlatformSurfaceRenderingSession(_context, _target.BeginDrawing());
} }
public void Dispose() public void Dispose()
@ -106,13 +120,13 @@ namespace Avalonia.Native
{ {
private IAvnGlSurfaceRenderingSession _session; private IAvnGlSurfaceRenderingSession _session;
public GlPlatformSurfaceRenderingSession(GlDisplay display, IAvnGlSurfaceRenderingSession session) public GlPlatformSurfaceRenderingSession(IGlContext context, IAvnGlSurfaceRenderingSession session)
{ {
Display = display; Context = context;
_session = session; _session = session;
} }
public IGlDisplay Display { get; } public IGlContext Context { get; }
public PixelSize Size public PixelSize Size
{ {
@ -138,14 +152,16 @@ namespace Avalonia.Native
class GlPlatformSurface : IGlPlatformSurface class GlPlatformSurface : IGlPlatformSurface
{ {
private readonly IAvnWindowBase _window; private readonly IAvnWindowBase _window;
private readonly IGlContext _context;
public GlPlatformSurface(IAvnWindowBase window) public GlPlatformSurface(IAvnWindowBase window, IGlContext context)
{ {
_window = window; _window = window;
_context = context;
} }
public IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() public IGlPlatformSurfaceRenderTarget CreateGlRenderTarget()
{ {
return new GlPlatformSurfaceRenderTarget(_window.CreateGlRenderTarget()); return new GlPlatformSurfaceRenderTarget(_window.CreateGlRenderTarget(), _context);
} }
} }

3
src/Avalonia.Native/PopupImpl.cs

@ -24,7 +24,8 @@ namespace Avalonia.Native
_glFeature = glFeature; _glFeature = glFeature;
using (var e = new PopupEvents(this)) using (var e = new PopupEvents(this))
{ {
Init(factory.CreatePopup(e, _opts.UseGpu ? glFeature?.DeferredContext.Context : null), factory.CreateScreens()); var context = _opts.UseGpu ? glFeature?.DeferredContext : null;
Init(factory.CreatePopup(e, context?.Context), factory.CreateScreens(), context);
} }
PopupPositioner = new ManagedPopupPositioner(new OsxManagedPopupPositionerPopupImplHelper(parent, MoveResize)); PopupPositioner = new ManagedPopupPositioner(new OsxManagedPopupPositionerPopupImplHelper(parent, MoveResize));
} }

5
src/Avalonia.Native/WindowImpl.cs

@ -5,6 +5,7 @@ using System;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Platform; using Avalonia.Controls.Platform;
using Avalonia.Native.Interop; using Avalonia.Native.Interop;
using Avalonia.OpenGL;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Platform.Interop; using Avalonia.Platform.Interop;
@ -24,8 +25,8 @@ namespace Avalonia.Native
_glFeature = glFeature; _glFeature = glFeature;
using (var e = new WindowEvents(this)) using (var e = new WindowEvents(this))
{ {
Init(_native = factory.CreateWindow(e, var context = _opts.UseGpu ? glFeature?.DeferredContext : null;
_opts.UseGpu ? glFeature?.DeferredContext.Context : null), factory.CreateScreens()); Init(_native = factory.CreateWindow(e, context?.Context), factory.CreateScreens(), context);
} }
NativeMenuExporter = new AvaloniaNativeMenuExporter(_native, factory); NativeMenuExporter = new AvaloniaNativeMenuExporter(_native, factory);

6
src/Avalonia.Native/WindowImplBase.cs

@ -59,6 +59,7 @@ namespace Avalonia.Native
private Size _lastRenderedLogicalSize; private Size _lastRenderedLogicalSize;
private double _savedScaling; private double _savedScaling;
private GlPlatformSurface _glSurface; private GlPlatformSurface _glSurface;
private IGlContext _glContext;
internal WindowBaseImpl(AvaloniaNativePlatformOptions opts, GlPlatformFeature glFeature) internal WindowBaseImpl(AvaloniaNativePlatformOptions opts, GlPlatformFeature glFeature)
{ {
@ -70,13 +71,14 @@ namespace Avalonia.Native
_cursorFactory = AvaloniaLocator.Current.GetService<IStandardCursorFactory>(); _cursorFactory = AvaloniaLocator.Current.GetService<IStandardCursorFactory>();
} }
protected void Init(IAvnWindowBase window, IAvnScreens screens) protected void Init(IAvnWindowBase window, IAvnScreens screens, IGlContext glContext)
{ {
_native = window; _native = window;
_glContext = glContext;
Handle = new MacOSTopLevelWindowHandle(window); Handle = new MacOSTopLevelWindowHandle(window);
if (_gpu) if (_gpu)
_glSurface = new GlPlatformSurface(window); _glSurface = new GlPlatformSurface(window, _glContext);
Screen = new ScreenImpl(screens); Screen = new ScreenImpl(screens);
_savedLogicalSize = ClientSize; _savedLogicalSize = ClientSize;
_savedScaling = Scaling; _savedScaling = Scaling;

15
src/Avalonia.OpenGL/EglContext.cs

@ -11,17 +11,26 @@ namespace Avalonia.OpenGL
private readonly EglInterface _egl; private readonly EglInterface _egl;
private readonly object _lock = new object(); private readonly object _lock = new object();
public EglContext(EglDisplay display, EglInterface egl, IntPtr ctx, EglSurface offscreenSurface) public EglContext(EglDisplay display, EglInterface egl, IntPtr ctx, EglSurface offscreenSurface,
GlVersion version, int sampleCount, int stencilSize)
{ {
_disp = display; _disp = display;
_egl = egl; _egl = egl;
Context = ctx; Context = ctx;
OffscreenSurface = offscreenSurface; OffscreenSurface = offscreenSurface;
Version = version;
SampleCount = sampleCount;
StencilSize = stencilSize;
GlInterface = GlInterface.FromNativeUtf8GetProcAddress(b => _egl.GetProcAddress(b));
} }
public IntPtr Context { get; } public IntPtr Context { get; }
public EglSurface OffscreenSurface { get; } public EglSurface OffscreenSurface { get; }
public IGlDisplay Display => _disp; public GlVersion Version { get; }
public GlInterface GlInterface { get; }
public int SampleCount { get; }
public int StencilSize { get; }
public EglDisplay Display => _disp;
public IDisposable Lock() public IDisposable Lock()
{ {
@ -52,7 +61,7 @@ namespace Avalonia.OpenGL
} }
} }
public IDisposable MakeCurrent() public IDisposable MakeCurrent()
{ {
var old = new RestoreContext(_egl, _disp.Handle); var old = new RestoreContext(_egl, _disp.Handle);

45
src/Avalonia.OpenGL/EglDisplay.cs

@ -6,7 +6,7 @@ using static Avalonia.OpenGL.EglConsts;
namespace Avalonia.OpenGL namespace Avalonia.OpenGL
{ {
public class EglDisplay : IGlDisplay public class EglDisplay
{ {
private readonly EglInterface _egl; private readonly EglInterface _egl;
private readonly IntPtr _display; private readonly IntPtr _display;
@ -16,6 +16,9 @@ namespace Avalonia.OpenGL
public IntPtr Handle => _display; public IntPtr Handle => _display;
private AngleOptions.PlatformApi? _angleApi; private AngleOptions.PlatformApi? _angleApi;
private int _sampleCount;
private int _stencilSize;
private GlVersion _version;
public EglDisplay(EglInterface egl) : this(egl, -1, IntPtr.Zero, null) public EglDisplay(EglInterface egl) : this(egl, -1, IntPtr.Zero, null)
{ {
@ -76,13 +79,6 @@ namespace Avalonia.OpenGL
foreach (var cfg in new[] foreach (var cfg in new[]
{ {
new
{
Attributes = new[] {EGL_NONE},
Api = EGL_OPENGL_API,
RenderableTypeBit = EGL_OPENGL_BIT,
Type = GlDisplayType.OpenGl
},
new new
{ {
Attributes = new[] Attributes = new[]
@ -92,7 +88,7 @@ namespace Avalonia.OpenGL
}, },
Api = EGL_OPENGL_ES_API, Api = EGL_OPENGL_ES_API,
RenderableTypeBit = EGL_OPENGL_ES2_BIT, RenderableTypeBit = EGL_OPENGL_ES2_BIT,
Type = GlDisplayType.OpenGLES Version = new GlVersion(GlProfileType.OpenGLES, 2, 0)
} }
}) })
{ {
@ -120,7 +116,9 @@ namespace Avalonia.OpenGL
continue; continue;
_contextAttributes = cfg.Attributes; _contextAttributes = cfg.Attributes;
_surfaceType = surfaceType; _surfaceType = surfaceType;
Type = cfg.Type; _version = cfg.Version;
_egl.GetConfigAttrib(_display, _config, EGL_SAMPLES, out _sampleCount);
_egl.GetConfigAttrib(_display, _config, EGL_STENCIL_SIZE, out _stencilSize);
goto Found; goto Found;
} }
@ -128,8 +126,6 @@ namespace Avalonia.OpenGL
Found: Found:
if (_contextAttributes == null) if (_contextAttributes == null)
throw new OpenGlException("No suitable EGL config was found"); throw new OpenGlException("No suitable EGL config was found");
GlInterface = GlInterface.FromNativeUtf8GetProcAddress(b => _egl.GetProcAddress(b));
} }
public EglDisplay() : this(new EglInterface()) public EglDisplay() : this(new EglInterface())
@ -137,8 +133,6 @@ namespace Avalonia.OpenGL
} }
public GlDisplayType Type { get; }
public GlInterface GlInterface { get; }
public EglInterface EglInterface => _egl; public EglInterface EglInterface => _egl;
public EglContext CreateContext(IGlContext share) public EglContext CreateContext(IGlContext share)
{ {
@ -156,7 +150,8 @@ namespace Avalonia.OpenGL
}); });
if (surf == IntPtr.Zero) if (surf == IntPtr.Zero)
throw OpenGlException.GetFormattedException("eglCreatePBufferSurface", _egl); throw OpenGlException.GetFormattedException("eglCreatePBufferSurface", _egl);
var rv = new EglContext(this, _egl, ctx, new EglSurface(this, _egl, surf)); var rv = new EglContext(this, _egl, ctx, new EglSurface(this, _egl, surf),
_version, _sampleCount, _stencilSize);
return rv; return rv;
} }
@ -165,7 +160,7 @@ namespace Avalonia.OpenGL
var ctx = _egl.CreateContext(_display, _config, share?.Context ?? IntPtr.Zero, _contextAttributes); var ctx = _egl.CreateContext(_display, _config, share?.Context ?? IntPtr.Zero, _contextAttributes);
if (ctx == IntPtr.Zero) if (ctx == IntPtr.Zero)
throw OpenGlException.GetFormattedException("eglCreateContext", _egl); throw OpenGlException.GetFormattedException("eglCreateContext", _egl);
var rv = new EglContext(this, _egl, ctx, offscreenSurface); var rv = new EglContext(this, _egl, ctx, offscreenSurface, _version, _sampleCount, _stencilSize);
rv.MakeCurrent(null); rv.MakeCurrent(null);
return rv; return rv;
} }
@ -177,23 +172,5 @@ namespace Avalonia.OpenGL
throw OpenGlException.GetFormattedException("eglCreateWindowSurface", _egl); throw OpenGlException.GetFormattedException("eglCreateWindowSurface", _egl);
return new EglSurface(this, _egl, s); return new EglSurface(this, _egl, s);
} }
public int SampleCount
{
get
{
_egl.GetConfigAttrib(_display, _config, EGL_SAMPLES, out var rv);
return rv;
}
}
public int StencilSize
{
get
{
_egl.GetConfigAttrib(_display, _config, EGL_STENCIL_SIZE, out var rv);
return rv;
}
}
} }
} }

5
src/Avalonia.OpenGL/EglGlPlatformFeature.cs

@ -6,12 +6,13 @@ namespace Avalonia.OpenGL
public class EglGlPlatformFeature : IWindowingPlatformGlFeature public class EglGlPlatformFeature : IWindowingPlatformGlFeature
{ {
private EglDisplay _display; private EglDisplay _display;
public IGlDisplay Display => _display; public EglDisplay Display => _display;
public IGlContext CreateContext() public IGlContext CreateContext()
{ {
return _display.CreateContext(DeferredContext); return _display.CreateContext(DeferredContext);
} }
public EglContext DeferredContext { get; set; } public EglContext DeferredContext { get; private set; }
public IGlContext MainContext => DeferredContext;
public static void TryInitialize() public static void TryInitialize()
{ {

8
src/Avalonia.OpenGL/EglGlPlatformSurface.cs

@ -16,9 +16,9 @@ namespace Avalonia.OpenGL
private readonly EglContext _context; private readonly EglContext _context;
private readonly IEglWindowGlPlatformSurfaceInfo _info; private readonly IEglWindowGlPlatformSurfaceInfo _info;
public EglGlPlatformSurface(EglDisplay display, EglContext context, IEglWindowGlPlatformSurfaceInfo info) public EglGlPlatformSurface(EglContext context, IEglWindowGlPlatformSurfaceInfo info)
{ {
_display = display; _display = context.Display;
_context = context; _context = context;
_info = info; _info = info;
} }
@ -96,7 +96,7 @@ namespace Avalonia.OpenGL
public void Dispose() public void Dispose()
{ {
_context.Display.GlInterface.Flush(); _context.GlInterface.Flush();
_display.EglInterface.WaitGL(); _display.EglInterface.WaitGL();
_glSurface.SwapBuffers(); _glSurface.SwapBuffers();
_display.EglInterface.WaitClient(); _display.EglInterface.WaitClient();
@ -106,7 +106,7 @@ namespace Avalonia.OpenGL
_lock.Dispose(); _lock.Dispose();
} }
public IGlDisplay Display => _context.Display; public IGlContext Context => _context;
public PixelSize Size => _info.Size; public PixelSize Size => _info.Size;
public double Scaling => _info.Scaling; public double Scaling => _info.Scaling;
public bool IsYFlipped { get; } public bool IsYFlipped { get; }

4
src/Avalonia.OpenGL/EglSurface.cs

@ -21,8 +21,6 @@ namespace Avalonia.OpenGL
} }
public override bool IsInvalid => handle == IntPtr.Zero; public override bool IsInvalid => handle == IntPtr.Zero;
public IGlDisplay Display => _display;
public void SwapBuffers() => _egl.SwapBuffers(_display.Handle, handle); public void SwapBuffers() => _egl.SwapBuffers(_display.Handle, handle);
} }
} }

8
src/Avalonia.OpenGL/GlDisplayType.cs

@ -1,8 +0,0 @@
namespace Avalonia.OpenGL
{
public enum GlDisplayType
{
OpenGl,
OpenGLES
}
}

22
src/Avalonia.OpenGL/GlVersion.cs

@ -0,0 +1,22 @@
namespace Avalonia.OpenGL
{
public enum GlProfileType
{
OpenGL,
OpenGLES
}
public struct GlVersion
{
public GlProfileType Type { get; }
public int Major { get; }
public int Minor { get; }
public GlVersion(GlProfileType type, int major, int minor)
{
Type = type;
Major = major;
Minor = minor;
}
}
}

5
src/Avalonia.OpenGL/IGlContext.cs

@ -4,7 +4,10 @@ namespace Avalonia.OpenGL
{ {
public interface IGlContext : IDisposable public interface IGlContext : IDisposable
{ {
IGlDisplay Display { get; } GlVersion Version { get; }
GlInterface GlInterface { get; }
int SampleCount { get; }
int StencilSize { get; }
IDisposable MakeCurrent(); IDisposable MakeCurrent();
} }
} }

10
src/Avalonia.OpenGL/IGlDisplay.cs

@ -1,10 +0,0 @@
namespace Avalonia.OpenGL
{
public interface IGlDisplay
{
GlDisplayType Type { get; }
GlInterface GlInterface { get; }
int SampleCount { get; }
int StencilSize { get; }
}
}

2
src/Avalonia.OpenGL/IGlPlatformSurfaceRenderingSession.cs

@ -4,7 +4,7 @@ namespace Avalonia.OpenGL
{ {
public interface IGlPlatformSurfaceRenderingSession : IDisposable public interface IGlPlatformSurfaceRenderingSession : IDisposable
{ {
IGlDisplay Display { get; } IGlContext Context { get; }
PixelSize Size { get; } PixelSize Size { get; }
double Scaling { get; } double Scaling { get; }
bool IsYFlipped { get; } bool IsYFlipped { get; }

2
src/Avalonia.OpenGL/IWindowingPlatformGlFeature.cs

@ -2,7 +2,7 @@ namespace Avalonia.OpenGL
{ {
public interface IWindowingPlatformGlFeature public interface IWindowingPlatformGlFeature
{ {
IGlDisplay Display { get; }
IGlContext CreateContext(); IGlContext CreateContext();
IGlContext MainContext { get; }
} }
} }

18
src/Avalonia.OpenGL/OpenGlControlBase.cs

@ -16,7 +16,7 @@ namespace Avalonia.OpenGL
private OpenGlTextureBitmap _bitmap; private OpenGlTextureBitmap _bitmap;
private PixelSize _oldSize; private PixelSize _oldSize;
private bool _glFailed; private bool _glFailed;
protected GlDisplayType DisplayType { get; private set; } protected GlVersion GlVersion { get; private set; }
public sealed override void Render(DrawingContext context) public sealed override void Render(DrawingContext context)
{ {
if(!EnsureInitialized()) if(!EnsureInitialized())
@ -26,7 +26,7 @@ namespace Avalonia.OpenGL
{ {
using (_bitmap.Lock()) using (_bitmap.Lock())
{ {
var gl = _context.Display.GlInterface; var gl = _context.GlInterface;
gl.BindFramebuffer(GL_FRAMEBUFFER, _fb); gl.BindFramebuffer(GL_FRAMEBUFFER, _fb);
if (_oldSize != GetPixelSize()) if (_oldSize != GetPixelSize())
ResizeTexture(gl); ResizeTexture(gl);
@ -46,7 +46,7 @@ namespace Avalonia.OpenGL
{ {
using (_context.MakeCurrent()) using (_context.MakeCurrent())
{ {
var gl = _context.Display.GlInterface; var gl = _context.GlInterface;
gl.BindTexture(GL_TEXTURE_2D, 0); gl.BindTexture(GL_TEXTURE_2D, 0);
gl.BindFramebuffer(GL_FRAMEBUFFER, 0); gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
gl.DeleteFramebuffers(1, new[] { _fb }); gl.DeleteFramebuffers(1, new[] { _fb });
@ -59,7 +59,7 @@ namespace Avalonia.OpenGL
try try
{ {
if (callUserDeinit) if (callUserDeinit)
OnOpenGlDeinit(_context.Display.GlInterface, _fb); OnOpenGlDeinit(_context.GlInterface, _fb);
} }
finally finally
{ {
@ -100,7 +100,7 @@ namespace Avalonia.OpenGL
return false; return false;
} }
DisplayType = feature.Display.Type; GlVersion = _context.Version;
try try
{ {
_bitmap = new OpenGlTextureBitmap(); _bitmap = new OpenGlTextureBitmap();
@ -120,7 +120,7 @@ namespace Avalonia.OpenGL
try try
{ {
_oldSize = GetPixelSize(); _oldSize = GetPixelSize();
var gl = _context.Display.GlInterface; var gl = _context.GlInterface;
var oneArr = new int[1]; var oneArr = new int[1];
gl.GenFramebuffers(1, oneArr); gl.GenFramebuffers(1, oneArr);
_fb = oneArr[0]; _fb = oneArr[0];
@ -153,7 +153,7 @@ namespace Avalonia.OpenGL
} }
if (!_glFailed) if (!_glFailed)
OnOpenGlInit(_context.Display.GlInterface, _fb); OnOpenGlInit(_context.GlInterface, _fb);
} }
if (_glFailed) if (_glFailed)
@ -171,7 +171,7 @@ namespace Avalonia.OpenGL
gl.GetIntegerv( GL_TEXTURE_BINDING_2D, out var oldTexture); gl.GetIntegerv( GL_TEXTURE_BINDING_2D, out var oldTexture);
gl.BindTexture(GL_TEXTURE_2D, _texture); gl.BindTexture(GL_TEXTURE_2D, _texture);
gl.TexImage2D(GL_TEXTURE_2D, 0, gl.TexImage2D(GL_TEXTURE_2D, 0,
DisplayType == GlDisplayType.OpenGLES ? GL_RGBA : GL_RGBA8, GlVersion.Type == GlProfileType.OpenGLES ? GL_RGBA : GL_RGBA8,
size.Width, size.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, IntPtr.Zero); size.Width, size.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, IntPtr.Zero);
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -184,7 +184,7 @@ namespace Avalonia.OpenGL
_renderBuffer = oneArr[0]; _renderBuffer = oneArr[0];
gl.BindRenderbuffer(GL_RENDERBUFFER, _renderBuffer); gl.BindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
gl.RenderbufferStorage(GL_RENDERBUFFER, gl.RenderbufferStorage(GL_RENDERBUFFER,
DisplayType == GlDisplayType.OpenGLES ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT, GlVersion.Type == GlProfileType.OpenGLES ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT,
size.Width, size.Height); size.Width, size.Height);
gl.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffer); gl.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffer);
gl.BindRenderbuffer(GL_RENDERBUFFER, oldRenderBuffer); gl.BindRenderbuffer(GL_RENDERBUFFER, oldRenderBuffer);

14
src/Avalonia.X11/Glx/Glx.cs

@ -97,12 +97,16 @@ namespace Avalonia.X11.Glx
[GlEntryPointAttribute("glXWaitGL")] [GlEntryPointAttribute("glXWaitGL")]
public GlxWaitGL WaitGL { get; } public GlxWaitGL WaitGL { get; }
public delegate void GlxWaitGL(); public delegate void GlxWaitGL();
public delegate int GlGetError(); public delegate int GlGetError();
[GlEntryPoint("glGetError")] [GlEntryPoint("glGetError")]
public GlGetError GetError { get; } public GlGetError GetError { get; }
public delegate IntPtr GlxQueryExtensionsString(IntPtr display, int screen);
[GlEntryPoint("glXQueryExtensionsString")]
public GlxQueryExtensionsString QueryExtensionsString { get; }
public GlxInterface() : base(SafeGetProcAddress) public GlxInterface() : base(SafeGetProcAddress)
{ {
} }
@ -122,5 +126,13 @@ namespace Avalonia.X11.Glx
} }
private static readonly Func<string, bool, IntPtr> GlxConverted = ConvertNative(GlxGetProcAddress); private static readonly Func<string, bool, IntPtr> GlxConverted = ConvertNative(GlxGetProcAddress);
public string[] GetExtensions(IntPtr display)
{
var s = Marshal.PtrToStringAnsi(QueryExtensionsString(display, 0));
return s.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Trim()).ToArray();
}
} }
} }

2
src/Avalonia.X11/Glx/GlxConsts.cs

@ -100,6 +100,8 @@ namespace Avalonia.X11.Glx
public const int GLX_CONTEXT_FLAGS_ARB = 0x2094; public const int GLX_CONTEXT_FLAGS_ARB = 0x2094;
public const int GLX_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001; public const int GLX_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001;
public const int GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002; public const int GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002;
public const int GLX_CONTEXT_ES2_PROFILE_BIT_EXT = 0x00000004;
public const int GLX_CONTEXT_PROFILE_MASK_ARB = 0x9126; public const int GLX_CONTEXT_PROFILE_MASK_ARB = 0x9126;
} }

15
src/Avalonia.X11/Glx/GlxContext.cs

@ -13,7 +13,9 @@ namespace Avalonia.X11.Glx
private readonly bool _ownsPBuffer; private readonly bool _ownsPBuffer;
private readonly object _lock = new object(); private readonly object _lock = new object();
public GlxContext(GlxInterface glx, IntPtr handle, GlxDisplay display, X11Info x11, IntPtr defaultXid, public GlxContext(GlxInterface glx, IntPtr handle, GlxDisplay display,
GlVersion version, int sampleCount, int stencilSize,
X11Info x11, IntPtr defaultXid,
bool ownsPBuffer) bool ownsPBuffer)
{ {
Handle = handle; Handle = handle;
@ -22,10 +24,17 @@ namespace Avalonia.X11.Glx
_defaultXid = defaultXid; _defaultXid = defaultXid;
_ownsPBuffer = ownsPBuffer; _ownsPBuffer = ownsPBuffer;
Display = display; Display = display;
Version = version;
SampleCount = sampleCount;
StencilSize = stencilSize;
GlInterface = new GlInterface(GlxInterface.SafeGetProcAddress);
} }
public GlxDisplay Display { get; } public GlxDisplay Display { get; }
IGlDisplay IGlContext.Display => Display; public GlVersion Version { get; }
public GlInterface GlInterface { get; }
public int SampleCount { get; }
public int StencilSize { get; }
public IDisposable Lock() public IDisposable Lock()
{ {
@ -58,7 +67,7 @@ namespace Avalonia.X11.Glx
_glx.MakeContextCurrent(disp, _draw, _read, _context); _glx.MakeContextCurrent(disp, _draw, _read, _context);
} }
} }
public IDisposable MakeCurrent() => MakeCurrent(_defaultXid); public IDisposable MakeCurrent() => MakeCurrent(_defaultXid);
public IDisposable MakeCurrent(IntPtr xid) public IDisposable MakeCurrent(IntPtr xid)

99
src/Avalonia.X11/Glx/GlxDisplay.cs

@ -1,27 +1,28 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Avalonia.OpenGL; using Avalonia.OpenGL;
using static Avalonia.X11.Glx.GlxConsts; using static Avalonia.X11.Glx.GlxConsts;
namespace Avalonia.X11.Glx namespace Avalonia.X11.Glx
{ {
unsafe class GlxDisplay : IGlDisplay unsafe class GlxDisplay
{ {
private readonly X11Info _x11; private readonly X11Info _x11;
private readonly List<GlVersion> _probeProfiles;
private readonly IntPtr _fbconfig; private readonly IntPtr _fbconfig;
private readonly XVisualInfo* _visual; private readonly XVisualInfo* _visual;
public GlDisplayType Type => GlDisplayType.OpenGl; private string[] _displayExtensions;
public GlInterface GlInterface { get; } private GlVersion? _version;
public XVisualInfo* VisualInfo => _visual; public XVisualInfo* VisualInfo => _visual;
public int SampleCount { get; }
public int StencilSize { get; }
public GlxContext DeferredContext { get; } public GlxContext DeferredContext { get; }
public GlxInterface Glx { get; } = new GlxInterface(); public GlxInterface Glx { get; } = new GlxInterface();
public GlxDisplay(X11Info x11) public GlxDisplay(X11Info x11, List<GlVersion> probeProfiles)
{ {
_x11 = x11; _x11 = x11;
_probeProfiles = probeProfiles.ToList();
_displayExtensions = Glx.GetExtensions(_x11.Display);
var baseAttribs = new[] var baseAttribs = new[]
{ {
@ -37,7 +38,8 @@ namespace Avalonia.X11.Glx
GLX_STENCIL_SIZE, 8, GLX_STENCIL_SIZE, 8,
}; };
int sampleCount = 0;
int stencilSize = 0;
foreach (var attribs in new[] foreach (var attribs in new[]
{ {
//baseAttribs.Concat(multiattribs), //baseAttribs.Concat(multiattribs),
@ -70,9 +72,9 @@ namespace Avalonia.X11.Glx
if (_visual == null) if (_visual == null)
throw new OpenGlException("Unable to get visual info from FBConfig"); throw new OpenGlException("Unable to get visual info from FBConfig");
if (Glx.GetFBConfigAttrib(_x11.Display, _fbconfig, GLX_SAMPLES, out var samples) == 0) if (Glx.GetFBConfigAttrib(_x11.Display, _fbconfig, GLX_SAMPLES, out var samples) == 0)
SampleCount = samples; sampleCount = samples;
if (Glx.GetFBConfigAttrib(_x11.Display, _fbconfig, GLX_STENCIL_SIZE, out var stencil) == 0) if (Glx.GetFBConfigAttrib(_x11.Display, _fbconfig, GLX_STENCIL_SIZE, out var stencil) == 0)
StencilSize = stencil; stencilSize = stencil;
var pbuffers = Enumerable.Range(0, 2).Select(_ => Glx.CreatePbuffer(_x11.Display, _fbconfig, new[] var pbuffers = Enumerable.Range(0, 2).Select(_ => Glx.CreatePbuffer(_x11.Display, _fbconfig, new[]
{ {
@ -81,13 +83,14 @@ namespace Avalonia.X11.Glx
XLib.XFlush(_x11.Display); XLib.XFlush(_x11.Display);
DeferredContext = CreateContext(CreatePBuffer(), null, true); DeferredContext = CreateContext(CreatePBuffer(), null,
sampleCount, stencilSize, true);
using (DeferredContext.MakeCurrent()) using (DeferredContext.MakeCurrent())
{ {
GlInterface = new GlInterface(GlxInterface.SafeGetProcAddress); var glInterface = new GlInterface(GlxInterface.SafeGetProcAddress);
if (GlInterface.Version == null) if (glInterface.Version == null)
throw new OpenGlException("GL version string is null, aborting"); throw new OpenGlException("GL version string is null, aborting");
if (GlInterface.Renderer == null) if (glInterface.Renderer == null)
throw new OpenGlException("GL renderer string is null, aborting"); throw new OpenGlException("GL renderer string is null, aborting");
if (Environment.GetEnvironmentVariable("AVALONIA_GLX_IGNORE_RENDERER_BLACKLIST") != "1") if (Environment.GetEnvironmentVariable("AVALONIA_GLX_IGNORE_RENDERER_BLACKLIST") != "1")
@ -96,9 +99,9 @@ namespace Avalonia.X11.Glx
?.GlxRendererBlacklist; ?.GlxRendererBlacklist;
if (blacklist != null) if (blacklist != null)
foreach (var item in blacklist) foreach (var item in blacklist)
if (GlInterface.Renderer.Contains(item)) if (glInterface.Renderer.Contains(item))
throw new OpenGlException( throw new OpenGlException(
$"Renderer '{GlInterface.Renderer}' is blacklisted by '{item}'"); $"Renderer '{glInterface.Renderer}' is blacklisted by '{item}'");
} }
} }
@ -111,40 +114,72 @@ namespace Avalonia.X11.Glx
public GlxContext CreateContext() => CreateContext(DeferredContext); public GlxContext CreateContext() => CreateContext(DeferredContext);
GlxContext CreateContext(IGlContext share) => CreateContext(CreatePBuffer(), share, true);
GlxContext CreateContext(IntPtr defaultXid, IGlContext share, bool ownsPBuffer) GlxContext CreateContext(IGlContext share) => CreateContext(CreatePBuffer(), share,
share.SampleCount, share.StencilSize, true);
GlxContext CreateContext(IntPtr defaultXid, IGlContext share,
int sampleCount, int stencilSize, bool ownsPBuffer)
{ {
var sharelist = ((GlxContext)share)?.Handle ?? IntPtr.Zero; var sharelist = ((GlxContext)share)?.Handle ?? IntPtr.Zero;
IntPtr handle = default; IntPtr handle = default;
foreach (var ver in new[]
{ GlxContext Create(GlVersion profile)
new Version(4, 0), new Version(3, 2),
new Version(3, 0), new Version(2, 0)
})
{ {
var profileMask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
if (profile.Type == GlProfileType.OpenGLES)
profileMask = GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
var attrs = new[] var attrs = new int[]
{ {
GLX_CONTEXT_MAJOR_VERSION_ARB, ver.Major, GLX_CONTEXT_MAJOR_VERSION_ARB, profile.Major,
GLX_CONTEXT_MINOR_VERSION_ARB, ver.Minor, GLX_CONTEXT_MINOR_VERSION_ARB, profile.Minor,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_PROFILE_MASK_ARB, profileMask,
0 0
}; };
try try
{ {
handle = Glx.CreateContextAttribsARB(_x11.Display, _fbconfig, sharelist, true, attrs); handle = Glx.CreateContextAttribsARB(_x11.Display, _fbconfig, sharelist, true, attrs);
if (handle != IntPtr.Zero) if (handle != IntPtr.Zero)
break; {
_version = profile;
return new GlxContext(new GlxInterface(), handle, this, profile,
sampleCount, stencilSize, _x11, defaultXid, ownsPBuffer);
}
} }
catch catch
{ {
break; return null;
} }
return null;
}
GlxContext rv = null;
if (_version.HasValue)
{
rv = Create(_version.Value);
} }
if (handle == IntPtr.Zero) foreach (var v in _probeProfiles)
throw new OpenGlException("Unable to create direct GLX context"); {
return new GlxContext(new GlxInterface(), handle, this, _x11, defaultXid, ownsPBuffer); if (v.Type == GlProfileType.OpenGLES
&& !_displayExtensions.Contains("GLX_EXT_create_context_es2_profile"))
continue;
rv = Create(v);
if (rv != null)
{
_version = v;
break;
}
}
if (rv != null)
return rv;
throw new OpenGlException("Unable to create direct GLX context");
} }
public void SwapBuffers(IntPtr xid) => Glx.SwapBuffers(_x11.Display, xid); public void SwapBuffers(IntPtr xid) => Glx.SwapBuffers(_x11.Display, xid);

4
src/Avalonia.X11/Glx/GlxGlPlatformSurface.cs

@ -59,6 +59,7 @@ namespace Avalonia.X11.Glx
private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info; private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info;
private IDisposable _lock; private IDisposable _lock;
private readonly IDisposable _clearContext; private readonly IDisposable _clearContext;
public IGlContext Context => _context;
public Session(GlxContext context, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info, public Session(GlxContext context, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo info,
IDisposable @lock, IDisposable clearContext) IDisposable @lock, IDisposable clearContext)
@ -71,7 +72,7 @@ namespace Avalonia.X11.Glx
public void Dispose() public void Dispose()
{ {
_context.Display.GlInterface.Flush(); _context.GlInterface.Flush();
_context.Glx.WaitGL(); _context.Glx.WaitGL();
_context.Display.SwapBuffers(_info.Handle); _context.Display.SwapBuffers(_info.Handle);
_context.Glx.WaitX(); _context.Glx.WaitX();
@ -79,7 +80,6 @@ namespace Avalonia.X11.Glx
_lock.Dispose(); _lock.Dispose();
} }
public IGlDisplay Display => _context.Display;
public PixelSize Size => _info.Size; public PixelSize Size => _info.Size;
public double Scaling => _info.Scaling; public double Scaling => _info.Scaling;
public bool IsYFlipped { get; } public bool IsYFlipped { get; }

12
src/Avalonia.X11/Glx/GlxPlatformFeature.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using Avalonia.Logging; using Avalonia.Logging;
using Avalonia.OpenGL; using Avalonia.OpenGL;
@ -8,13 +9,12 @@ namespace Avalonia.X11.Glx
{ {
public GlxDisplay Display { get; private set; } public GlxDisplay Display { get; private set; }
public IGlContext CreateContext() => Display.CreateContext(); public IGlContext CreateContext() => Display.CreateContext();
IGlDisplay IWindowingPlatformGlFeature.Display => Display;
public GlxContext DeferredContext { get; private set; } public GlxContext DeferredContext { get; private set; }
public IGlContext MainContext => DeferredContext;
public static bool TryInitialize(X11Info x11) public static bool TryInitialize(X11Info x11, List<GlVersion> glProfiles)
{ {
var feature = TryCreate(x11); var feature = TryCreate(x11, glProfiles);
if (feature != null) if (feature != null)
{ {
AvaloniaLocator.CurrentMutable.Bind<IWindowingPlatformGlFeature>().ToConstant(feature); AvaloniaLocator.CurrentMutable.Bind<IWindowingPlatformGlFeature>().ToConstant(feature);
@ -24,11 +24,11 @@ namespace Avalonia.X11.Glx
return false; return false;
} }
public static GlxGlPlatformFeature TryCreate(X11Info x11) public static GlxGlPlatformFeature TryCreate(X11Info x11, List<GlVersion> glProfiles)
{ {
try try
{ {
var disp = new GlxDisplay(x11); var disp = new GlxDisplay(x11, glProfiles);
return new GlxGlPlatformFeature return new GlxGlPlatformFeature
{ {
Display = disp, Display = disp,

13
src/Avalonia.X11/X11Platform.cs

@ -67,7 +67,7 @@ namespace Avalonia.X11
if (options.UseEGL) if (options.UseEGL)
EglGlPlatformFeature.TryInitialize(); EglGlPlatformFeature.TryInitialize();
else else
GlxGlPlatformFeature.TryInitialize(Info); GlxGlPlatformFeature.TryInitialize(Info, Options.GlProfiles);
} }
@ -97,6 +97,17 @@ namespace Avalonia
public bool OverlayPopups { get; set; } public bool OverlayPopups { get; set; }
public bool UseDBusMenu { get; set; } public bool UseDBusMenu { get; set; }
public List<GlVersion> GlProfiles { get; set; } = new List<GlVersion>
{
new GlVersion(GlProfileType.OpenGL, 4, 0),
new GlVersion(GlProfileType.OpenGL, 3, 2),
new GlVersion(GlProfileType.OpenGL, 3, 0),
new GlVersion(GlProfileType.OpenGLES, 3, 2),
new GlVersion(GlProfileType.OpenGLES, 3, 0),
new GlVersion(GlProfileType.OpenGLES, 2, 0),
new GlVersion(GlProfileType.OpenGL, 2, 0)
};
public List<string> GlxRendererBlacklist { get; set; } = new List<string> public List<string> GlxRendererBlacklist { get; set; } = new List<string>
{ {
// llvmpipe is a software GL rasterizer. If it's returned by glGetString, // llvmpipe is a software GL rasterizer. If it's returned by glGetString,

2
src/Avalonia.X11/X11Window.cs

@ -165,7 +165,7 @@ namespace Avalonia.X11
if (egl != null) if (egl != null)
surfaces.Insert(0, surfaces.Insert(0,
new EglGlPlatformSurface((EglDisplay)egl.Display, egl.DeferredContext, new EglGlPlatformSurface(egl.DeferredContext,
new SurfaceInfo(this, _x11.DeferredDisplay, _handle, _renderHandle))); new SurfaceInfo(this, _x11.DeferredDisplay, _handle, _renderHandle)));
if (glx != null) if (glx != null)
surfaces.Insert(0, new GlxGlPlatformSurface(glx.Display, glx.DeferredContext, surfaces.Insert(0, new GlxGlPlatformSurface(glx.Display, glx.DeferredContext,

15
src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs

@ -15,6 +15,8 @@ namespace Avalonia.LinuxFramebuffer.Output
private readonly EglGlPlatformSurface _eglPlatformSurface; private readonly EglGlPlatformSurface _eglPlatformSurface;
public PixelSize PixelSize => _mode.Resolution; public PixelSize PixelSize => _mode.Resolution;
public double Scaling { get; set; } public double Scaling { get; set; }
public IGlContext MainContext => _deferredContext;
public DrmOutput(string path = null) public DrmOutput(string path = null)
{ {
var card = new DrmCard(path); var card = new DrmCard(path);
@ -132,8 +134,8 @@ namespace Avalonia.LinuxFramebuffer.Output
using (_deferredContext.MakeCurrent(_eglSurface)) using (_deferredContext.MakeCurrent(_eglSurface))
{ {
_eglDisplay.GlInterface.ClearColor(0, 0, 0, 0); _deferredContext.GlInterface.ClearColor(0, 0, 0, 0);
_eglDisplay.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT); _deferredContext.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT);
_eglSurface.SwapBuffers(); _eglSurface.SwapBuffers();
} }
@ -154,8 +156,8 @@ namespace Avalonia.LinuxFramebuffer.Output
for(var c=0;c<2;c++) for(var c=0;c<2;c++)
using (CreateGlRenderTarget().BeginDraw()) using (CreateGlRenderTarget().BeginDraw())
{ {
_eglDisplay.GlInterface.ClearColor(0, 0, 0, 0); _deferredContext.GlInterface.ClearColor(0, 0, 0, 0);
_eglDisplay.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT); _deferredContext.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT);
} }
} }
@ -191,7 +193,7 @@ namespace Avalonia.LinuxFramebuffer.Output
public void Dispose() public void Dispose()
{ {
_parent._eglDisplay.GlInterface.Flush(); _parent._deferredContext.GlInterface.Flush();
_parent._eglSurface.SwapBuffers(); _parent._eglSurface.SwapBuffers();
var nextBo = gbm_surface_lock_front_buffer(_parent._gbmTargetSurface); var nextBo = gbm_surface_lock_front_buffer(_parent._gbmTargetSurface);
@ -233,7 +235,7 @@ namespace Avalonia.LinuxFramebuffer.Output
} }
public IGlDisplay Display => _parent._eglDisplay; public IGlContext Context => _parent._deferredContext;
public PixelSize Size => _parent._mode.Resolution; public PixelSize Size => _parent._mode.Resolution;
@ -248,7 +250,6 @@ namespace Avalonia.LinuxFramebuffer.Output
} }
} }
public IGlDisplay Display => _eglDisplay;
public IGlContext CreateContext() public IGlContext CreateContext()
{ {
throw new NotImplementedException(); throw new NotImplementedException();

2
src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs

@ -59,7 +59,7 @@ namespace Avalonia.Skia
bool success = false; bool success = false;
try try
{ {
var disp = glSession.Display; var disp = glSession.Context;
var gl = disp.GlInterface; var gl = disp.GlInterface;
gl.GetIntegerv(GL_FRAMEBUFFER_BINDING, out var fb); gl.GetIntegerv(GL_FRAMEBUFFER_BINDING, out var fb);

12
src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs

@ -11,14 +11,12 @@ namespace Avalonia.Skia
public GlSkiaGpu(IWindowingPlatformGlFeature gl) public GlSkiaGpu(IWindowingPlatformGlFeature gl)
{ {
var context = gl.MainContext;
var immediateContext = gl.CreateContext(); using (context.MakeCurrent())
using (immediateContext.MakeCurrent())
{ {
var display = gl.Display; using (var iface = context.Version.Type == GlProfileType.OpenGL ?
using (var iface = display.Type == GlDisplayType.OpenGl ? GRGlInterface.AssembleGlInterface((_, proc) => context.GlInterface.GetProcAddress(proc)) :
GRGlInterface.AssembleGlInterface((_, proc) => display.GlInterface.GetProcAddress(proc)) : GRGlInterface.AssembleGlesInterface((_, proc) => context.GlInterface.GetProcAddress(proc)))
GRGlInterface.AssembleGlesInterface((_, proc) => display.GlInterface.GetProcAddress(proc)))
{ {
_grContext = GRContext.Create(GRBackend.OpenGL, iface); _grContext = GRContext.Create(GRBackend.OpenGL, iface);
} }

3
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -67,8 +67,7 @@ namespace Avalonia.Win32
CreateWindow(); CreateWindow();
_framebuffer = new FramebufferManager(_hwnd); _framebuffer = new FramebufferManager(_hwnd);
if (Win32GlManager.EglFeature != null) if (Win32GlManager.EglFeature != null)
_gl = new EglGlPlatformSurface((EglDisplay)Win32GlManager.EglFeature.Display, _gl = new EglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this);
Win32GlManager.EglFeature.DeferredContext, this);
s_instances.Add(this); s_instances.Add(this);
} }

Loading…
Cancel
Save