diff --git a/src/Linux/Avalonia.LinuxFramebuffer/LinuxDrmOptions.cs b/src/Linux/Avalonia.LinuxFramebuffer/LinuxDrmOptions.cs
new file mode 100644
index 0000000000..a67d6f7d8b
--- /dev/null
+++ b/src/Linux/Avalonia.LinuxFramebuffer/LinuxDrmOptions.cs
@@ -0,0 +1,46 @@
+using Avalonia.LinuxFramebuffer.Output;
+using Avalonia.Media;
+using JetBrains.Annotations;
+
+namespace Avalonia.LinuxFramebuffer
+{
+ public class LinuxDrmOptions
+ {
+ ///
+ /// Path for DrmCard to use, if no is passed.
+ /// Default: null
+ ///
+ [CanBeNull] public string Card { get; set; }
+
+ ///
+ /// True to call drmModeGetConnector for all available connectors, otherwise drmModeGetConnectorCurrent is called to get the kernel-cached connected connector.
+ /// Info: since some hardware might have incorrect connector information on startup for some reason, you may need to set this parameter to true.
+ /// Default: False
+ ///
+ public bool DrmConnectorsForceProbe { get; set; } = false;
+
+ ///
+ /// Scaling factor.
+ /// Default: 1.0
+ ///
+ public double Scaling { get; set; } = 1.0;
+
+ ///
+ /// If true an two cycle buffer swapping is processed at init.
+ /// Default: True
+ ///
+ public bool EnableInitialBufferSwapping { get; set; } = true;
+
+ ///
+ /// Color for
+ /// Default: R0 G0 B0 A0
+ ///
+ public Color InitialBufferSwappingColor { get; set; } = new Color(0, 0, 0, 0);
+
+ ///
+ /// IOutputBackend. If Null, a new DrmOutput for with will be created.
+ /// Default: null
+ ///
+ [CanBeNull] public IOutputBackend OutputBackend { get; set; }
+ }
+}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs b/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
index 4add4c423b..bf29aed1a4 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
@@ -140,6 +140,14 @@ public static class LinuxFramebufferPlatformExtensions
public static int StartLinuxDrm(this T builder, string[] args, string card = null, double scaling = 1)
where T : AppBuilderBase, new() => StartLinuxDirect(builder, args, new DrmOutput(card) {Scaling = scaling});
+
+ public static int StartLinuxDrm(this T builder, string[] args, [CanBeNull] LinuxDrmOptions drmOptions)
+ where T : AppBuilderBase, new()
+ {
+ drmOptions ??= new LinuxDrmOptions();
+ drmOptions.OutputBackend ??= new DrmOutput(drmOptions) {Scaling = drmOptions.Scaling};
+ return StartLinuxDirect(builder, args, drmOptions.OutputBackend);
+ }
public static int StartLinuxDirect(this T builder, string[] args, IOutputBackend backend)
where T : AppBuilderBase, new()
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs
index 9c476b1b63..04bc2c1f67 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs
@@ -162,6 +162,8 @@ namespace Avalonia.LinuxFramebuffer.Output
[DllImport(libdrm, SetLastError = true)]
public static extern drmModeConnector* drmModeGetConnector(int fd, uint connector);
[DllImport(libdrm, SetLastError = true)]
+ public static extern drmModeConnector* drmModeGetConnectorCurrent(int fd, uint connector);
+ [DllImport(libdrm, SetLastError = true)]
public static extern void drmModeFreeConnector(drmModeConnector* res);
[DllImport(libdrm, SetLastError = true)]
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs
index de281245f1..070e1a95bc 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs
@@ -84,7 +84,7 @@ namespace Avalonia.LinuxFramebuffer.Output
{
public List Connectors { get; }= new List();
internal Dictionary Encoders { get; } = new Dictionary();
- public DrmResources(int fd)
+ public DrmResources(int fd, bool connectorsForceProbe = false)
{
var res = drmModeGetResources(fd);
if (res == null)
@@ -107,7 +107,7 @@ namespace Avalonia.LinuxFramebuffer.Output
for (var c = 0; c < res->count_connectors; c++)
{
- var conn = drmModeGetConnector(fd, res->connectors[c]);
+ var conn = connectorsForceProbe ? drmModeGetConnector(fd, res->connectors[c]) : drmModeGetConnectorCurrent(fd, res->connectors[c]);
Connectors.Add(new DrmConnector(conn));
drmModeFreeConnector(conn);
}
@@ -168,7 +168,7 @@ namespace Avalonia.LinuxFramebuffer.Output
}
}
- public DrmResources GetResources() => new DrmResources(Fd);
+ public DrmResources GetResources(bool connectorsForceProbe = false) => new DrmResources(Fd, connectorsForceProbe);
public void Dispose()
{
close(Fd);
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
index 99c4b62716..85cf1fba76 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
@@ -15,20 +15,34 @@ namespace Avalonia.LinuxFramebuffer.Output
{
public unsafe class DrmOutput : IGlOutputBackend, IGlPlatformSurface
{
+ private LinuxDrmOptions _options;
private DrmCard _card;
public PixelSize PixelSize => _mode.Resolution;
- public double Scaling { get; set; }
+
+ public double Scaling
+ {
+ get => _options.Scaling;
+ set => _options.Scaling = value;
+ }
public IGlContext PrimaryContext => _deferredContext;
private EglPlatformOpenGlInterface _platformGl;
public IPlatformOpenGlInterface PlatformOpenGlInterface => _platformGl;
- public DrmOutput(string path = null)
+ public DrmOutput(LinuxDrmOptions drmOptions)
{
- var card = new DrmCard(path);
+ _options = drmOptions;
+ CreateDrmOutput(_options.Card, _options.DrmConnectorsForceProbe);
+ }
+ public DrmOutput(string path = null) : this(new LinuxDrmOptions() { Card = path })
+ {
+ }
- var resources = card.GetResources();
+ private void CreateDrmOutput(string path = null, bool connectorsForceProbe = false)
+ {
+ var card = new DrmCard(path);
+ var resources = card.GetResources(connectorsForceProbe);
var connector =
resources.Connectors.FirstOrDefault(x => x.Connection == DrmModeConnection.DRM_MODE_CONNECTED);
@@ -144,7 +158,9 @@ namespace Avalonia.LinuxFramebuffer.Output
using (_deferredContext.MakeCurrent(_eglSurface))
{
- _deferredContext.GlInterface.ClearColor(0, 0, 0, 0);
+ _deferredContext.GlInterface.ClearColor(_options.InitialBufferSwappingColor.R,
+ _options.InitialBufferSwappingColor.G, _options.InitialBufferSwappingColor.B,
+ _options.InitialBufferSwappingColor.A);
_deferredContext.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT);
_eglSurface.SwapBuffers();
}
@@ -162,13 +178,18 @@ namespace Avalonia.LinuxFramebuffer.Output
_mode = mode;
_currentBo = bo;
- // Go trough two cycles of buffer swapping (there are render artifacts otherwise)
- for(var c=0;c<2;c++)
- using (CreateGlRenderTarget().BeginDraw())
- {
- _deferredContext.GlInterface.ClearColor(0, 0, 0, 0);
- _deferredContext.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT);
- }
+ if (_options.EnableInitialBufferSwapping)
+ {
+ //Go trough two cycles of buffer swapping (there are render artifacts otherwise)
+ for(var c=0;c<2;c++)
+ using (CreateGlRenderTarget().BeginDraw())
+ {
+ _deferredContext.GlInterface.ClearColor(_options.InitialBufferSwappingColor.R,
+ _options.InitialBufferSwappingColor.G, _options.InitialBufferSwappingColor.B,
+ _options.InitialBufferSwappingColor.A);
+ _deferredContext.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT);
+ }
+ }
}