slightly refactor OSD layer, no longer uses a render callback, rather it will do its logic itself and has its own enable drawing flag

This commit is contained in:
CasualPokePlayer 2023-08-22 17:57:46 -07:00
parent 53563657fe
commit 19443040c4
4 changed files with 75 additions and 83 deletions

View File

@ -280,32 +280,15 @@ namespace BizHawk.Client.Common
}
if (!includeUserFilters)
{
selectedChain = null;
}
var fCoreScreenControl = CreateCoreScreenControl();
var fPresent = new FinalPresentation(chainOutSize);
var fInput = new SourceImage(chainInSize);
var fOSD = new OSD();
fOSD.RenderCallback = () =>
{
if (!includeOSD)
{
return;
}
var size = fOSD.FindInput().SurfaceFormat.Size;
_renderer.Begin(size.Width, size.Height);
var myBlitter = new MyBlitter(this)
{
ClipBounds = new Rectangle(0, 0, size.Width, size.Height)
};
_renderer.EnableBlending();
OSD.Begin(myBlitter);
OSD.DrawScreenInfo(myBlitter);
OSD.DrawMessages(myBlitter);
_renderer.End();
};
var fOSD = new OSD(includeOSD, OSD, _theOneFont);
var chain = new FilterProgram();
@ -392,18 +375,17 @@ namespace BizHawk.Client.Common
// add final presentation
if (includeUserFilters)
{
chain.AddFilter(fPresent, "presentation");
}
//add lua layer 'native'
AppendApiHawkLayer(chain, DisplaySurfaceID.Client);
// and OSD goes on top of that
// TODO - things break if this isn't present (the final presentation filter gets messed up when used with prescaling)
// so, always include it (we'll handle this flag in the callback to do no rendering)
if (true /*includeOSD*/)
{
chain.AddFilter(fOSD, "osd");
}
// so, always include it (we'll handle includeOSD on Run)
chain.AddFilter(fOSD, "osd");
return chain;
}
@ -1067,29 +1049,5 @@ namespace BizHawk.Client.Common
_apiHawkIDToSurface.Remove(surfaceID);
_apiHawkSurfaceSets[surfaceID].SetPending(dispSurfaceImpl);
}
// helper classes:
private class MyBlitter : IBlitter
{
private readonly DisplayManagerBase _owner;
public MyBlitter(DisplayManagerBase dispManager)
{
_owner = dispManager;
}
public StringRenderer GetFontType(string fontType) => _owner._theOneFont;
public void DrawString(string s, StringRenderer font, Color color, float x, float y)
{
_owner._renderer.SetModulateColor(color);
font.RenderString(_owner._renderer, x, y, s);
_owner._renderer.SetModulateColorWhite();
}
public SizeF MeasureString(string s, StringRenderer font) => font.Measure(s);
public Rectangle ClipBounds { get; set; }
}
}
}

View File

@ -802,31 +802,70 @@ namespace BizHawk.Client.Common.Filters
public class OSD : BaseFilter
{
// this class has the ability to disable its operations for higher performance when the callback is removed,
// without having to take it out of the chain. although, its presence in the chain may slow down performance due to added resolves/renders
// so, we should probably rebuild the chain.
// This class has the ability to disable its operations for higher performance _drawOsd is false, while still allowing it to be in the chain
// (although its presence in the chain may slow down performance itself due to added resolves/renders)
private readonly bool _drawOsd;
private readonly OSDManager _manager;
private readonly StringRenderer _font;
public OSD(bool drawOsd, OSDManager manager, StringRenderer font)
{
_drawOsd = drawOsd;
_manager = manager;
_font = font;
}
public override void Initialize()
{
if (RenderCallback != null)
{
DeclareInput(SurfaceDisposition.RenderTarget);
}
DeclareInput(SurfaceDisposition.RenderTarget);
}
public override void SetInputFormat(string channel, SurfaceState state)
{
if (RenderCallback != null)
{
DeclareOutput(state);
}
DeclareOutput(state);
}
public Action RenderCallback;
public override void Run()
{
RenderCallback?.Invoke();
if (!_drawOsd)
{
return;
}
var size = FindInput().SurfaceFormat.Size;
FilterProgram.GuiRenderer.Begin(size.Width, size.Height);
var blitter = new OSDBlitter(_font, FilterProgram.GuiRenderer, new(0, 0, size.Width, size.Height));
FilterProgram.GuiRenderer.EnableBlending();
_manager.DrawScreenInfo(blitter);
_manager.DrawMessages(blitter);
FilterProgram.GuiRenderer.End();
}
private class OSDBlitter : IBlitter
{
private readonly StringRenderer _font;
private readonly IGuiRenderer _renderer;
public OSDBlitter(StringRenderer font, IGuiRenderer renderer, Rectangle clipBounds)
{
_font = font;
_renderer = renderer;
ClipBounds = clipBounds;
}
public void DrawString(string s, Color color, float x, float y)
{
_renderer.SetModulateColor(color);
_font.RenderString(_renderer, x, y, s);
_renderer.SetModulateColorWhite();
}
public SizeF MeasureString(string s)
=> _font.Measure(s);
public Rectangle ClipBounds { get; }
}
}
}

View File

@ -11,9 +11,10 @@ namespace BizHawk.Client.Common
/// </summary>
public interface IBlitter
{
StringRenderer GetFontType(string fontType);
void DrawString(string s, StringRenderer font, Color color, float x, float y);
SizeF MeasureString(string s, StringRenderer font);
Rectangle ClipBounds { get; set; }
void DrawString(string s, Color color, float x, float y);
SizeF MeasureString(string s);
Rectangle ClipBounds { get; }
}
}

View File

@ -34,19 +34,13 @@ namespace BizHawk.Client.Common
}
public string Fps { get; set; }
public StringRenderer MessageFont;
public void Begin(IBlitter blitter)
{
MessageFont = blitter.GetFontType(nameof(MessageFont));
}
public Color FixedMessagesColor => Color.FromArgb(_config.MessagesColor);
public Color FixedAlertMessageColor => Color.FromArgb(_config.AlertMessageColor);
private PointF GetCoordinates(IBlitter g, MessagePosition position, string message)
{
var size = g.MeasureString(message, MessageFont);
var size = g.MeasureString(message);
float x = position.Anchor.IsLeft()
? position.X
: g.ClipBounds.Width - position.X - size.Width;
@ -132,7 +126,7 @@ namespace BizHawk.Client.Common
{
var point = GetCoordinates(g, _config.Messages, message.Message);
var y = point.Y + yOffset; // TODO: clean me up
g.DrawString(message.Message, MessageFont, FixedMessagesColor, point.X, y);
g.DrawString(message.Message, FixedMessagesColor, point.X, y);
}
public void DrawMessages(IBlitter g)
@ -173,7 +167,7 @@ namespace BizHawk.Client.Common
{
var point = GetCoordinates(g, text.Position, text.Message);
if (point.Y >= g.ClipBounds.Height) continue; // simple optimisation; don't bother drawing off-screen
g.DrawString(text.Message, MessageFont, text.ForeColor, point.X, point.Y);
g.DrawString(text.Message, text.ForeColor, point.X, point.Y);
}
catch (Exception)
{
@ -245,7 +239,7 @@ namespace BizHawk.Client.Common
private void DrawOsdMessage(IBlitter g, string message, Color color, float x, float y)
{
g.DrawString(message, MessageFont, color, x, y);
g.DrawString(message, color, x, y);
}
/// <summary>
@ -275,7 +269,7 @@ namespace BizHawk.Client.Common
var input = InputStrMovie();
var point = GetCoordinates(g, _config.InputDisplay, input);
Color c = Color.FromArgb(_config.MovieInput);
g.DrawString(input, MessageFont, c, point.X, point.Y);
g.DrawString(input, c, point.X, point.Y);
}
if (!moviePlaying) // TODO: message config -- allow setting of "mixed", and "auto"
@ -294,14 +288,14 @@ namespace BizHawk.Client.Common
// first display previous frame's input.
// note: that's only available in case we're working on a movie
var previousStr = InputPrevious();
g.DrawString(previousStr, MessageFont, previousColor, point.X, point.Y);
g.DrawString(previousStr, previousColor, point.X, point.Y);
// next, draw the immediate input.
// that is, whatever is being held down interactively right this moment even if the game is paused
// this includes things held down due to autohold or autofire
// I know, this is all really confusing
var immediate = InputStrImmediate();
g.DrawString(immediate, MessageFont, immediateColor, point.X, point.Y);
g.DrawString(immediate, immediateColor, point.X, point.Y);
// next draw anything that's pressed because it's sticky.
// this applies to autofire and autohold both. somehow. I don't understand it.
@ -310,11 +304,11 @@ namespace BizHawk.Client.Common
// so we make an AND adapter and combine it using immediate & sticky
// (adapter creation moved to InputManager)
var autoString = MakeStringFor(_inputManager.WeirdStickyControllerForInputDisplay, cache: true);
g.DrawString(autoString, MessageFont, autoColor, point.X, point.Y);
g.DrawString(autoString, autoColor, point.X, point.Y);
//recolor everything that's changed from the previous input
var immediateOverlay = MakeIntersectImmediatePrevious();
g.DrawString(immediateOverlay, MessageFont, changedColor, point.X, point.Y);
g.DrawString(immediateOverlay, changedColor, point.X, point.Y);
}
}
@ -357,7 +351,7 @@ namespace BizHawk.Client.Common
var message = sb.ToString();
var point = GetCoordinates(g, _config.Autohold, message);
g.DrawString(message, MessageFont, Color.White, point.X, point.Y);
g.DrawString(message, Color.White, point.X, point.Y);
}
if (_movieSession.Movie.IsActive() && _config.DisplaySubtitles)