Browse Source

Added drmModeGetConnectorCurrent, added new StartLinuxDrm with LinuxDrmOptions

pull/8602/head
Markus Wenzl 4 years ago
parent
commit
6b1de285ba
  1. 46
      src/Linux/Avalonia.LinuxFramebuffer/LinuxDrmOptions.cs
  2. 8
      src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
  3. 2
      src/Linux/Avalonia.LinuxFramebuffer/Output/Drm.cs
  4. 6
      src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs
  5. 45
      src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs

46
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
{
/// <summary>
/// Path for DrmCard to use, if no <see cref="OutputBackend"/> is passed.
/// Default: null
/// </summary>
[CanBeNull] public string Card { get; set; }
/// <summary>
/// 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
/// </summary>
public bool DrmConnectorsForceProbe { get; set; } = false;
/// <summary>
/// Scaling factor.
/// Default: 1.0
/// </summary>
public double Scaling { get; set; } = 1.0;
/// <summary>
/// If true an two cycle buffer swapping is processed at init.
/// Default: True
/// </summary>
public bool EnableInitialBufferSwapping { get; set; } = true;
/// <summary>
/// Color for <see cref="EnableInitialBufferSwapping"/>
/// Default: R0 G0 B0 A0
/// </summary>
public Color InitialBufferSwappingColor { get; set; } = new Color(0, 0, 0, 0);
/// <summary>
/// IOutputBackend. If Null, a new DrmOutput for <see cref="Card"/> with <see cref="Scaling"/> will be created.
/// Default: null
/// </summary>
[CanBeNull] public IOutputBackend OutputBackend { get; set; }
}
}

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

@ -140,6 +140,14 @@ public static class LinuxFramebufferPlatformExtensions
public static int StartLinuxDrm<T>(this T builder, string[] args, string card = null, double scaling = 1)
where T : AppBuilderBase<T>, new() => StartLinuxDirect(builder, args, new DrmOutput(card) {Scaling = scaling});
public static int StartLinuxDrm<T>(this T builder, string[] args, [CanBeNull] LinuxDrmOptions drmOptions)
where T : AppBuilderBase<T>, new()
{
drmOptions ??= new LinuxDrmOptions();
drmOptions.OutputBackend ??= new DrmOutput(drmOptions) {Scaling = drmOptions.Scaling};
return StartLinuxDirect(builder, args, drmOptions.OutputBackend);
}
public static int StartLinuxDirect<T>(this T builder, string[] args, IOutputBackend backend)
where T : AppBuilderBase<T>, new()

2
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)]

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

@ -84,7 +84,7 @@ namespace Avalonia.LinuxFramebuffer.Output
{
public List<DrmConnector> Connectors { get; }= new List<DrmConnector>();
internal Dictionary<uint, DrmEncoder> Encoders { get; } = new Dictionary<uint, DrmEncoder>();
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);

45
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);
}
}
}

Loading…
Cancel
Save