Add screen orientation support for Linux DRM (#20154)

* On Frame-Buffer-Orientation: Add screen orientation support for Linux frame buffer and DRM applications.

This commit introduces support for screen orientation across various components by adding a new `Orientation` property of type `SurfaceOrientation` in `DrmOutputOptions` and `FbDevOutputOptions`. The `IScreenInfoProvider` interface is updated to inherit from `ISurfaceOrientation`, ensuring consistent orientation management.

Key changes include:
- Enhanced `FramebufferToplevelImpl` to handle orientation in size calculations.
- Updated `LibInputBackend` for device input coordinate rotation based on screen orientation.
- Implemented `ISurfaceOrientation` in `DrmOutput` and `FbdevOutput` classes.
- Modified `DrawingContextImpl` to support canvas rotation based on orientation.
- Improved `FramebufferRenderTarget` and `PixelFormatConversionShim` to respect framebuffer orientation during surface creation and pixel format conversions.
- Streamlined rendering methods to ensure drawing operations align with the current surface orientation.
- Removed redundant code related to framebuffer handling.

* Fix review comments, add ability to test

* Some formatting

* Should be working now

* Remove fbdev changes

Theres really no point to do this in fbdev.

* Better method of rotating and transforming the canvas

* Remove breaking changes

* Switch to using a 2nd frame buffer in the rotation case

* Fix review comments

* Incorrect variable

* Fix sample

---------

Co-authored-by: davidw <davidw@icselectronics.co.uk>
This commit is contained in:
Thad House
2026-02-03 01:01:29 -08:00
committed by GitHub
parent 92190e6ee1
commit babab4f9cb
12 changed files with 276 additions and 30 deletions
+23 -9
View File
@@ -8,8 +8,10 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Headless;
using Avalonia.LinuxFramebuffer;
using Avalonia.LinuxFramebuffer.Output;
using Avalonia.LogicalTree;
using Avalonia.Platform;
using Avalonia.Rendering.Composition;
using Avalonia.Threading;
using Avalonia.Vulkan;
@@ -19,16 +21,9 @@ namespace ControlCatalog.Desktop
{
static class Program
{
private static bool s_useFramebuffer;
[STAThread]
static int Main(string[] args)
{
if (args.Contains("--fbdev"))
{
s_useFramebuffer = true;
}
if (args.Contains("--wait-for-attach"))
{
Console.WriteLine("Attach debugger and use 'Set next statement'");
@@ -50,7 +45,22 @@ namespace ControlCatalog.Desktop
return scaling;
return 1;
}
if (s_useFramebuffer)
SurfaceOrientation GetOrientation()
{
var idx = Array.IndexOf(args, "--orientation");
if (idx >= 0 && args.Length > idx + 1 &&
Enum.TryParse<SurfaceOrientation>(args[idx + 1], true, out var orientation))
return orientation;
return SurfaceOrientation.Rotation0;
}
string? GetCard()
{
var idx = Array.IndexOf(args, "--card");
if (idx >= 0 && args.Length > idx + 1)
return args[idx + 1];
return null;
}
if (args.Contains("--fbdev"))
{
SilenceConsole();
return builder.StartLinuxFbDev(args, new FbDevOutputOptions()
@@ -108,7 +118,11 @@ namespace ControlCatalog.Desktop
else if (args.Contains("--drm"))
{
SilenceConsole();
return builder.StartLinuxDrm(args, scaling: GetScaling());
return builder.StartLinuxDrm(args, card: GetCard(), options: new DrmOutputOptions()
{
Scaling = GetScaling(),
Orientation = GetOrientation(),
});
}
else if (args.Contains("--dxgi"))
{