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

XFESystem

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

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

namespace XFESystem.NativeKernel;

/// <summary>Independent scanouts supplied by Limine, not inferred from GPU connector counts.</summary>
public static unsafe class DisplayHardware
{
    const uint Limit = 8;
    static NativeFrameSurface* _surfaces;
    static ulong* _identities;
    public static uint Count;

    public static bool Valid(LimineFramebuffer* source)
    {
        if (source == null || source->Address == null || source->MemoryModel != 1 || source->BitsPerPixel != 32 ||
            source->Width < 320 || source->Height < 200 || source->Width > 16384 || source->Height > 16384 ||
            source->Width * source->Height > 33554432 || source->Pitch < source->Width * 4 ||
            source->Pitch > 1024 * 1024 || (source->Pitch & 3) != 0 ||
            (ulong)source->Address > ~0UL - source->Pitch * source->Height ||
            source->RedSize != 8 || source->GreenSize != 8 || source->BlueSize != 8 ||
            source->RedShift > 24 || source->GreenShift > 24 || source->BlueShift > 24) return false;
        uint r = 255u << source->RedShift, g = 255u << source->GreenShift, b = 255u << source->BlueShift;
        return (r & g) == 0 && (r & b) == 0 && (g & b) == 0;
    }

    public static void Initialize(NativeBootInfo* boot)
    {
        Count = 0;
        ulong physical = PhysicalMemory.Allocate();
        if (physical == 0 || boot == null) return;
        _surfaces = (NativeFrameSurface*)PhysicalMemory.ToVirtual(physical);
        _identities = (ulong*)((byte*)_surfaces + Limit * sizeof(NativeFrameSurface));
        ulong available = boot->Framebuffers != null && boot->FramebufferCount <= 32 ? boot->FramebufferCount : 0;
        if (available == 0) available = 1;
        for (uint index = 0; index < available && Count < Limit; index++)
        {
            LimineFramebuffer* source = boot->Framebuffers == null ? boot->Framebuffer : boot->Framebuffers[index];
            if (!Valid(source)) continue;
            ulong address = (ulong)source->Address, bytes = source->Pitch * source->Height;
            bool overlaps = false;
            for (uint previous = 0; previous < Count; previous++)
                if (address < _surfaces[previous].Address + _surfaces[previous].MappedBytes &&
                    _surfaces[previous].Address < address + bytes) overlaps = true;
            // Aliased firmware handles are one output, never two independent monitors.
            if (overlaps) continue;
            NativeFrameSurface* target = _surfaces + Count;
            target->Address = address; target->MappedBytes = bytes;
            target->Width = (uint)source->Width; target->Height = (uint)source->Height;
            target->PitchBytes = (uint)source->Pitch; target->BitsPerPixel = source->BitsPerPixel;
            target->RedMaskSize = source->RedSize; target->RedMaskShift = source->RedShift;
            target->GreenMaskSize = source->GreenSize; target->GreenMaskShift = source->GreenShift;
            target->BlueMaskSize = source->BlueSize; target->BlueMaskShift = source->BlueShift;
            // No physical address is persisted: EDID plus enumeration slot identifies
            // a boot output. Without EDID, a changed geometry invalidates saved settings.
            ulong identity = 14695981039346656037UL;
            if (source->Edid != null && source->EdidBytes >= 128 && source->EdidBytes <= 4096)
                for (uint i = 0; i < source->EdidBytes; i++) identity = (identity ^ source->Edid[i]) * 1099511628211UL;
            identity = (identity ^ index) * 1099511628211UL;
            identity = (identity ^ source->Width) * 1099511628211UL;
            _identities[Count] = (identity ^ source->Height) * 1099511628211UL;
            // Secondary outputs remain black while the primary runs the branded splash.
            if (source != boot->Framebuffer)
                for (ulong y = 0; y < source->Height; y++)
                    for (ulong x = 0; x < source->Width; x++) *(uint*)(source->Address + y * source->Pitch + x * 4) = 0;
            Serial.Write("XFE_DISPLAY_OUTPUT|Index|"); Serial.Number(Count);
            Serial.Write("|Width|"); Serial.Number(source->Width); Serial.Write("|Height|"); Serial.Number(source->Height);
            Serial.Write("|Identity|"); Serial.Hex(_identities[Count]); Serial.Line("|Backend|LimineFramebuffer");
            Count++;
        }
        Serial.Write("XFE_DISPLAY_OUTPUTS|Count|"); Serial.Number(Count); Serial.Line("|Hotplug|0|Modeset|0");
    }

    [UnmanagedCallersOnly(EntryPoint = "xfe_runtime_display_count")]
    public static uint ReadCount() => Count;

    [UnmanagedCallersOnly(EntryPoint = "xfe_runtime_display_copy32")]
    public static int Copy32(uint index, uint* source, ulong sourcePixels, uint sourceWidth, uint sourceHeight,
        uint x, uint y, uint width, uint height)
    {
        if (index >= Count || source == null || sourceWidth == 0 || sourceHeight == 0 ||
            (ulong)sourceWidth * sourceHeight > sourcePixels || sourceWidth > 16384 || sourceHeight > 16384) return -1;
        NativeFrameSurface* surface = _surfaces + index;
        if (sourceWidth != surface->Width || sourceHeight != surface->Height ||
            x > sourceWidth || y > sourceHeight || width > sourceWidth - x || height > sourceHeight - y) return -1;
        if (surface->BitsPerPixel != 32 || surface->RedMaskSize != 8 || surface->GreenMaskSize != 8 || surface->BlueMaskSize != 8 ||
            surface->GreenMaskShift != 8 || !((surface->RedMaskShift == 16 && surface->BlueMaskShift == 0) ||
            (surface->RedMaskShift == 0 && surface->BlueMaskShift == 16))) return 0;
        // No source alias can be accepted: AP row ownership assumes immutable
        // input. The managed caller pins the span across the synchronous join.
        ulong start = (ulong)source, bytes = (ulong)sourceWidth * sourceHeight * 4;
        if (start > ~0UL - bytes || (start < surface->Address + surface->MappedBytes && surface->Address < start + bytes)) return -1;
        if (width == 0 || height == 0) return 1;
        uint* input = source + (ulong)y * sourceWidth + x;
        byte* output = (byte*)surface->Address + (ulong)y * surface->PitchBytes + (ulong)x * 4;
        return Multiprocessor.TryCopy(input, output, sourceWidth * 4, surface->PitchBytes, width, height,
            surface->RedMaskShift == 0 ? 1u : 0u) ? 1 : 0;
    }

    // 72 bytes: version, bytes, stable identity, existing 56-byte surface ABI.
    [UnmanagedCallersOnly(EntryPoint = "xfe_runtime_display_info")]
    public static int Read(uint index, byte* destination, uint bytes)
    {
        if (destination == null || bytes != 72 || index >= Count) return 0;
        *(uint*)destination = 1; *(uint*)(destination + 4) = 72;
        *(ulong*)(destination + 8) = _identities[index];
        *(NativeFrameSurface*)(destination + 16) = _surfaces[index];
        return 1;
    }
}