Browse Source

Merge pull request #8602 from DrWenz/feature/drmoutput-performance

Improve DRM startup time
pull/8611/head
Nikita Tsukanov 4 years ago
committed by GitHub
parent
commit
24e49d1a9c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs
  2. 2
      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. 49
      src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs

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

@ -0,0 +1,27 @@
using Avalonia.LinuxFramebuffer.Output;
using Avalonia.Media;
using JetBrains.Annotations;
namespace Avalonia.LinuxFramebuffer
{
public class DrmOutputOptions
{
/// <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);
}
}

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

@ -140,6 +140,8 @@ 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, string card = null, bool connectorsForceProbe = false, [CanBeNull] DrmOutputOptions options = null)
where T : AppBuilderBase<T>, new() => StartLinuxDirect(builder, args, new DrmOutput(card, connectorsForceProbe, options));
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);

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

@ -7,6 +7,7 @@ using Avalonia.OpenGL;
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces;
using Avalonia.Platform.Interop;
using JetBrains.Annotations;
using static Avalonia.LinuxFramebuffer.NativeUnsafeMethods;
using static Avalonia.LinuxFramebuffer.Output.LibDrm;
using static Avalonia.LinuxFramebuffer.Output.LibDrm.GbmColorFormats;
@ -15,20 +16,35 @@ namespace Avalonia.LinuxFramebuffer.Output
{
public unsafe class DrmOutput : IGlOutputBackend, IGlPlatformSurface
{
private DrmOutputOptions _outputOptions = new();
private DrmCard _card;
public PixelSize PixelSize => _mode.Resolution;
public double Scaling { get; set; }
public double Scaling
{
get => _outputOptions.Scaling;
set => _outputOptions.Scaling = value;
}
public IGlContext PrimaryContext => _deferredContext;
private EglPlatformOpenGlInterface _platformGl;
public IPlatformOpenGlInterface PlatformOpenGlInterface => _platformGl;
public DrmOutput(string path = null)
public DrmOutput(DrmCard card, DrmResources resources, DrmConnector connector, DrmModeInfo modeInfo,
DrmOutputOptions? options = null)
{
if(options != null)
_outputOptions = options;
Init(card, resources, connector, modeInfo);
}
public DrmOutput(string path = null, bool connectorsForceProbe = false, [CanBeNull] DrmOutputOptions options = null)
{
if(options != null)
_outputOptions = options;
var card = new DrmCard(path);
var resources = card.GetResources();
var resources = card.GetResources(connectorsForceProbe);
var connector =
resources.Connectors.FirstOrDefault(x => x.Connection == DrmModeConnection.DRM_MODE_CONNECTED);
@ -142,9 +158,14 @@ namespace Avalonia.LinuxFramebuffer.Output
_deferredContext = _platformGl.PrimaryEglContext;
var initialBufferSwappingColorR = _outputOptions.InitialBufferSwappingColor.R / 255.0f;
var initialBufferSwappingColorG = _outputOptions.InitialBufferSwappingColor.G / 255.0f;
var initialBufferSwappingColorB = _outputOptions.InitialBufferSwappingColor.B / 255.0f;
var initialBufferSwappingColorA = _outputOptions.InitialBufferSwappingColor.A / 255.0f;
using (_deferredContext.MakeCurrent(_eglSurface))
{
_deferredContext.GlInterface.ClearColor(0, 0, 0, 0);
_deferredContext.GlInterface.ClearColor(initialBufferSwappingColorR, initialBufferSwappingColorG,
initialBufferSwappingColorB, initialBufferSwappingColorA);
_deferredContext.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT);
_eglSurface.SwapBuffers();
}
@ -162,13 +183,17 @@ 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 (_outputOptions.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(initialBufferSwappingColorR, initialBufferSwappingColorG,
initialBufferSwappingColorB, initialBufferSwappingColorA);
_deferredContext.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT);
}
}
}

Loading…
Cancel
Save