diff --git a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj index 73493c69c0..4dd7432082 100644 --- a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj +++ b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Avalonia.OpenGL/Controls/CompositionOpenGlSwapchain.cs b/src/Avalonia.OpenGL/Controls/CompositionOpenGlSwapchain.cs index 3db0aafd7b..42b1af7b25 100644 --- a/src/Avalonia.OpenGL/Controls/CompositionOpenGlSwapchain.cs +++ b/src/Avalonia.OpenGL/Controls/CompositionOpenGlSwapchain.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Avalonia.Platform; using Avalonia.Rendering; @@ -22,7 +21,7 @@ internal class CompositionOpenGlSwapchain : SwapchainBase } public CompositionOpenGlSwapchain(IGlContext context, ICompositionGpuInterop interop, CompositionDrawingSurface target, - IGlContextExternalObjectsFeature externalObjectsFeature) : base(interop, target) + IGlContextExternalObjectsFeature? externalObjectsFeature) : base(interop, target) { _context = context; _externalObjectsFeature = externalObjectsFeature; @@ -95,7 +94,7 @@ internal class DxgiMutexOpenGlSwapChainImage : IGlSwapchainImage public int TextureId => _texture.TextureId; public int InternalFormat => _texture.InternalFormat; public PixelSize Size => new(_texture.Properties.Width, _texture.Properties.Height); - public Task LastPresent => _lastPresent; + public Task? LastPresent => _lastPresent; public void BeginDraw() => _texture.AcquireKeyedMutex(0); public void Present() diff --git a/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs b/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs index 4d0663a12b..7e73397743 100644 --- a/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs +++ b/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Threading.Tasks; using Avalonia.Controls; @@ -11,10 +12,10 @@ namespace Avalonia.OpenGL.Controls { public abstract class OpenGlControlBase : Control { - private CompositionSurfaceVisual _visual; - private Action _update; + private CompositionSurfaceVisual? _visual; + private readonly Action _update; private bool _updateQueued; - private Task _initialization; + private Task? _initialization; private OpenGlControlBaseResources? _resources; private Compositor? _compositor; protected GlVersion GlVersion => _resources?.Context.Version ?? default; @@ -24,7 +25,7 @@ namespace Avalonia.OpenGL.Controls _update = Update; } - void DoCleanup() + private void DoCleanup() { if (_initialization is { Status: TaskStatus.RanToCompletion } && _resources != null) { @@ -63,14 +64,14 @@ namespace Avalonia.OpenGL.Controls RequestNextFrameRendering(); } + [MemberNotNullWhen(true, nameof(_resources))] private bool EnsureInitializedCore( ICompositionGpuInterop interop, - IOpenGlTextureSharingRenderInterfaceContextFeature contextSharingFeature) + IOpenGlTextureSharingRenderInterfaceContextFeature? contextSharingFeature) { - var surface = _compositor.CreateDrawingSurface(); + var surface = _compositor!.CreateDrawingSurface(); - IGlContext ctx = null; - var contextFactory = AvaloniaLocator.Current.GetService(); + IGlContext? ctx = null; try { if (contextSharingFeature?.CanCreateSharedContext == true) @@ -78,6 +79,7 @@ namespace Avalonia.OpenGL.Controls if(_resources == null) { + var contextFactory = AvaloniaLocator.Current.GetRequiredService(); ctx = contextFactory.CreateContext(null); if (ctx.TryGetFeature(out var externalObjects)) _resources = OpenGlControlBaseResources.TryCreate(ctx, surface, interop, externalObjects); @@ -121,13 +123,14 @@ namespace Avalonia.OpenGL.Controls base.OnPropertyChanged(change); } - void ContextLost() + private void ContextLost() { _initialization = null; _resources?.DisposeAsync(); OnOpenGlLost(); } + [MemberNotNullWhen(true, nameof(_resources))] private bool EnsureInitialized() { if (_initialization != null) @@ -170,11 +173,11 @@ namespace Avalonia.OpenGL.Controls private void Update() { _updateQueued = false; - if (VisualRoot == null) + if (VisualRoot is not { } visualRoot) return; if(!EnsureInitialized()) return; - using (_resources.BeginDraw(GetPixelSize())) + using (_resources.BeginDraw(GetPixelSize(visualRoot))) OnOpenGlRender(_resources.Context.GlInterface, _resources.Fbo); } @@ -190,7 +193,7 @@ namespace Avalonia.OpenGL.Controls var gpuInteropTask = _compositor.TryGetCompositionGpuInterop(); var contextSharingFeature = - (IOpenGlTextureSharingRenderInterfaceContextFeature) + (IOpenGlTextureSharingRenderInterfaceContextFeature?) await _compositor.TryGetRenderInterfaceFeature( typeof(IOpenGlTextureSharingRenderInterfaceContextFeature)); var interop = await gpuInteropTask; @@ -208,7 +211,7 @@ namespace Avalonia.OpenGL.Controls return false; } - using (_resources!.Context.MakeCurrent()) + using (_resources.Context.MakeCurrent()) OnOpenGlInit(_resources.Context.GlInterface); return true; @@ -228,9 +231,9 @@ namespace Avalonia.OpenGL.Controls } } - private PixelSize GetPixelSize() + private PixelSize GetPixelSize(IRenderRoot visualRoot) { - var scaling = VisualRoot!.RenderScaling; + var scaling = visualRoot.RenderScaling; return new PixelSize(Math.Max(1, (int)(Bounds.Width * scaling)), Math.Max(1, (int)(Bounds.Height * scaling))); } diff --git a/src/Avalonia.OpenGL/Controls/OpenGlControlResources.cs b/src/Avalonia.OpenGL/Controls/OpenGlControlResources.cs index bda2bd1568..3b0b3bd028 100644 --- a/src/Avalonia.OpenGL/Controls/OpenGlControlResources.cs +++ b/src/Avalonia.OpenGL/Controls/OpenGlControlResources.cs @@ -14,14 +14,14 @@ internal class OpenGlControlBaseResources : IAsyncDisposable public int Fbo { get; private set; } private PixelSize _depthBufferSize; public CompositionDrawingSurface Surface { get; } - public CompositionOpenGlSwapchain _swapchain; + private readonly CompositionOpenGlSwapchain _swapchain; public IGlContext Context { get; private set; } public static OpenGlControlBaseResources? TryCreate(CompositionDrawingSurface surface, ICompositionGpuInterop interop, IOpenGlTextureSharingRenderInterfaceContextFeature feature) { - IGlContext context; + IGlContext? context; try { context = feature.CreateSharedContext(); @@ -71,7 +71,7 @@ internal class OpenGlControlBaseResources : IAsyncDisposable new CompositionOpenGlSwapchain(context, interop, Surface, externalObjects); } - void UpdateDepthRenderbuffer(PixelSize size) + private void UpdateDepthRenderbuffer(PixelSize size) { if (size == _depthBufferSize && _depthBuffer != 0) return; diff --git a/src/Avalonia.OpenGL/Egl/EglContext.cs b/src/Avalonia.OpenGL/Egl/EglContext.cs index 48dfc6c4c0..936ec06c1d 100644 --- a/src/Avalonia.OpenGL/Egl/EglContext.cs +++ b/src/Avalonia.OpenGL/Egl/EglContext.cs @@ -12,15 +12,15 @@ namespace Avalonia.OpenGL.Egl { private readonly EglDisplay _disp; private readonly EglInterface _egl; - private readonly EglContext _sharedWith; + private readonly EglContext? _sharedWith; private bool _isLost; private IntPtr _context; - private readonly Action _disposeCallback; + private readonly Action? _disposeCallback; private readonly Dictionary _features; private readonly object _lock; - internal EglContext(EglDisplay display, EglInterface egl, EglContext sharedWith, IntPtr ctx, EglSurface offscreenSurface, - GlVersion version, int sampleCount, int stencilSize, Action disposeCallback, + internal EglContext(EglDisplay display, EglInterface egl, EglContext? sharedWith, IntPtr ctx, EglSurface? offscreenSurface, + GlVersion version, int sampleCount, int stencilSize, Action? disposeCallback, Dictionary> features) { _disp = display; @@ -42,19 +42,19 @@ namespace Avalonia.OpenGL.Egl public IntPtr Context => _context == IntPtr.Zero ? throw new ObjectDisposedException(nameof(EglContext)) : _context; - public EglSurface OffscreenSurface { get; } + public EglSurface? OffscreenSurface { get; } public GlVersion Version { get; } public GlInterface GlInterface { get; } public int SampleCount { get; } public int StencilSize { get; } public EglDisplay Display => _disp; - class RestoreContext : IDisposable + private class RestoreContext : IDisposable { private readonly EglInterface _egl; private readonly object _l; private readonly IntPtr _display; - public IntPtr _context, _read, _draw; + private readonly IntPtr _context, _read, _draw; public RestoreContext(EglInterface egl, IntPtr defDisplay, object l) { @@ -78,7 +78,7 @@ namespace Avalonia.OpenGL.Egl public IDisposable MakeCurrent() => MakeCurrent(OffscreenSurface); - public IDisposable MakeCurrent(EglSurface surface) + public IDisposable MakeCurrent(EglSurface? surface) { if (IsLost) throw new PlatformGraphicsContextLostException(); @@ -147,7 +147,7 @@ namespace Avalonia.OpenGL.Egl public bool CanCreateSharedContext => _disp.SupportsSharing; - public IGlContext CreateSharedContext(IEnumerable preferredVersions = null) => + public IGlContext CreateSharedContext(IEnumerable? preferredVersions = null) => _disp.CreateContext(new EglContextOptions { ShareWith = _sharedWith ?? this @@ -174,9 +174,9 @@ namespace Avalonia.OpenGL.Egl _disposeCallback?.Invoke(); } - public object TryGetFeature(Type featureType) + public object? TryGetFeature(Type featureType) { - if (_features?.TryGetValue(featureType, out var feature) == true) + if (_features.TryGetValue(featureType, out var feature)) return feature; return null; } diff --git a/src/Avalonia.OpenGL/Egl/EglDisplay.cs b/src/Avalonia.OpenGL/Egl/EglDisplay.cs index 60cad2fa1e..db1fe56139 100644 --- a/src/Avalonia.OpenGL/Egl/EglDisplay.cs +++ b/src/Avalonia.OpenGL/Egl/EglDisplay.cs @@ -14,14 +14,14 @@ namespace Avalonia.OpenGL.Egl private readonly EglDisplayOptions _options; private EglConfigInfo _config; private bool _isLost; - private object _lock = new(); + private readonly object _lock = new(); public bool SupportsSharing { get; } public IntPtr Handle => _display; public IntPtr Config => _config.Config; internal bool SingleContext => !_options.SupportsMultipleContexts; - private List _contexts = new(); + private readonly List _contexts = new(); public EglDisplay() : this(new EglDisplayCreationOptions { @@ -38,7 +38,7 @@ namespace Avalonia.OpenGL.Egl public EglDisplay(IntPtr display, EglDisplayOptions options) { - _egl = options.Egl; + _egl = options.Egl ?? new EglInterface(); SupportsSharing = options.SupportsContextSharing; _display = display; _options = options; @@ -49,7 +49,7 @@ namespace Avalonia.OpenGL.Egl } public EglInterface EglInterface => _egl; - public EglContext CreateContext(EglContextOptions options) + public EglContext CreateContext(EglContextOptions? options) { if (SingleContext && _contexts.Any()) throw new OpenGlException("This EGLDisplay can only have one active context"); @@ -129,7 +129,7 @@ namespace Avalonia.OpenGL.Egl protected virtual bool DisplayLockIsSharedWithContexts => false; - internal object ContextSharedSyncRoot => DisplayLockIsSharedWithContexts ? _lock : null; + internal object? ContextSharedSyncRoot => DisplayLockIsSharedWithContexts ? _lock : null; internal void OnContextLost(EglContext context) { @@ -171,7 +171,6 @@ namespace Avalonia.OpenGL.Egl if (_display != IntPtr.Zero) _egl.Terminate(_display); _display = IntPtr.Zero; - _config = null; _options.DisposeCallback?.Invoke(); } } diff --git a/src/Avalonia.OpenGL/Egl/EglDisplayOptions.cs b/src/Avalonia.OpenGL/Egl/EglDisplayOptions.cs index 906a533e2d..a2cbeb5b3d 100644 --- a/src/Avalonia.OpenGL/Egl/EglDisplayOptions.cs +++ b/src/Avalonia.OpenGL/Egl/EglDisplayOptions.cs @@ -5,26 +5,26 @@ namespace Avalonia.OpenGL.Egl; public class EglDisplayOptions { - public EglInterface Egl { get; set; } + public EglInterface? Egl { get; set; } public bool SupportsContextSharing { get; set; } public bool SupportsMultipleContexts { get; set; } public bool ContextLossIsDisplayLoss { get; set; } - public Func DeviceLostCheckCallback { get; set; } - public Action DisposeCallback { get; set; } - public IEnumerable GlVersions { get; set; } + public Func? DeviceLostCheckCallback { get; set; } + public Action? DisposeCallback { get; set; } + public IEnumerable? GlVersions { get; set; } } public class EglContextOptions { - public EglContext ShareWith { get; set; } - public EglSurface OffscreenSurface { get; set; } - public Action DisposeCallback { get; set; } - public Dictionary> ExtraFeatures { get; set; } + public EglContext? ShareWith { get; set; } + public EglSurface? OffscreenSurface { get; set; } + public Action? DisposeCallback { get; set; } + public Dictionary>? ExtraFeatures { get; set; } } public class EglDisplayCreationOptions : EglDisplayOptions { public int? PlatformType { get; set; } public IntPtr PlatformDisplay { get; set; } - public int[] PlatformDisplayAttrs { get; set; } + public int[]? PlatformDisplayAttrs { get; set; } } diff --git a/src/Avalonia.OpenGL/Egl/EglDisplayUtils.cs b/src/Avalonia.OpenGL/Egl/EglDisplayUtils.cs index 5573eb39fa..0adf114b54 100644 --- a/src/Avalonia.OpenGL/Egl/EglDisplayUtils.cs +++ b/src/Avalonia.OpenGL/Egl/EglDisplayUtils.cs @@ -1,15 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using static Avalonia.OpenGL.Egl.EglConsts; namespace Avalonia.OpenGL.Egl; -static class EglDisplayUtils +internal static class EglDisplayUtils { public static IntPtr CreateDisplay(EglDisplayCreationOptions options) { - var egl = options.Egl; + var egl = options.Egl ?? new EglInterface(); var display = IntPtr.Zero; if (options.PlatformType == null) { @@ -30,9 +29,9 @@ static class EglDisplayUtils return display; } - public static EglConfigInfo InitializeAndGetConfig(EglInterface egl, IntPtr display, IEnumerable versions) + public static EglConfigInfo InitializeAndGetConfig(EglInterface egl, IntPtr display, IEnumerable? versions) { - if (!egl.Initialize(display, out var major, out var minor)) + if (!egl.Initialize(display, out _, out _)) throw OpenGlException.GetFormattedException("eglInitialize", egl); // TODO: AvaloniaLocator.Current.GetService()?.GlProfiles @@ -112,7 +111,7 @@ static class EglDisplayUtils } -class EglConfigInfo +internal class EglConfigInfo { public IntPtr Config { get; } public GlVersion Version { get; } diff --git a/src/Avalonia.OpenGL/Egl/EglGlPlatformSurface.cs b/src/Avalonia.OpenGL/Egl/EglGlPlatformSurface.cs index 348028bd08..59ef25b1a4 100644 --- a/src/Avalonia.OpenGL/Egl/EglGlPlatformSurface.cs +++ b/src/Avalonia.OpenGL/Egl/EglGlPlatformSurface.cs @@ -27,9 +27,9 @@ namespace Avalonia.OpenGL.Egl return new RenderTarget(glSurface, eglContext, _info); } - class RenderTarget : EglPlatformSurfaceRenderTargetBase + private class RenderTarget : EglPlatformSurfaceRenderTargetBase { - private EglSurface _glSurface; + private EglSurface? _glSurface; private readonly IEglWindowGlPlatformSurfaceInfo _info; private PixelSize _currentSize; private readonly IntPtr _handle; @@ -42,12 +42,12 @@ namespace Avalonia.OpenGL.Egl _handle = _info.Handle; } - public override void Dispose() => _glSurface.Dispose(); + public override void Dispose() => _glSurface?.Dispose(); public override IGlPlatformSurfaceRenderingSession BeginDrawCore() { if (_info.Size != _currentSize - || _handle != _info.Handle + || _handle != _info.Handle || _glSurface == null) { _glSurface?.Dispose(); diff --git a/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs b/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs index f66f630556..927e1253fc 100644 --- a/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs +++ b/src/Avalonia.OpenGL/Egl/EglGlPlatformSurfaceBase.cs @@ -33,7 +33,7 @@ namespace Avalonia.OpenGL.Egl public abstract IGlPlatformSurfaceRenderingSession BeginDrawCore(); protected IGlPlatformSurfaceRenderingSession BeginDraw(EglSurface surface, - PixelSize size, double scaling, Action onFinish = null, bool isYFlipped = false) + PixelSize size, double scaling, Action? onFinish = null, bool isYFlipped = false) { var restoreContext = Context.MakeCurrent(surface); @@ -56,19 +56,18 @@ namespace Avalonia.OpenGL.Egl restoreContext.Dispose(); } } - - class Session : IGlPlatformSurfaceRenderingSession + + private class Session : IGlPlatformSurfaceRenderingSession { private readonly EglContext _context; private readonly EglSurface _glSurface; private readonly EglDisplay _display; private readonly IDisposable _restoreContext; - private readonly Action _onFinish; - + private readonly Action? _onFinish; public Session(EglDisplay display, EglContext context, EglSurface glSurface, PixelSize size, double scaling, - IDisposable restoreContext, Action onFinish, bool isYFlipped) + IDisposable restoreContext, Action? onFinish, bool isYFlipped) { Size = size; Scaling = scaling; diff --git a/src/Avalonia.OpenGL/Egl/EglInterface.cs b/src/Avalonia.OpenGL/Egl/EglInterface.cs index d2d41f4def..2235d9087c 100644 --- a/src/Avalonia.OpenGL/Egl/EglInterface.cs +++ b/src/Avalonia.OpenGL/Egl/EglInterface.cs @@ -49,7 +49,7 @@ namespace Avalonia.OpenGL.Egl public partial IntPtr GetDisplay(IntPtr nativeDisplay); [GetProcAddress("eglGetPlatformDisplayEXT", true)] - public partial IntPtr GetPlatformDisplayExt(int platform, IntPtr nativeDisplay, int[] attrs); + public partial IntPtr GetPlatformDisplayExt(int platform, IntPtr nativeDisplay, int[]? attrs); [GetProcAddress("eglInitialize")] public partial bool Initialize(IntPtr display, out int major, out int minor); @@ -75,7 +75,7 @@ namespace Avalonia.OpenGL.Egl public partial bool DestroyContext(IntPtr display, IntPtr context); [GetProcAddress("eglCreatePbufferSurface")] - public partial IntPtr CreatePBufferSurface(IntPtr display, IntPtr config, int[] attrs); + public partial IntPtr CreatePBufferSurface(IntPtr display, IntPtr config, int[]? attrs); [GetProcAddress("eglMakeCurrent")] public partial bool MakeCurrent(IntPtr display, IntPtr draw, IntPtr read, IntPtr context); @@ -96,7 +96,7 @@ namespace Avalonia.OpenGL.Egl public partial void SwapBuffers(IntPtr display, IntPtr surface); [GetProcAddress("eglCreateWindowSurface")] - public partial IntPtr CreateWindowSurface(IntPtr display, IntPtr config, IntPtr window, int[] attrs); + public partial IntPtr CreateWindowSurface(IntPtr display, IntPtr config, IntPtr window, int[]? attrs); [GetProcAddress("eglBindTexImage")] public partial int BindTexImage(IntPtr display, IntPtr surface, int buffer); @@ -116,7 +116,7 @@ namespace Avalonia.OpenGL.Egl [GetProcAddress("eglQueryString")] public partial IntPtr QueryStringNative(IntPtr display, int i); - public string QueryString(IntPtr display, int i) + public string? QueryString(IntPtr display, int i) { var rv = QueryStringNative(display, i); if (rv == IntPtr.Zero) @@ -125,7 +125,7 @@ namespace Avalonia.OpenGL.Egl } [GetProcAddress("eglCreatePbufferFromClientBuffer")] - public partial IntPtr CreatePbufferFromClientBuffer(IntPtr display, int buftype, IntPtr buffer, IntPtr config, int[] attrib_list); + public partial IntPtr CreatePbufferFromClientBuffer(IntPtr display, int buftype, IntPtr buffer, IntPtr config, int[]? attrib_list); [GetProcAddress("eglQueryDisplayAttribEXT", true)] public partial bool QueryDisplayAttribExt(IntPtr display, int attr, out IntPtr res); diff --git a/src/Avalonia.OpenGL/Egl/EglPlatformGraphics.cs b/src/Avalonia.OpenGL/Egl/EglPlatformGraphics.cs index faa9f279a6..07e304febe 100644 --- a/src/Avalonia.OpenGL/Egl/EglPlatformGraphics.cs +++ b/src/Avalonia.OpenGL/Egl/EglPlatformGraphics.cs @@ -1,7 +1,6 @@ using System; using Avalonia.Logging; using Avalonia.Platform; -using static Avalonia.OpenGL.Egl.EglConsts; namespace Avalonia.OpenGL.Egl { @@ -24,7 +23,7 @@ namespace Avalonia.OpenGL.Egl AvaloniaLocator.CurrentMutable.Bind().ToConstant(feature); } - public static EglPlatformGraphics TryCreate() => TryCreate(() => new EglDisplay(new EglDisplayCreationOptions + public static EglPlatformGraphics? TryCreate() => TryCreate(() => new EglDisplay(new EglDisplayCreationOptions { Egl = new EglInterface(), // Those are expected to be supported by most EGL implementations @@ -32,7 +31,7 @@ namespace Avalonia.OpenGL.Egl SupportsContextSharing = true })); - public static EglPlatformGraphics TryCreate(Func displayFactory) + public static EglPlatformGraphics? TryCreate(Func displayFactory) { try { diff --git a/src/Avalonia.OpenGL/Features/ExternalObjectsOpenGlExtensionFeature.cs b/src/Avalonia.OpenGL/Features/ExternalObjectsOpenGlExtensionFeature.cs index 02d152ff61..6778726f84 100644 --- a/src/Avalonia.OpenGL/Features/ExternalObjectsOpenGlExtensionFeature.cs +++ b/src/Avalonia.OpenGL/Features/ExternalObjectsOpenGlExtensionFeature.cs @@ -63,10 +63,10 @@ public class ExternalObjectsOpenGlExtensionFeature : IGlContextExternalObjectsFe { private readonly IGlContext _context; private readonly ExternalObjectsInterface _ext; - private List _imageTypes = new(); - private List _semaphoreTypes = new(); + private readonly List _imageTypes = new(); + private readonly List _semaphoreTypes = new(); - public static ExternalObjectsOpenGlExtensionFeature TryCreate(IGlContext context) + public static ExternalObjectsOpenGlExtensionFeature? TryCreate(IGlContext context) { var extensions = context.GlInterface.GetExtensions(); if (extensions.Contains("GL_EXT_memory_object") && extensions.Contains("GL_EXT_semaphore")) @@ -142,10 +142,15 @@ public class ExternalObjectsOpenGlExtensionFeature : IGlContextExternalObjectsFe public IGlExternalImageTexture ImportImage(IPlatformHandle handle, PlatformGraphicsExternalImageProperties properties) { - if(!_imageTypes.Contains(handle.HandleDescriptor)) - throw new ArgumentException(handle.HandleDescriptor + " is not supported"); - - if (handle.HandleDescriptor == KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaquePosixFileDescriptor) + var handleDescriptor = handle.HandleDescriptor; + + if (string.IsNullOrEmpty(handleDescriptor)) + throw new ArgumentException("The handle must have a descriptor", nameof(handle)); + + if (!_imageTypes.Contains(handleDescriptor)) + throw new ArgumentException(handleDescriptor + " is not supported", nameof(handle)); + + if (handleDescriptor == KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaquePosixFileDescriptor) { while (_context.GlInterface.GetError() != 0) { @@ -174,23 +179,27 @@ public class ExternalObjectsOpenGlExtensionFeature : IGlContextExternalObjectsFe return new ExternalImageTexture(_context, properties, _ext, memoryObject, texture); } - throw new ArgumentException(handle.HandleDescriptor + " is not supported"); + throw new ArgumentException(handleDescriptor + " is not supported", nameof(handle)); } public IGlExternalSemaphore ImportSemaphore(IPlatformHandle handle) { - if(!_semaphoreTypes.Contains(handle.HandleDescriptor)) - throw new ArgumentException(handle.HandleDescriptor + " is not supported"); + var handleDescriptor = handle.HandleDescriptor; + + if (string.IsNullOrEmpty(handleDescriptor)) + throw new ArgumentException("The handle must have a descriptor", nameof(handle)); + + if (!_semaphoreTypes.Contains(handleDescriptor)) + throw new ArgumentException(handleDescriptor + " is not supported"); - if (handle.HandleDescriptor == - KnownPlatformGraphicsExternalSemaphoreHandleTypes.VulkanOpaquePosixFileDescriptor) + if (handleDescriptor == KnownPlatformGraphicsExternalSemaphoreHandleTypes.VulkanOpaquePosixFileDescriptor) { _ext.GenSemaphoresEXT(1, out var semaphore); _ext.ImportSemaphoreFdEXT(semaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, handle.Handle.ToInt32()); return new ExternalSemaphore(_context, _ext, semaphore); } - throw new ArgumentException(handle.HandleDescriptor + " is not supported"); + throw new ArgumentException(handleDescriptor + " is not supported", nameof(handle)); } public CompositionGpuImportedImageSynchronizationCapabilities GetSynchronizationCapabilities(string imageHandleType) @@ -200,10 +209,10 @@ public class ExternalObjectsOpenGlExtensionFeature : IGlContextExternalObjectsFe return default; } - public byte[] DeviceLuid { get; } - public byte[] DeviceUuid { get; } + public byte[]? DeviceLuid { get; } + public byte[]? DeviceUuid { get; } - unsafe class ExternalSemaphore : IGlExternalSemaphore + private unsafe class ExternalSemaphore : IGlExternalSemaphore { private readonly IGlContext _context; private readonly ExternalObjectsInterface _ext; @@ -242,7 +251,7 @@ public class ExternalObjectsOpenGlExtensionFeature : IGlContextExternalObjectsFe } } - class ExternalImageTexture : IGlExternalImageTexture + private class ExternalImageTexture : IGlExternalImageTexture { private readonly IGlContext _context; private readonly ExternalObjectsInterface _ext; diff --git a/src/Avalonia.OpenGL/GlBasicInfoInterface.cs b/src/Avalonia.OpenGL/GlBasicInfoInterface.cs index 7a7110f15b..38969cc966 100644 --- a/src/Avalonia.OpenGL/GlBasicInfoInterface.cs +++ b/src/Avalonia.OpenGL/GlBasicInfoInterface.cs @@ -2,14 +2,14 @@ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; -using Avalonia.Platform.Interop; using Avalonia.SourceGenerator; namespace Avalonia.OpenGL { public unsafe partial class GlBasicInfoInterface { - public GlBasicInfoInterface(Func getProcAddress){ + public GlBasicInfoInterface(Func getProcAddress) + { Initialize(getProcAddress); } @@ -22,7 +22,7 @@ namespace Avalonia.OpenGL [GetProcAddress("glGetStringi")] public partial IntPtr GetStringiNative(int v, int v1); - public string GetString(int v) + public string? GetString(int v) { var ptr = GetStringNative(v); if (ptr != IntPtr.Zero) @@ -30,7 +30,7 @@ namespace Avalonia.OpenGL return null; } - public string GetString(int v, int index) + public string? GetString(int v, int index) { var ptr = GetStringiNative(v, index); if (ptr != IntPtr.Zero) @@ -46,7 +46,13 @@ namespace Avalonia.OpenGL GetIntegerv(GlConsts.GL_NUM_EXTENSIONS, out int count); var rv = new List(count); for (var c = 0; c < count; c++) - rv.Add(GetString(GlConsts.GL_EXTENSIONS, c)); + { + if (GetString(GlConsts.GL_EXTENSIONS, c) is { } extension) + { + rv.Add(extension); + } + } + return rv; } } diff --git a/src/Avalonia.OpenGL/GlInterface.cs b/src/Avalonia.OpenGL/GlInterface.cs index a9dd882e3b..a6dadcd087 100644 --- a/src/Avalonia.OpenGL/GlInterface.cs +++ b/src/Avalonia.OpenGL/GlInterface.cs @@ -11,9 +11,9 @@ namespace Avalonia.OpenGL public unsafe partial class GlInterface : GlBasicInfoInterface { private readonly Func _getProcAddress; - public string Version { get; } - public string Vendor { get; } - public string Renderer { get; } + public string? Version { get; } + public string? Vendor { get; } + public string? Renderer { get; } public GlContextInfo ContextInfo { get; } public class GlContextInfo @@ -39,9 +39,9 @@ namespace Avalonia.OpenGL { _getProcAddress = getProcAddress; ContextInfo = info; - Version = GetString(GlConsts.GL_VERSION); - Renderer = GetString(GlConsts.GL_RENDERER); - Vendor = GetString(GlConsts.GL_VENDOR); + Version = GetString(GL_VERSION); + Renderer = GetString(GL_RENDERER); + Vendor = GetString(GL_VENDOR); Initialize(getProcAddress, ContextInfo); } @@ -203,7 +203,7 @@ namespace Avalonia.OpenGL [GetProcAddress("glGetShaderInfoLog")] public partial void GetShaderInfoLog(int shader, int maxLength, out int length, void* infoLog); - public unsafe string CompileShaderAndGetError(int shader, string source) + public unsafe string? CompileShaderAndGetError(int shader, string source) { ShaderSourceString(shader, source); CompileShader(shader); @@ -238,7 +238,7 @@ namespace Avalonia.OpenGL [GetProcAddress("glGetProgramInfoLog")] public partial void GetProgramInfoLog(int program, int maxLength, out int len, void* infoLog); - public unsafe string LinkProgramAndGetError(int program) + public unsafe string? LinkProgramAndGetError(int program) { LinkProgram(program); int compiled; @@ -374,4 +374,4 @@ namespace Avalonia.OpenGL }); } } -} \ No newline at end of file +} diff --git a/src/Avalonia.OpenGL/IGlContext.cs b/src/Avalonia.OpenGL/IGlContext.cs index d45ea931d0..fb4554d37f 100644 --- a/src/Avalonia.OpenGL/IGlContext.cs +++ b/src/Avalonia.OpenGL/IGlContext.cs @@ -15,7 +15,7 @@ namespace Avalonia.OpenGL IDisposable EnsureCurrent(); bool IsSharedWith(IGlContext context); bool CanCreateSharedContext { get; } - IGlContext CreateSharedContext(IEnumerable preferredVersions = null); + IGlContext? CreateSharedContext(IEnumerable? preferredVersions = null); } public interface IGlPlatformSurfaceRenderTargetFactory diff --git a/src/Avalonia.OpenGL/IOpenGlTextureSharingRenderInterfaceContextFeature.cs b/src/Avalonia.OpenGL/IOpenGlTextureSharingRenderInterfaceContextFeature.cs index 2043e944d1..19127fba40 100644 --- a/src/Avalonia.OpenGL/IOpenGlTextureSharingRenderInterfaceContextFeature.cs +++ b/src/Avalonia.OpenGL/IOpenGlTextureSharingRenderInterfaceContextFeature.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using Avalonia.Rendering.Composition; @@ -7,7 +6,7 @@ namespace Avalonia.OpenGL public interface IOpenGlTextureSharingRenderInterfaceContextFeature { bool CanCreateSharedContext { get; } - IGlContext CreateSharedContext(IEnumerable preferredVersions = null); + IGlContext? CreateSharedContext(IEnumerable? preferredVersions = null); ICompositionImportableOpenGlSharedTexture CreateSharedTextureForComposition(IGlContext context, PixelSize size); } diff --git a/src/Avalonia.OpenGL/OpenGlException.cs b/src/Avalonia.OpenGL/OpenGlException.cs index c498ed7833..d7a42c4400 100644 --- a/src/Avalonia.OpenGL/OpenGlException.cs +++ b/src/Avalonia.OpenGL/OpenGlException.cs @@ -5,13 +5,13 @@ namespace Avalonia.OpenGL { public class OpenGlException : Exception { - public int? ErrorCode { get; private set; } + public int? ErrorCode { get; } - public OpenGlException(string message) : base(message) + public OpenGlException(string? message) : base(message) { } - private OpenGlException(string message, int errorCode) : base(message) + private OpenGlException(string? message, int errorCode) : base(message) { ErrorCode = errorCode; }