BizHawk/ExternalToolProjects/FakeTemporalAA/FakeTemporalAAToolForm.cs

84 lines
2.5 KiB
C#

namespace BizHawk.Experiments.FakeTemporalAA;
using System;
using BizHawk.Bizware.Graphics;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk;
using BizHawk.Emulation.Common;
[ExternalTool(TOOL_NAME, Description = "Naively blends each frame with the previous")]
public sealed class FakeTemporalAAToolForm: ToolFormBase, IExternalToolForm
{
private const string TOOL_NAME = "Fake Temporal Anti-aliasing";
private BitmapBuffer? _bbPrev = null;
[RequiredService]
public IVideoProvider? _maybeVideoProvider { get; set; }
public ApiContainer? _maybeAPIContainer { get; set; }
private ApiContainer APIs
=> _maybeAPIContainer!;
protected override string WindowTitleStatic
=> TOOL_NAME;
public FakeTemporalAAToolForm()
=> _ = _maybeVideoProvider; // used via ToolFormBase.MainForm
private void ClearDrawingSurface()
=> _maybeAPIContainer?.Gui?.WithSurface(DisplaySurfaceID.EmuCore, g => g.ClearGraphics(DisplaySurfaceID.EmuCore));
protected override void Dispose(bool disposing)
{
ClearDrawingSurface();
base.Dispose(disposing);
}
public override void Restart()
{
_bbPrev = null;
ClearDrawingSurface();
}
public override void UpdateValues(ToolFormUpdateType type)
{
const int OPACITY_MASK = 0xFF << 24;
static void Invert(Span<int> buf)
{
for (var i = 0; i < buf.Length; i++) buf[i] = OPACITY_MASK | ~buf[i]; //TODO vectorise?
}
static int AverageXRGB(int c1, int c2)
{
//TODO can this be improved?
const int R_MASK = 0xFF0000;
const int G_MASK = 0xFF00;
const int B_MASK = 0xFF;
var r = (((c1 & R_MASK) + (c2 & R_MASK)) / 2) & R_MASK;
var g = (((c1 & G_MASK) + (c2 & G_MASK)) / 2) & G_MASK;
var b = (((c1 & B_MASK) + (c2 & B_MASK)) / 2) & B_MASK;
var c3 = r | g | b;
c3 &= ~OPACITY_MASK;
return OPACITY_MASK | c3;
}
if (type is not (ToolFormUpdateType.PreFrame or ToolFormUpdateType.FastPreFrame)) return;
var bbCurrent = MainForm.MakeScreenshotImage();
var spanCurrent = bbCurrent.AsSpan();
Invert(spanCurrent);
if (_bbPrev is null) // initialisation
{
_bbPrev = bbCurrent;
return;
}
var spanPrev = _bbPrev.AsSpan(); // was inverted before saving
for (var i = 0; i < spanCurrent.Length; i++) spanPrev[i] = AverageXRGB(spanPrev[i], spanCurrent[i]);
Invert(spanPrev);
APIs.Gui.WithSurface(DisplaySurfaceID.EmuCore, g => g.DrawImage(_bbPrev!.ToSysdrawingBitmap(), 0, 0, cache: false));
_bbPrev = bbCurrent;
}
}