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

XFESystem

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

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

namespace XFESystem.Desktop;

/// <summary>Optional readback of the real presented framebuffer, in native pixels.</summary>
public interface IDesktopPresentedPixelsCanvas
{
    long FramesPresented { get; }
    long LastPresentTicks => 0;
    bool TryFingerprintPresentedPixels(DesktopBounds nativeBounds, out DesktopPresentedPixelsFingerprint result);
}

public readonly record struct DesktopPresentedPixelsFingerprint(DesktopBounds NativeBounds, long PresentationSequence, string Fingerprint);

/// <summary>Bounded diagnostic fingerprint; never a substitute for GPU or screenshot evidence.</summary>
public static class DesktopPresentedPixels
{
    public const int MaximumFingerprintPixels = 262_144;
    public const string FingerprintAlgorithm = "RGB24-FNV1a64";

    public static bool TryFingerprint(ReadOnlySpan<int> framebuffer, int width, int height, int stride,
        DesktopBounds bounds, long presentationSequence, out DesktopPresentedPixelsFingerprint result)
    {
        result = default;
        if (presentationSequence <= 0 || width <= 0 || height <= 0 || stride < width || bounds.X < 0 || bounds.Y < 0 ||
            bounds.Width <= 0 || bounds.Height <= 0 || (long)bounds.X + bounds.Width > width || (long)bounds.Y + bounds.Height > height ||
            (long)bounds.Width * bounds.Height > MaximumFingerprintPixels || (long)(height - 1) * stride + width > framebuffer.Length)
            return false;
        ulong hash = 14695981039346656037;
        for (int y = bounds.Y; y < bounds.Y + bounds.Height; y++)
            for (int x = bounds.X; x < bounds.X + bounds.Width; x++)
            {
                uint pixel = unchecked((uint)framebuffer[y * stride + x]);
                hash = unchecked((hash ^ (byte)(pixel >> 16)) * 1099511628211);
                hash = unchecked((hash ^ (byte)(pixel >> 8)) * 1099511628211);
                hash = unchecked((hash ^ (byte)pixel) * 1099511628211);
            }
        result = new(bounds, presentationSequence, hash.ToString("x16", CultureInfo.InvariantCulture));
        return true;
    }
}