Browse Source

Nullable annotations for LinuxFramebuffer (#17489)

pull/17499/head
Julien Lebosquain 1 year ago
committed by GitHub
parent
commit
601425d519
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
  2. 7
      src/Linux/Avalonia.LinuxFramebuffer/EpollDispatcherImpl.cs
  3. 27
      src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
  4. 8
      src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevBackend.cs
  5. 4
      src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevDevice.cs
  6. 2
      src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevDeviceDescription.cs
  7. 14
      src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevTouchScreen.cs
  8. 22
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Pointer.cs
  9. 2
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Touch.cs
  10. 4
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
  11. 4
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs
  12. 4
      src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
  13. 4
      src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs
  14. 19
      src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
  15. 4
      src/Linux/Avalonia.LinuxFramebuffer/Output/FbDevBackBuffer.cs
  16. 2
      src/Linux/Avalonia.LinuxFramebuffer/Output/FbDevOutputOptions.cs
  17. 8
      src/Linux/Avalonia.LinuxFramebuffer/Output/FbdevOutput.cs
  18. 1
      src/Linux/Avalonia.LinuxFramebuffer/Output/IGlOutputBackend.cs

1
src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj

@ -10,4 +10,5 @@
<Compile Include="..\..\Shared\RawEventGrouping.cs" /> <Compile Include="..\..\Shared\RawEventGrouping.cs" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\..\build\TrimmingEnable.props" /> <Import Project="..\..\..\build\TrimmingEnable.props" />
<Import Project="..\..\..\build\NullableEnable.props" />
</Project> </Project>

7
src/Linux/Avalonia.LinuxFramebuffer/EpollDispatcherImpl.cs

@ -11,7 +11,7 @@ namespace Avalonia.LinuxFramebuffer;
internal unsafe class EpollDispatcherImpl : IControlledDispatcherImpl internal unsafe class EpollDispatcherImpl : IControlledDispatcherImpl
{ {
private readonly ManagedDispatcherImpl.IManagedDispatcherInputProvider _inputProvider; private readonly ManagedDispatcherImpl.IManagedDispatcherInputProvider _inputProvider;
private Thread _mainThread; private readonly Thread _mainThread;
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
private struct epoll_data private struct epoll_data
@ -161,6 +161,7 @@ internal unsafe class EpollDispatcherImpl : IControlledDispatcherImpl
itimerspec timer = new() itimerspec timer = new()
{ {
it_interval = default,
it_value = new() it_value = new()
{ {
tv_sec = new IntPtr(Math.Min((int)waitFor.TotalSeconds, 100)), tv_sec = new IntPtr(Math.Min((int)waitFor.TotalSeconds, 100)),
@ -219,8 +220,8 @@ internal unsafe class EpollDispatcherImpl : IControlledDispatcherImpl
public bool CurrentThreadIsLoopThread => Thread.CurrentThread == _mainThread; public bool CurrentThreadIsLoopThread => Thread.CurrentThread == _mainThread;
public event Action Signaled; public event Action? Signaled;
public event Action Timer; public event Action? Timer;
public void UpdateTimer(long? dueTimeInMs) public void UpdateTimer(long? dueTimeInMs)
{ {

27
src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs

@ -6,7 +6,6 @@ using Avalonia.Input.Raw;
using Avalonia.LinuxFramebuffer.Input; using Avalonia.LinuxFramebuffer.Input;
using Avalonia.LinuxFramebuffer.Output; using Avalonia.LinuxFramebuffer.Output;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition; using Avalonia.Rendering.Composition;
using Avalonia.Threading; using Avalonia.Threading;
@ -18,7 +17,7 @@ using Avalonia.Rendering.Composition;
private readonly IInputBackend _inputBackend; private readonly IInputBackend _inputBackend;
private readonly RawEventGrouper _inputQueue; private readonly RawEventGrouper _inputQueue;
public IInputRoot InputRoot { get; private set; } public IInputRoot? InputRoot { get; private set; }
public FramebufferToplevelImpl(IOutputBackend outputBackend, IInputBackend inputBackend) public FramebufferToplevelImpl(IOutputBackend outputBackend, IInputBackend inputBackend)
{ {
@ -49,28 +48,28 @@ using Avalonia.Rendering.Composition;
public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1); public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1);
public void SetCursor(ICursorImpl cursor) public void SetCursor(ICursorImpl? cursor)
{ {
} }
public double DesktopScaling => 1; public double DesktopScaling => 1;
public IPlatformHandle Handle { get; } public IPlatformHandle? Handle => null;
public Size ClientSize => ScaledSize; public Size ClientSize => ScaledSize;
public Size? FrameSize => null; public Size? FrameSize => null;
public IMouseDevice MouseDevice => new MouseDevice(); public IMouseDevice MouseDevice { get; } = new MouseDevice();
public IPopupImpl CreatePopup() => null; public IPopupImpl? CreatePopup() => null;
public double RenderScaling => _outputBackend.Scaling; public double RenderScaling => _outputBackend.Scaling;
public IEnumerable<object> Surfaces { get; } public IEnumerable<object> Surfaces { get; }
public Action<RawInputEventArgs> Input { get; set; } public Action<RawInputEventArgs>? Input { get; set; }
public Action<Rect> Paint { get; set; } public Action<Rect>? Paint { get; set; }
public Action<Size, WindowResizeReason> Resized { get; set; } public Action<Size, WindowResizeReason>? Resized { get; set; }
public Action<double> ScalingChanged { get; set; } public Action<double>? ScalingChanged { get; set; }
public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; } public Action<WindowTransparencyLevel>? TransparencyLevelChanged { get; set; }
public Action Closed { get; set; } public Action? Closed { get; set; }
public Action LostFocus { get; set; } public Action? LostFocus { get; set; }
public Size ScaledSize => _outputBackend.PixelSize.ToSize(RenderScaling); public Size ScaledSize => _outputBackend.PixelSize.ToSize(RenderScaling);
@ -81,6 +80,6 @@ using Avalonia.Rendering.Composition;
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { } public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1); public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1);
public object TryGetFeature(Type featureType) => null; public object? TryGetFeature(Type featureType) => null;
} }
} }

8
src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevBackend.cs

@ -12,8 +12,8 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
private readonly EvDevDeviceDescription[] _deviceDescriptions; private readonly EvDevDeviceDescription[] _deviceDescriptions;
private readonly List<EvDevDeviceHandler> _handlers = new List<EvDevDeviceHandler>(); private readonly List<EvDevDeviceHandler> _handlers = new List<EvDevDeviceHandler>();
private int _epoll; private int _epoll;
private Action<RawInputEventArgs> _onInput; private Action<RawInputEventArgs>? _onInput;
private IInputRoot _inputRoot; private IInputRoot? _inputRoot;
public EvDevBackend(EvDevDeviceDescription[] devices) public EvDevBackend(EvDevDeviceDescription[] devices)
{ {
@ -53,7 +53,7 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
for (var c = 0; c < _deviceDescriptions.Length; c++) for (var c = 0; c < _deviceDescriptions.Length; c++)
{ {
var description = _deviceDescriptions[c]; var description = _deviceDescriptions[c];
var dev = EvDevDevice.Open(description.Path); var dev = EvDevDevice.Open(description.Path ?? string.Empty);
EvDevDeviceHandler handler; EvDevDeviceHandler handler;
if (description is EvDevTouchScreenDeviceDescription touch) if (description is EvDevTouchScreenDeviceDescription touch)
handler = new EvDevSingleTouchScreen(dev, touch, info) { InputRoot = _inputRoot }; handler = new EvDevSingleTouchScreen(dev, touch, info) { InputRoot = _inputRoot };
@ -86,7 +86,7 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
{ {
if (key.StartsWith("AVALONIA_EVDEV_DEVICE_")) if (key.StartsWith("AVALONIA_EVDEV_DEVICE_"))
{ {
var value = (string)env[key]; var value = (string)env[key]!;
deviceDescriptions.Add(EvDevDeviceDescription.ParseFromEnv(value)); deviceDescriptions.Add(EvDevDeviceDescription.ParseFromEnv(value));
} }
} }

4
src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevDevice.cs

@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Avalonia.LinuxFramebuffer.Input.EvDev namespace Avalonia.LinuxFramebuffer.Input.EvDev
@ -10,7 +8,7 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
{ {
public int Fd { get; } public int Fd { get; }
private IntPtr _dev; private IntPtr _dev;
public string Name { get; } public string? Name { get; }
public List<EvType> EventTypes { get; private set; } = new List<EvType>(); public List<EvType> EventTypes { get; private set; } = new List<EvType>();
public input_absinfo? AbsX { get; } public input_absinfo? AbsX { get; }
public input_absinfo? AbsY { get; } public input_absinfo? AbsY { get; }

2
src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevDeviceDescription.cs

@ -10,7 +10,7 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
} }
public string Path { get; set; } public string? Path { get; set; }
internal static EvDevDeviceDescription ParseFromEnv(string env) internal static EvDevDeviceDescription ParseFromEnv(string env)
{ {

14
src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevTouchScreen.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.Raw; using Avalonia.Input.Raw;
@ -90,14 +91,23 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
internal abstract class EvDevDeviceHandler internal abstract class EvDevDeviceHandler
{ {
public event Action<RawInputEventArgs> OnEvent; private IInputRoot? _inputRoot;
public event Action<RawInputEventArgs>? OnEvent;
public EvDevDeviceHandler(EvDevDevice device) public EvDevDeviceHandler(EvDevDevice device)
{ {
Device = device; Device = device;
} }
public EvDevDevice Device { get; } public EvDevDevice Device { get; }
public IInputRoot InputRoot { get; set; }
[AllowNull]
public IInputRoot InputRoot
{
get => _inputRoot ?? throw new InvalidOperationException($"{nameof(InputRoot)} hasn't been set");
set => _inputRoot = value;
}
public void HandleEvents() public void HandleEvents()
{ {

22
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Pointer.cs

@ -16,14 +16,14 @@ public partial class LibInputBackend
{ {
var modifiers = RawInputModifiers.None; //TODO: support input modifiers var modifiers = RawInputModifiers.None; //TODO: support input modifiers
var pev = libinput_event_get_pointer_event(ev); var pev = libinput_event_get_pointer_event(ev);
var info = _screen.ScaledSize; var info = _screen!.ScaledSize;
var ts = libinput_event_pointer_get_time_usec(pev) / 1000; var ts = libinput_event_pointer_get_time_usec(pev) / 1000;
switch (type) switch (type)
{ {
case LibInputEventType.LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: case LibInputEventType.LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
_mousePosition = new Point(libinput_event_pointer_get_absolute_x_transformed(pev, (int)info.Width), _mousePosition = new Point(libinput_event_pointer_get_absolute_x_transformed(pev, (int)info.Width),
libinput_event_pointer_get_absolute_y_transformed(pev, (int)info.Height)); libinput_event_pointer_get_absolute_y_transformed(pev, (int)info.Height));
ScheduleInput(new RawPointerEventArgs(_mouse, ts, _inputRoot, RawPointerEventType.Move, _mousePosition, ScheduleInput(new RawPointerEventArgs(_mouse, ts, InputRoot, RawPointerEventType.Move, _mousePosition,
modifiers)); modifiers));
break; break;
case LibInputEventType.LIBINPUT_EVENT_POINTER_BUTTON: case LibInputEventType.LIBINPUT_EVENT_POINTER_BUTTON:
@ -31,20 +31,20 @@ public partial class LibInputBackend
var button = (EvKey)libinput_event_pointer_get_button(pev); var button = (EvKey)libinput_event_pointer_get_button(pev);
var buttonState = libinput_event_pointer_get_button_state(pev); var buttonState = libinput_event_pointer_get_button_state(pev);
RawPointerEventArgs evnt = button switch RawPointerEventArgs? evnt = button switch
{ {
EvKey.BTN_LEFT when buttonState == 1 EvKey.BTN_LEFT when buttonState == 1
=> new(_mouse, ts, _inputRoot, RawPointerEventType.LeftButtonDown, _mousePosition, modifiers), => new(_mouse, ts, InputRoot, RawPointerEventType.LeftButtonDown, _mousePosition, modifiers),
EvKey.BTN_LEFT when buttonState == 0 EvKey.BTN_LEFT when buttonState == 0
=> new(_mouse, ts, _inputRoot, RawPointerEventType.LeftButtonUp, _mousePosition, modifiers), => new(_mouse, ts, InputRoot, RawPointerEventType.LeftButtonUp, _mousePosition, modifiers),
EvKey.BTN_RIGHT when buttonState == 1 EvKey.BTN_RIGHT when buttonState == 1
=> new(_mouse, ts, _inputRoot, RawPointerEventType.RightButtonUp, _mousePosition, modifiers), => new(_mouse, ts, InputRoot, RawPointerEventType.RightButtonUp, _mousePosition, modifiers),
EvKey.BTN_RIGHT when buttonState == 2 EvKey.BTN_RIGHT when buttonState == 2
=> new(_mouse, ts, _inputRoot, RawPointerEventType.RightButtonDown, _mousePosition, modifiers), => new(_mouse, ts, InputRoot, RawPointerEventType.RightButtonDown, _mousePosition, modifiers),
EvKey.BTN_MIDDLE when buttonState == 1 EvKey.BTN_MIDDLE when buttonState == 1
=> new(_mouse, ts, _inputRoot, RawPointerEventType.MiddleButtonDown, _mousePosition, modifiers), => new(_mouse, ts, InputRoot, RawPointerEventType.MiddleButtonDown, _mousePosition, modifiers),
EvKey.BTN_MIDDLE when buttonState == 2 EvKey.BTN_MIDDLE when buttonState == 2
=> new(_mouse, ts, _inputRoot, RawPointerEventType.MiddleButtonUp, _mousePosition, modifiers), => new(_mouse, ts, InputRoot, RawPointerEventType.MiddleButtonUp, _mousePosition, modifiers),
_ => default, _ => default,
}; };
if (evnt is not null) if (evnt is not null)
@ -70,7 +70,7 @@ public partial class LibInputBackend
LibInputPointerAxis.LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); LibInputPointerAxis.LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
ScheduleInput(new RawMouseWheelEventArgs(_mouse ScheduleInput(new RawMouseWheelEventArgs(_mouse
, ts , ts
, _inputRoot , InputRoot
, _mousePosition , _mousePosition
, new Vector(0, -value) , new Vector(0, -value)
, modifiers)); , modifiers));
@ -94,7 +94,7 @@ public partial class LibInputBackend
LibInputPointerAxis.LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) / 120); LibInputPointerAxis.LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) / 120);
ScheduleInput(new RawMouseWheelEventArgs(_mouse ScheduleInput(new RawMouseWheelEventArgs(_mouse
, ts , ts
, _inputRoot , InputRoot
, _mousePosition , _mousePosition
, value , value
, modifiers)); , modifiers));

2
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Touch.cs

@ -18,7 +18,7 @@ public partial class LibInputBackend
return; return;
if (type < LibInputEventType.LIBINPUT_EVENT_TOUCH_FRAME) if (type < LibInputEventType.LIBINPUT_EVENT_TOUCH_FRAME)
{ {
var info = _screen.ScaledSize; var info = _screen!.ScaledSize;
var slot = libinput_event_touch_get_slot(tev); var slot = libinput_event_touch_get_slot(tev);
Point pt; Point pt;

4
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs

@ -1,4 +1,3 @@
#nullable enable
using System; using System;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
@ -25,6 +24,9 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
_options = options; _options = options;
} }
private IInputRoot InputRoot
=> _inputRoot ?? throw new InvalidOperationException($"{nameof(InputRoot)} hasn't been set");
private unsafe void InputThread(IntPtr ctx, LibInputBackendOptions options) private unsafe void InputThread(IntPtr ctx, LibInputBackendOptions options)
{ {
var fd = libinput_get_fd(ctx); var fd = libinput_get_fd(ctx);

4
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs

@ -13,7 +13,7 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
static int OpenRestricted(IntPtr path, int flags, IntPtr userData) static int OpenRestricted(IntPtr path, int flags, IntPtr userData)
{ {
var fd = NativeUnsafeMethods.open(Marshal.PtrToStringAnsi(path), flags, 0); var fd = NativeUnsafeMethods.open(Marshal.PtrToStringAnsi(path) ?? string.Empty, flags, 0);
if (fd == -1) if (fd == -1)
return -Marshal.GetLastWin32Error(); return -Marshal.GetLastWin32Error();
@ -31,7 +31,7 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
{ {
s_Interface = (IntPtr*)Marshal.AllocHGlobal(IntPtr.Size * 2); s_Interface = (IntPtr*)Marshal.AllocHGlobal(IntPtr.Size * 2);
IntPtr Convert<TDelegate>(TDelegate del) IntPtr Convert<TDelegate>(TDelegate del) where TDelegate : notnull
{ {
GCHandle.Alloc(del); GCHandle.Alloc(del);
return Marshal.GetFunctionPointerForDelegate(del); return Marshal.GetFunctionPointerForDelegate(del);

4
src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
@ -8,7 +7,6 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Embedding; using Avalonia.Controls.Embedding;
using Avalonia.Controls.Platform;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.Platform; using Avalonia.Input.Platform;
using Avalonia.LinuxFramebuffer; using Avalonia.LinuxFramebuffer;
@ -21,8 +19,6 @@ using Avalonia.Rendering;
using Avalonia.Rendering.Composition; using Avalonia.Rendering.Composition;
using Avalonia.Threading; using Avalonia.Threading;
#nullable enable
namespace Avalonia.LinuxFramebuffer namespace Avalonia.LinuxFramebuffer
{ {
internal class LinuxFramebufferIconLoaderStub : IPlatformIconLoader internal class LinuxFramebufferIconLoaderStub : IPlatformIconLoader

4
src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs

@ -63,7 +63,7 @@ namespace Avalonia.LinuxFramebuffer.Output
public PixelSize Resolution => new PixelSize(Mode.hdisplay, Mode.vdisplay); public PixelSize Resolution => new PixelSize(Mode.hdisplay, Mode.vdisplay);
public bool IsPreferred => Mode.type.HasAllFlags(DrmModeType.DRM_MODE_TYPE_PREFERRED); public bool IsPreferred => Mode.type.HasAllFlags(DrmModeType.DRM_MODE_TYPE_PREFERRED);
public string Name { get; } public string? Name { get; }
} }
unsafe class DrmEncoder unsafe class DrmEncoder
@ -141,7 +141,7 @@ namespace Avalonia.LinuxFramebuffer.Output
public unsafe class DrmCard : IDisposable public unsafe class DrmCard : IDisposable
{ {
public int Fd { get; private set; } public int Fd { get; private set; }
public DrmCard(string path = null) public DrmCard(string? path = null)
{ {
if (path == null) if (path == null)
{ {

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

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Avalonia.OpenGL; using Avalonia.OpenGL;
@ -41,19 +42,19 @@ namespace Avalonia.LinuxFramebuffer.Output
public IPlatformGraphics PlatformGraphics { get; private set; } public IPlatformGraphics PlatformGraphics { get; private set; }
public DrmOutput(DrmCard card, DrmResources resources, DrmConnector connector, DrmModeInfo modeInfo, public DrmOutput(DrmCard card, DrmResources resources, DrmConnector connector, DrmModeInfo modeInfo,
DrmOutputOptions options = null) DrmOutputOptions? options = null)
{ {
if (options != null) if (options != null)
_outputOptions = options; _outputOptions = options;
Init(card, resources, connector, modeInfo); Init(card, resources, connector, modeInfo);
} }
public DrmOutput(string path = null, bool connectorsForceProbe = false, DrmOutputOptions options = null) public DrmOutput(string? path = null, bool connectorsForceProbe = false, DrmOutputOptions? options = null)
:this(new DrmCard(path), connectorsForceProbe, options) :this(new DrmCard(path), connectorsForceProbe, options)
{ {
} }
public DrmOutput(DrmCard card, bool connectorsForceProbe = false, DrmOutputOptions options = null) public DrmOutput(DrmCard card, bool connectorsForceProbe = false, DrmOutputOptions? options = null)
{ {
if (options != null) if (options != null)
_outputOptions = options; _outputOptions = options;
@ -78,7 +79,7 @@ namespace Avalonia.LinuxFramebuffer.Output
if (connector == null) if (connector == null)
throw new InvalidOperationException("Unable to find connected DRM connector"); throw new InvalidOperationException("Unable to find connected DRM connector");
DrmModeInfo mode = null; DrmModeInfo? mode = null;
if (options?.VideoMode != null) if (options?.VideoMode != null)
{ {
@ -157,6 +158,12 @@ namespace Avalonia.LinuxFramebuffer.Output
} }
[MemberNotNull(nameof(_card))]
[MemberNotNull(nameof(PlatformGraphics))]
[MemberNotNull(nameof(FbDestroyDelegate))]
[MemberNotNull(nameof(_eglDisplay))]
[MemberNotNull(nameof(_eglSurface))]
[MemberNotNull(nameof(_deferredContext))]
void Init(DrmCard card, DrmResources resources, DrmConnector connector, DrmModeInfo modeInfo) void Init(DrmCard card, DrmResources resources, DrmConnector connector, DrmModeInfo modeInfo)
{ {
FbDestroyDelegate = FbDestroyCallback; FbDestroyDelegate = FbDestroyCallback;
@ -232,7 +239,7 @@ namespace Avalonia.LinuxFramebuffer.Output
if (_outputOptions.EnableInitialBufferSwapping) if (_outputOptions.EnableInitialBufferSwapping)
{ {
//Go trough two cycles of buffer swapping (there are render artifacts otherwise) //Go through two cycles of buffer swapping (there are render artifacts otherwise)
for (var c = 0; c < 2; c++) for (var c = 0; c < 2; c++)
using (CreateGlRenderTarget().BeginDraw()) using (CreateGlRenderTarget().BeginDraw())
{ {
@ -330,7 +337,7 @@ namespace Avalonia.LinuxFramebuffer.Output
public double Scaling => _parent.Scaling; public double Scaling => _parent.Scaling;
public bool IsYFlipped { get; } public bool IsYFlipped => false;
} }
public IGlPlatformSurfaceRenderingSession BeginDraw() public IGlPlatformSurfaceRenderingSession BeginDraw()

4
src/Linux/Avalonia.LinuxFramebuffer/Output/FbDevBackBuffer.cs

@ -1,6 +1,4 @@
#nullable enable using System;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using Avalonia.Logging; using Avalonia.Logging;

2
src/Linux/Avalonia.LinuxFramebuffer/Output/FbDevOutputOptions.cs

@ -1,5 +1,3 @@
#nullable enable
using Avalonia.Platform; using Avalonia.Platform;
namespace Avalonia.LinuxFramebuffer.Output; namespace Avalonia.LinuxFramebuffer.Output;

8
src/Linux/Avalonia.LinuxFramebuffer/Output/FbdevOutput.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using Avalonia.Controls.Platform.Surfaces; using Avalonia.Controls.Platform.Surfaces;
@ -14,7 +15,7 @@ namespace Avalonia.LinuxFramebuffer
private fb_var_screeninfo _varInfo; private fb_var_screeninfo _varInfo;
private IntPtr _mappedLength; private IntPtr _mappedLength;
private IntPtr _mappedAddress; private IntPtr _mappedAddress;
private FbDevBackBuffer _backBuffer; private FbDevBackBuffer? _backBuffer;
private readonly FbDevOutputOptions _options; private readonly FbDevOutputOptions _options;
private bool _lockedAtLeastOnce; private bool _lockedAtLeastOnce;
public double Scaling { get; set; } public double Scaling { get; set; }
@ -24,7 +25,7 @@ namespace Avalonia.LinuxFramebuffer
/// </summary> /// </summary>
/// <param name="fileName">The frame buffer device name. /// <param name="fileName">The frame buffer device name.
/// Defaults to the value in environment variable FRAMEBUFFER or /dev/fb0 when FRAMEBUFFER is not set</param> /// Defaults to the value in environment variable FRAMEBUFFER or /dev/fb0 when FRAMEBUFFER is not set</param>
public FbdevOutput(string fileName = null) : this(fileName, null) public FbdevOutput(string? fileName = null) : this(fileName, null)
{ {
} }
@ -36,7 +37,7 @@ namespace Avalonia.LinuxFramebuffer
/// <param name="format">The required pixel format for the frame buffer. /// <param name="format">The required pixel format for the frame buffer.
/// A null value will leave the frame buffer in the current pixel format. /// A null value will leave the frame buffer in the current pixel format.
/// Otherwise sets the frame buffer to the required format</param> /// Otherwise sets the frame buffer to the required format</param>
public FbdevOutput(string fileName, PixelFormat? format) : this(new FbDevOutputOptions() public FbdevOutput(string? fileName, PixelFormat? format) : this(new FbDevOutputOptions()
{ {
FileName = fileName, FileName = fileName,
PixelFormat = format PixelFormat = format
@ -68,6 +69,7 @@ namespace Avalonia.LinuxFramebuffer
} }
} }
[MemberNotNull(nameof(Id))]
void Init(PixelFormat? format) void Init(PixelFormat? format)
{ {
fixed (void* pnfo = &_varInfo) fixed (void* pnfo = &_varInfo)

1
src/Linux/Avalonia.LinuxFramebuffer/Output/IGlOutputBackend.cs

@ -1,4 +1,3 @@
using Avalonia.OpenGL;
using Avalonia.Platform; using Avalonia.Platform;
namespace Avalonia.LinuxFramebuffer.Output namespace Avalonia.LinuxFramebuffer.Output

Loading…
Cancel
Save