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

XFESystem

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

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

namespace XFESystem.NativeKernel;

/// <summary>A native scheduler worker owns scanout until the application's first complete frame is ready.</summary>
public static unsafe class BootSplash
{
    // Zero deliberately omits IsVolatile. Explicit unmanaged memory barriers
    // make each scheduler boundary reload these single-BSP handoff flags.
    private static bool _active, _ready, _finished, _failed;
    private static ulong _started, _frames;
    private static uint* _backbuffer;
    private static ulong _bufferBytes;
    public static bool Active => _active;

    public static bool Start()
    {
        if (!Framebuffer.Ready || !Threads.Ready || !MonotonicClock.Ready || _active) return false;
        _bufferBytes = ((ulong)Framebuffer.Width * Framebuffer.Height * 4 + 4095) & ~4095UL;
        ulong flags = Native.IrqSave();
        _backbuffer = (uint*)VirtualMemory.Reserve(_bufferBytes, 4096);
        bool allocated = _backbuffer != null && VirtualMemory.Commit((ulong)_backbuffer, _bufferBytes);
        if (!allocated && _backbuffer != null) VirtualMemory.Release((ulong)_backbuffer, _bufferBytes);
        Native.IrqRestore(flags);
        if (!allocated) { _backbuffer = null; return false; }
        for (ulong i = 0; i < (ulong)Framebuffer.Width * Framebuffer.Height; i++) _backbuffer[i] = 0;
        _ready = _finished = _failed = false; _frames = 0;
        _started = MonotonicClock.Nanoseconds(); _active = true;
        Serial.Line("XFE_BOOT_VISUAL_START|IntroMs|2400|Text|XFESystem|NativeWorker|1");
        if (Threads.Create(&Run, null, 65536, 0, false) != 0) return true;
        ReleaseBuffer(); _active = false; return false;
    }

    [UnmanagedCallersOnly(EntryPoint = "xfe_boot_visual_worker")]
    public static uint Run(void* argument)
    {
        bool introReported = false, waitingReported = false;
        for (;;)
        {
            Native.MemoryBarrier();
            if (_failed) break;
            ulong elapsed = (MonotonicClock.Nanoseconds() - _started) / 1000000;
            if (elapsed >= BootVisual.IntroMilliseconds && !introReported)
            { introReported = true; Serial.Line("XFE_BOOT_VISUAL_INTRO_COMPLETE"); }
            if (BootVisual.ShouldRelease(elapsed, _ready))
            {
                Serial.Write("XFE_BOOT_VISUAL_RELEASED|ElapsedMs|"); Serial.Number(elapsed);
                Serial.Write("|Frames|"); Serial.Number(_frames);
                Serial.Write("|LoadingShown|"); Serial.Number(waitingReported ? 1UL : 0UL); Serial.Line("");
                _active = false; ReleaseBuffer(); Native.MemoryBarrier(); _finished = true;
                return 0;
            }
            bool waiting = BootVisual.IsWaiting(elapsed, _ready);
            if (waiting && !waitingReported)
            { waitingReported = true; Serial.Line("XFE_BOOT_VISUAL_WAITING"); }
            Framebuffer.PaintBoot(_backbuffer, elapsed, waiting);
            _frames++;
            Threads.Sleep(16);
        }
        _active = false; ReleaseBuffer(); _finished = true;
        return 1;
    }

    [UnmanagedCallersOnly(EntryPoint = "xfe_runtime_boot_complete")]
    public static int Complete()
    {
        if (!_active && !_finished || _failed) return 0;
        Serial.Line("XFE_BOOT_VISUAL_APPLICATION_FRAME_READY");
        _ready = true; Native.MemoryBarrier();
        // Main has already prepared its first frame. The boot worker finishes
        // the intro or stops its loader before this caller can touch scanout.
        for (;;)
        {
            Native.MemoryBarrier();
            if (_finished || _failed) break;
            Threads.Sleep(1);
        }
        return _failed ? 0 : 1;
    }

    public static void Blackout()
    {
        _failed = true;
        Framebuffer.Fill(0);
        Native.MemoryBarrier();
    }
    private static void ReleaseBuffer()
    {
        ulong flags = Native.IrqSave();
        if (_backbuffer != null) VirtualMemory.Release((ulong)_backbuffer, _bufferBytes);
        _backbuffer = null; _bufferBytes = 0;
        Native.IrqRestore(flags);
    }
}