XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Numerics;

namespace XFESystem.NativeRuntime.ConsoleApplication;

public readonly record struct ConsoleFramebufferSurface(nuint Address, nuint MappedBytes, int Width, int Height,
    int PitchBytes, int BitsPerPixel, uint RedMask, uint GreenMask, uint BlueMask);

public interface IConsoleFramebuffer
{
    int Width { get; }
    int Height { get; }
    void Present(ReadOnlySpan<int> pixels);
}

/// <summary>Console scanout uses only the kernel-provided mapping; it never creates a desktop or a host window.</summary>
public sealed unsafe class ConsoleMemoryFramebuffer : IConsoleFramebuffer
{
    private readonly ConsoleFramebufferSurface surface;
    private readonly int bytesPerPixel;
    private Action? beforeFirstPresent;
    public int Width => surface.Width;
    public int Height => surface.Height;

    public ConsoleMemoryFramebuffer(ConsoleFramebufferSurface surface, Action? beforeFirstPresent = null)
    {
        if (surface.Address == 0 || surface.Width is < 320 or > 16384 || surface.Height is < 240 or > 16384 ||
            (long)surface.Width * surface.Height > 33_554_432 || surface.BitsPerPixel is not (16 or 24 or 32))
            throw new ArgumentException("A bounded mapped framebuffer is required.", nameof(surface));
        bytesPerPixel = surface.BitsPerPixel / 8;
        ulong required = checked((ulong)(surface.Height - 1) * (uint)surface.PitchBytes + (ulong)surface.Width * (uint)bytesPerPixel);
        if (surface.PitchBytes < (long)surface.Width * bytesPerPixel || required > surface.MappedBytes ||
            required > nuint.MaxValue - surface.Address || !ValidMask(surface.RedMask, surface.BitsPerPixel) ||
            !ValidMask(surface.GreenMask, surface.BitsPerPixel) || !ValidMask(surface.BlueMask, surface.BitsPerPixel) ||
            (surface.RedMask & surface.GreenMask) != 0 || (surface.RedMask & surface.BlueMask) != 0 || (surface.GreenMask & surface.BlueMask) != 0)
            throw new ArgumentException("Framebuffer extent, pitch or masks are invalid.", nameof(surface));
        this.surface = surface;
        this.beforeFirstPresent = beforeFirstPresent;
    }

    public void Present(ReadOnlySpan<int> pixels)
    {
        if (pixels.Length != (long)Width * Height) throw new ArgumentException("Incomplete console frame.", nameof(pixels));
        beforeFirstPresent?.Invoke(); beforeFirstPresent = null;
        // Common UEFI/QEMU RGB32 case: row copies retain firmware pitch padding.
        if (bytesPerPixel == 4 && surface.RedMask == 0xFF0000 && surface.GreenMask == 0xFF00 && surface.BlueMask == 0xFF)
        {
            for (int y = 0; y < Height; y++)
                pixels.Slice(y * Width, Width).CopyTo(new Span<int>((void*)(surface.Address + (nuint)y * (nuint)surface.PitchBytes), Width));
            return;
        }
        for (int y = 0; y < Height; y++)
        {
            byte* output = (byte*)surface.Address + (nuint)y * (nuint)surface.PitchBytes;
            for (int x = 0; x < Width; x++)
            {
                uint rgb = unchecked((uint)pixels[y * Width + x]);
                uint packed = Channel((byte)(rgb >> 16), surface.RedMask) | Channel((byte)(rgb >> 8), surface.GreenMask) | Channel((byte)rgb, surface.BlueMask);
                for (int index = 0; index < bytesPerPixel; index++) *output++ = (byte)(packed >> (index * 8));
            }
        }
    }
    private static bool ValidMask(uint mask, int bits)
    {
        if (mask == 0 || bits < 32 && mask >> bits != 0) return false;
        uint range = mask >> BitOperations.TrailingZeroCount(mask);
        return (range & (range + 1)) == 0;
    }
    private static uint Channel(byte value, uint mask)
    {
        int shift = BitOperations.TrailingZeroCount(mask);
        return (uint)(((ulong)value * (mask >> shift) + 127) / 255) << shift;
    }
}