Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds a pixel format parameter to Linux frame buffer platform setup. #6101

Merged
merged 4 commits into from
Jun 21, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ public void Shutdown(int exitCode)

public static class LinuxFramebufferPlatformExtensions
{
public static int StartLinuxFbDev<T>(this T builder, string[] args, string fbdev = null, double scaling = 1)
public static int StartLinuxFbDev<T>(this T builder, string[] args, PixelFormat? format = null, string fbdev = null, double scaling = 1)
where T : AppBuilderBase<T>, new() =>
StartLinuxDirect(builder, args, new FbdevOutput(fbdev) {Scaling = scaling});
StartLinuxDirect(builder, args, new FbdevOutput(format: format, fileName: fbdev) { Scaling = scaling });

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});
Expand Down
2 changes: 1 addition & 1 deletion src/Linux/Avalonia.LinuxFramebuffer/LockedFramebuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ public void Dispose()
public PixelSize Size => new PixelSize((int)_varInfo.xres, (int) _varInfo.yres);
public int RowBytes => (int) _fixedInfo.line_length;
public Vector Dpi { get; }
public PixelFormat Format => _varInfo.blue.offset == 16 ? PixelFormat.Rgba8888 : PixelFormat.Bgra8888;
public PixelFormat Format => _varInfo.bits_per_pixel == 16 ? PixelFormat.Rgb565 : _varInfo.blue.offset == 16 ? PixelFormat.Rgba8888 : PixelFormat.Bgra8888;
}
}
90 changes: 63 additions & 27 deletions src/Linux/Avalonia.LinuxFramebuffer/Output/FbdevOutput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,23 @@ public sealed unsafe class FbdevOutput : IFramebufferPlatformSurface, IDisposabl
private IntPtr _mappedAddress;
public double Scaling { get; set; }

public FbdevOutput(string fileName = null)
/// <summary>
/// Create a Linux frame buffer device output
/// </summary>
/// <param name="format">The required pixel format for the frame buffer.
/// A null value will leave the frame buffer in the current pixel format.
/// Otherwise sets the frame buffer to the required format</param>
/// <param name="fileName">the frame buffer device name</param>
public FbdevOutput(PixelFormat? format = null, string fileName = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep the original constructor so it could be merged to 0.10.x. Also it's probably better to have configuration options after the file name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, will do

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

{
fileName = fileName ?? Environment.GetEnvironmentVariable("FRAMEBUFFER") ?? "/dev/fb0";
fileName ??= Environment.GetEnvironmentVariable("FRAMEBUFFER") ?? "/dev/fb0";
_fd = NativeUnsafeMethods.open(fileName, 2, 0);
if (_fd <= 0)
throw new Exception("Error: " + Marshal.GetLastWin32Error());

try
{
Init();
Init(format);
}
catch
{
Expand All @@ -34,25 +41,28 @@ public FbdevOutput(string fileName = null)
}
}

void Init()
void Init(PixelFormat? format)
{
fixed (void* pnfo = &_varInfo)
{
if (-1 == NativeUnsafeMethods.ioctl(_fd, FbIoCtl.FBIOGET_VSCREENINFO, pnfo))
throw new Exception("FBIOGET_VSCREENINFO error: " + Marshal.GetLastWin32Error());

SetBpp();
if (format.HasValue)
{
SetBpp(format.Value);

if (-1 == NativeUnsafeMethods.ioctl(_fd, FbIoCtl.FBIOPUT_VSCREENINFO, pnfo))
_varInfo.transp = new fb_bitfield();
if (-1 == NativeUnsafeMethods.ioctl(_fd, FbIoCtl.FBIOPUT_VSCREENINFO, pnfo))
_varInfo.transp = new fb_bitfield();

NativeUnsafeMethods.ioctl(_fd, FbIoCtl.FBIOPUT_VSCREENINFO, pnfo);
NativeUnsafeMethods.ioctl(_fd, FbIoCtl.FBIOPUT_VSCREENINFO, pnfo);

if (-1 == NativeUnsafeMethods.ioctl(_fd, FbIoCtl.FBIOGET_VSCREENINFO, pnfo))
throw new Exception("FBIOGET_VSCREENINFO error: " + Marshal.GetLastWin32Error());
if (-1 == NativeUnsafeMethods.ioctl(_fd, FbIoCtl.FBIOGET_VSCREENINFO, pnfo))
throw new Exception("FBIOGET_VSCREENINFO error: " + Marshal.GetLastWin32Error());

if (_varInfo.bits_per_pixel != 32)
throw new Exception("Unable to set 32-bit display mode");
if (_varInfo.bits_per_pixel != 32)
throw new Exception("Unable to set 32-bit display mode");
}
}
fixed(void*pnfo = &_fixedInfo)
if (-1 == NativeUnsafeMethods.ioctl(_fd, FbIoCtl.FBIOGET_FSCREENINFO, pnfo))
Expand All @@ -70,17 +80,43 @@ void Init()
}
}

void SetBpp()
void SetBpp(PixelFormat format)
{
_varInfo.bits_per_pixel = 32;
_varInfo.grayscale = 0;
_varInfo.red = _varInfo.blue = _varInfo.green = _varInfo.transp = new fb_bitfield
switch (format)
{
length = 8
};
_varInfo.green.offset = 8;
_varInfo.blue.offset = 16;
_varInfo.transp.offset = 24;
case PixelFormat.Rgba8888:
_varInfo.bits_per_pixel = 32;
_varInfo.grayscale = 0;
_varInfo.red = _varInfo.blue = _varInfo.green = _varInfo.transp = new fb_bitfield
{
length = 8
};
_varInfo.green.offset = 8;
_varInfo.blue.offset = 16;
_varInfo.transp.offset = 24;
break;
case PixelFormat.Bgra8888:
_varInfo.bits_per_pixel = 32;
_varInfo.grayscale = 0;
_varInfo.red = _varInfo.blue = _varInfo.green = _varInfo.transp = new fb_bitfield
{
length = 8
};
_varInfo.green.offset = 8;
_varInfo.red.offset = 16;
_varInfo.transp.offset = 24;
break;
case PixelFormat.Rgb565:
_varInfo.bits_per_pixel = 16;
_varInfo.grayscale = 0;
_varInfo.red = _varInfo.blue = _varInfo.green = _varInfo.transp = new fb_bitfield();
_varInfo.red.length = 5;
_varInfo.green.offset = 5;
_varInfo.green.length = 6;
_varInfo.blue.offset = 11;
_varInfo.blue.length = 5;
break;
}
}

public string Id { get; private set; }
Expand All @@ -90,17 +126,17 @@ public PixelSize PixelSize
get
{
fb_var_screeninfo nfo;
if (-1 == NativeUnsafeMethods.ioctl(_fd, FbIoCtl.FBIOGET_VSCREENINFO, &nfo))
aguahombre marked this conversation as resolved.
Show resolved Hide resolved
throw new Exception("FBIOGET_VSCREENINFO error: " + Marshal.GetLastWin32Error());
return new PixelSize((int)nfo.xres, (int)nfo.yres);
return (-1 == NativeUnsafeMethods.ioctl(_fd, FbIoCtl.FBIOGET_VSCREENINFO, &nfo))
? throw new Exception("FBIOGET_VSCREENINFO error: " + Marshal.GetLastWin32Error())
: new PixelSize((int)nfo.xres, (int)nfo.yres);
}
}

public ILockedFramebuffer Lock()
{
if (_fd <= 0)
throw new ObjectDisposedException("LinuxFramebuffer");
return new LockedFramebuffer(_fd, _fixedInfo, _varInfo, _mappedAddress, new Vector(96, 96) * Scaling);
return _fd <= 0
? throw new ObjectDisposedException("LinuxFramebuffer")
: new LockedFramebuffer(_fd, _fixedInfo, _varInfo, _mappedAddress, new Vector(96, 96) * Scaling);
}


Expand Down