delete display manager threading. fix gdi+ leaks in lua code. add abstracted OSD drawing "blitter" system for sysdrawing/d3d dual compatibility and framework for future use for faster lua drawing.
This commit is contained in:
parent
e9983598c2
commit
c7925d986c
|
@ -290,30 +290,27 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
public string FPS { get; set; }
|
||||
public string MT { get; set; }
|
||||
private Font MessageFont;
|
||||
private Font AlertFont;
|
||||
IBlitterFont MessageFont;
|
||||
IBlitterFont AlertFont;
|
||||
public void Dispose()
|
||||
{
|
||||
if (MessageFont != null)
|
||||
{
|
||||
MessageFont.Dispose();
|
||||
MessageFont = null;
|
||||
}
|
||||
if (AlertFont != null)
|
||||
{
|
||||
AlertFont.Dispose();
|
||||
AlertFont = null;
|
||||
}
|
||||
}
|
||||
public OSDManager()
|
||||
{
|
||||
//MessageFont = new Font(Device, 16, 0, FontWeight.Bold, 1, false, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.Default | PitchAndFamily.DontCare, "Courier");
|
||||
//AlertFont = new Font(Device, 16, 0, FontWeight.ExtraBold, 1, true, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.Default | PitchAndFamily.DontCare, "Courier");
|
||||
MessageFont = new Font("Courier", 14, FontStyle.Bold, GraphicsUnit.Pixel);
|
||||
AlertFont = new Font("Courier", 14, FontStyle.Bold, GraphicsUnit.Pixel);
|
||||
|
||||
}
|
||||
|
||||
private float GetX(Graphics g, int x, int anchor, Font font, string message)
|
||||
public void Begin(IBlitter blitter)
|
||||
{
|
||||
MessageFont = blitter.GetFontType("MessageFont");
|
||||
AlertFont = blitter.GetFontType("AlertFont");
|
||||
}
|
||||
|
||||
public System.Drawing.Color FixedMessagesColor { get { return System.Drawing.Color.FromArgb(Global.Config.MessagesColor); } }
|
||||
public System.Drawing.Color FixedAlertMessageColor { get { return System.Drawing.Color.FromArgb(Global.Config.AlertMessageColor); } }
|
||||
|
||||
public OSDManager()
|
||||
{
|
||||
}
|
||||
|
||||
private float GetX(IBlitter g, int x, int anchor, IBlitterFont font, string message)
|
||||
{
|
||||
var size = g.MeasureString(message, font);
|
||||
//Rectangle rect = g.MeasureString(Sprite, message, new DrawTextFormat());
|
||||
|
@ -329,7 +326,7 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
}
|
||||
|
||||
private float GetY(Graphics g, int y, int anchor, Font font, string message)
|
||||
private float GetY(IBlitter g, int y, int anchor, IBlitterFont font, string message)
|
||||
{
|
||||
var size = g.MeasureString(message, font);
|
||||
switch (anchor)
|
||||
|
@ -377,9 +374,9 @@ namespace BizHawk.MultiClient
|
|||
messages.Add(new UIMessage { Message = message, ExpireAt = DateTime.Now + TimeSpan.FromSeconds(2) });
|
||||
}
|
||||
|
||||
public void AddGUIText(string message, int x, int y, bool alert, Brush BackGround, Brush ForeColor, int anchor)
|
||||
public void AddGUIText(string message, int x, int y, bool alert, Color BackGround, Color ForeColor, int anchor)
|
||||
{
|
||||
GUITextList.Add(new UIDisplay { Message = message, X = x, Y = y, BackGround = BackGround, ForeColor = ForeColor, Alert = alert, Anchor = anchor });
|
||||
GUITextList.Add(new UIDisplay { Message = message, X = x, Y = y, BackGround = BackGround, ForeColor = ForeColor, Alert = alert, Anchor = anchor });
|
||||
}
|
||||
|
||||
public void ClearGUIText()
|
||||
|
@ -388,7 +385,7 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
|
||||
|
||||
public void DrawMessages(Graphics g)
|
||||
public void DrawMessages(IBlitter g)
|
||||
{
|
||||
//todo - not so much brush object churn?
|
||||
|
||||
|
@ -399,31 +396,29 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
float x = 3;
|
||||
float y = g.ClipBounds.Height - (line * 18);
|
||||
g.DrawString(messages[i].Message, MessageFont, Brushes.Black, x + 2, y + 2);
|
||||
using(var brush = new SolidBrush(Color.FromArgb(Global.Config.MessagesColor)))
|
||||
g.DrawString(messages[i].Message, MessageFont, brush, x, y);
|
||||
g.DrawString(messages[i].Message, MessageFont, Color.Black, x + 2, y + 2);
|
||||
g.DrawString(messages[i].Message, MessageFont, FixedMessagesColor, x, y);
|
||||
}
|
||||
for (int x = 0; x < GUITextList.Count; x++)
|
||||
{
|
||||
try
|
||||
{
|
||||
float posx = GetX(g, GUITextList[x].X, GUITextList[x].Anchor, MessageFont, GUITextList[x].Message);
|
||||
float posy = GetY(g, GUITextList[x].Y, GUITextList[x].Anchor, MessageFont, GUITextList[x].Message);
|
||||
try
|
||||
{
|
||||
float posx = GetX(g, GUITextList[x].X, GUITextList[x].Anchor, MessageFont, GUITextList[x].Message);
|
||||
float posy = GetY(g, GUITextList[x].Y, GUITextList[x].Anchor, MessageFont, GUITextList[x].Message);
|
||||
|
||||
g.DrawString(GUITextList[x].Message, MessageFont, GUITextList[x].BackGround, posx + 2, posy + 2);
|
||||
g.DrawString(GUITextList[x].Message, MessageFont, Brushes.Gray, posx + 1, posy + 1);
|
||||
g.DrawString(GUITextList[x].Message, MessageFont, GUITextList[x].BackGround, posx + 2, posy + 2);
|
||||
g.DrawString(GUITextList[x].Message, MessageFont, Color.Gray, posx + 1, posy + 1);
|
||||
|
||||
if (GUITextList[x].Alert)
|
||||
using(var brush = new SolidBrush(Color.FromArgb(Global.Config.AlertMessageColor)))
|
||||
g.DrawString(GUITextList[x].Message, MessageFont, brush, posx,posy);
|
||||
else
|
||||
g.DrawString(GUITextList[x].Message, MessageFont, GUITextList[x].ForeColor, posx, posy);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (GUITextList[x].Alert)
|
||||
g.DrawString(GUITextList[x].Message, MessageFont, FixedMessagesColor, posx, posy);
|
||||
else
|
||||
g.DrawString(GUITextList[x].Message, MessageFont, GUITextList[x].ForeColor, posx, posy);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -450,16 +445,15 @@ namespace BizHawk.MultiClient
|
|||
/// <summary>
|
||||
/// Display all screen info objects like fps, frame counter, lag counter, and input display
|
||||
/// </summary>
|
||||
public void DrawScreenInfo(Graphics g)
|
||||
public void DrawScreenInfo(IBlitter g)
|
||||
{
|
||||
if (Global.Config.DisplayFrameCounter)
|
||||
{
|
||||
string message = MakeFrameCounter();
|
||||
float x = GetX(g, Global.Config.DispFrameCx, Global.Config.DispFrameanchor, MessageFont, message);
|
||||
float y = GetY(g, Global.Config.DispFrameCy, Global.Config.DispFrameanchor, MessageFont, message);
|
||||
g.DrawString(message, MessageFont, Brushes.Black, x + 1, y + 1);
|
||||
using(var brush = new SolidBrush(Color.FromArgb(Global.Config.MessagesColor)))
|
||||
g.DrawString(message, MessageFont, brush, x, y );
|
||||
g.DrawString(message, MessageFont, Color.Black, x + 1, y + 1);
|
||||
g.DrawString(message, MessageFont, Color.FromArgb(Global.Config.MessagesColor), x, y);
|
||||
}
|
||||
if (Global.Config.DisplayInput)
|
||||
{
|
||||
|
@ -474,27 +468,24 @@ namespace BizHawk.MultiClient
|
|||
else
|
||||
c = Color.FromArgb(Global.Config.MessagesColor);
|
||||
|
||||
g.DrawString(input, MessageFont, Brushes.Black, x+1,y+1);
|
||||
using(var brush = new SolidBrush(c))
|
||||
g.DrawString(input, MessageFont, brush, x,y);
|
||||
g.DrawString(input, MessageFont, Color.Black, x+1,y+1);
|
||||
g.DrawString(input, MessageFont, c, x,y);
|
||||
}
|
||||
if (Global.MovieSession.MultiTrack.IsActive)
|
||||
{
|
||||
g.DrawString(MT, MessageFont, Brushes.Black,
|
||||
g.DrawString(MT, MessageFont, Color.Black,
|
||||
Global.Config.DispFPSx + 1, //TODO: Multitrack position variables
|
||||
Global.Config.DispFPSy + 1);
|
||||
using(var brush = new SolidBrush(Color.FromArgb(Global.Config.MessagesColor)))
|
||||
g.DrawString(MT, MessageFont, Brushes.Black,
|
||||
Global.Config.DispFPSx, //TODO: Multitrack position variables
|
||||
Global.Config.DispFPSy);
|
||||
g.DrawString(MT, MessageFont, FixedMessagesColor,
|
||||
Global.Config.DispFPSx, //TODO: Multitrack position variables
|
||||
Global.Config.DispFPSy);
|
||||
}
|
||||
if (Global.Config.DisplayFPS && FPS != null)
|
||||
{
|
||||
float x = GetX(g, Global.Config.DispFPSx, Global.Config.DispFPSanchor, MessageFont, FPS);
|
||||
float y = GetY(g, Global.Config.DispFPSy, Global.Config.DispFPSanchor, MessageFont, FPS);
|
||||
g.DrawString(FPS, MessageFont, Brushes.Black, x + 1, y + 1);
|
||||
using(var brush = new SolidBrush(Color.FromArgb(Global.Config.MessagesColor)))
|
||||
g.DrawString(FPS, MessageFont, brush, x, y);
|
||||
g.DrawString(FPS, MessageFont, Color.Black, x + 1, y + 1);
|
||||
g.DrawString(FPS, MessageFont, FixedMessagesColor, x, y);
|
||||
}
|
||||
|
||||
if (Global.Config.DisplayLagCounter)
|
||||
|
@ -505,21 +496,19 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
float x = GetX(g, Global.Config.DispLagx, Global.Config.DispLaganchor, AlertFont, counter);
|
||||
float y = GetY(g, Global.Config.DispLagy, Global.Config.DispLaganchor, AlertFont, counter);
|
||||
g.DrawString(MakeLagCounter(), AlertFont, Brushes.Black,
|
||||
g.DrawString(MakeLagCounter(), AlertFont, Color.Black,
|
||||
Global.Config.DispLagx + 1,
|
||||
Global.Config.DispLagy + 1);
|
||||
using(var brush = new SolidBrush(Color.FromArgb(Global.Config.AlertMessageColor)))
|
||||
g.DrawString(MakeLagCounter(), AlertFont, brush,
|
||||
Global.Config.DispLagx,
|
||||
Global.Config.DispLagy);
|
||||
g.DrawString(MakeLagCounter(), AlertFont, FixedAlertMessageColor,
|
||||
Global.Config.DispLagx,
|
||||
Global.Config.DispLagy);
|
||||
}
|
||||
else
|
||||
{
|
||||
float x = GetX(g, Global.Config.DispLagx, Global.Config.DispLaganchor, MessageFont, counter);
|
||||
float y = GetY(g, Global.Config.DispLagy, Global.Config.DispLaganchor, MessageFont, counter);
|
||||
g.DrawString(counter, MessageFont, Brushes.Black, x + 1, y + 1);
|
||||
using(var brush = new SolidBrush(Color.FromArgb(Global.Config.MessagesColor)))
|
||||
g.DrawString(counter, MessageFont, brush, x , y );
|
||||
g.DrawString(counter, MessageFont, Color.Black, x + 1, y + 1);
|
||||
g.DrawString(counter, MessageFont, FixedMessagesColor, x , y );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -528,26 +517,26 @@ namespace BizHawk.MultiClient
|
|||
string rerec = MakeRerecordCount();
|
||||
float x = GetX(g, Global.Config.DispRecx, Global.Config.DispRecanchor, MessageFont, rerec);
|
||||
float y = GetY(g, Global.Config.DispRecy, Global.Config.DispRecanchor, MessageFont, rerec);
|
||||
g.DrawString(rerec, MessageFont, Brushes.Black, x + 1, y + 1);
|
||||
using(var brush = new SolidBrush(Color.FromArgb(Global.Config.MessagesColor)))
|
||||
g.DrawString(rerec, MessageFont, brush, x , y);
|
||||
g.DrawString(rerec, MessageFont, Color.Black, x + 1, y + 1);
|
||||
g.DrawString(rerec, MessageFont, FixedMessagesColor, x, y);
|
||||
}
|
||||
|
||||
if (Global.MovieSession.Movie.Mode == MOVIEMODE.PLAY)
|
||||
{
|
||||
|
||||
int r = (int)g.ClipBounds.Width;
|
||||
Point[] p = { new Point(r - 20, 2),
|
||||
new Point(r - 4, 12),
|
||||
new Point(r - 20, 22) };
|
||||
g.FillPolygon(new SolidBrush(Color.Red), p);
|
||||
g.DrawPolygon(new Pen(new SolidBrush(Color.Pink)), p);
|
||||
//TODO
|
||||
//g.FillPolygon(new SolidBrush(Color.Red), p);
|
||||
//g.DrawPolygon(new Pen(new SolidBrush(Color.Pink)), p);
|
||||
|
||||
}
|
||||
else if (Global.MovieSession.Movie.Mode == MOVIEMODE.RECORD)
|
||||
{
|
||||
g.FillEllipse(new SolidBrush(Color.Red), new Rectangle((int)g.ClipBounds.Width - 22, 2, 20, 20));
|
||||
g.DrawEllipse(new Pen(new SolidBrush(Color.Pink)), new Rectangle((int)g.ClipBounds.Width - 22, 2, 20, 20));
|
||||
//TODO
|
||||
//g.FillEllipse(new SolidBrush(Color.Red), new Rectangle((int)g.ClipBounds.Width - 22, 2, 20, 20));
|
||||
//g.DrawEllipse(new Pen(new SolidBrush(Color.Pink)), new Rectangle((int)g.ClipBounds.Width - 22, 2, 20, 20));
|
||||
}
|
||||
|
||||
if (Global.MovieSession.Movie.Mode != MOVIEMODE.INACTIVE && Global.Config.DisplaySubtitles)
|
||||
|
@ -557,11 +546,10 @@ namespace BizHawk.MultiClient
|
|||
if (s == null) return;
|
||||
for (int i = 0; i < s.Count; i++)
|
||||
{
|
||||
g.DrawString(s[i].Message, MessageFont, Brushes.Black,
|
||||
g.DrawString(s[i].Message, MessageFont, Color.Black,
|
||||
s[i].X + 1, s[i].Y + 1);
|
||||
using (var brush = new SolidBrush(Color.FromArgb((int)s[i].Color)))
|
||||
g.DrawString(s[i].Message, MessageFont, brush,
|
||||
s[i].X, s[i].Y);
|
||||
g.DrawString(s[i].Message, MessageFont, Color.FromArgb((int)s[i].Color),
|
||||
s[i].X, s[i].Y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -585,12 +573,6 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
//have at least something here at the start
|
||||
luaNativeSurfacePreOSD = new DisplaySurface(1, 1);
|
||||
|
||||
wakeupEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
|
||||
suspendReplyEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
|
||||
displayThread = new Thread(ThreadProc);
|
||||
displayThread.IsBackground = true;
|
||||
displayThread.Start();
|
||||
}
|
||||
|
||||
volatile bool VsyncToggle = false;
|
||||
|
@ -598,31 +580,50 @@ namespace BizHawk.MultiClient
|
|||
SwappableDisplaySurfaceSet sourceSurfaceSet = new SwappableDisplaySurfaceSet();
|
||||
public void UpdateSource(IVideoProvider videoProvider)
|
||||
{
|
||||
VsyncRequested = Global.Config.DisplayVSync;
|
||||
|
||||
//needsclear = false because we're about to clobber the data with AcceptIntArray
|
||||
var newPendingSurface = sourceSurfaceSet.AllocateSurface(videoProvider.BufferWidth, videoProvider.BufferHeight, false);
|
||||
newPendingSurface.AcceptIntArray((int[])videoProvider.GetVideoBuffer().Clone());
|
||||
newPendingSurface.AcceptIntArray(videoProvider.GetVideoBuffer());
|
||||
sourceSurfaceSet.SetPending(newPendingSurface);
|
||||
wakeupEvent.Set();
|
||||
|
||||
var renderPanel = Global.RenderPanel;
|
||||
if (renderPanel == null) return;
|
||||
|
||||
if (VsyncRequested)
|
||||
{
|
||||
VsyncToggle = true;
|
||||
currNativeWidth = Global.RenderPanel.NativeSize.Width;
|
||||
currNativeHeight = Global.RenderPanel.NativeSize.Height;
|
||||
|
||||
//if we're configured to use a scaling filter, apply it now
|
||||
//SHOULD THIS BE RUN REPEATEDLY?
|
||||
//some filters may need to run repeatedly (temporal interpolation, ntsc scanline field alternating)
|
||||
//but its sort of wasted work.
|
||||
//IDisplayFilter filter = new Hq2xBase_Super2xSai();
|
||||
//var tempSurface = filter.Execute(currentSourceSurface);
|
||||
//currentSourceSurface.Dispose();
|
||||
//currentSourceSurface = tempSurface;
|
||||
|
||||
currentSourceSurface = sourceSurfaceSet.GetCurrent();
|
||||
|
||||
if (currentSourceSurface == null) return;
|
||||
|
||||
int w = currNativeWidth;
|
||||
int h = currNativeHeight;
|
||||
|
||||
DisplaySurface luaEmuSurface = luaEmuSurfaceSet.GetCurrent();
|
||||
DisplaySurface luaSurface = luaNativeSurfaceSet.GetCurrent();
|
||||
|
||||
//do we have anything to do?
|
||||
//bool complexComposite = false;
|
||||
//if (luaEmuSurface != null) complexComposite = true;
|
||||
//if (luaSurface != null) complexComposite = true;
|
||||
|
||||
Global.RenderPanel.Clear(Color.FromArgb(videoProvider.BackgroundColor));
|
||||
Global.RenderPanel.Render(currentSourceSurface);
|
||||
if (luaEmuSurface != null)
|
||||
Global.RenderPanel.RenderOverlay(luaEmuSurface);
|
||||
|
||||
RenderOSD();
|
||||
|
||||
Global.RenderPanel.Present();
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
//if (Direct3DRenderPanel.vsyncEvent.WaitOne(1)) break;
|
||||
if (!VsyncToggle) break;
|
||||
Application.DoEvents();
|
||||
}
|
||||
}
|
||||
|
||||
//for(;;)
|
||||
//{
|
||||
// if (Direct3DRenderPanel.vsyncEvent.WaitOne(1)) break;
|
||||
// Application.DoEvents();
|
||||
//}
|
||||
}
|
||||
|
||||
public bool Disposed { get; private set; }
|
||||
|
@ -630,10 +631,6 @@ namespace BizHawk.MultiClient
|
|||
public void Dispose()
|
||||
{
|
||||
if (Disposed) return;
|
||||
shutdownFlag = true;
|
||||
VsyncToggle = true;
|
||||
while (shutdownFlag) Thread.Sleep(1);
|
||||
wakeupEvent.Dispose();
|
||||
Disposed = true;
|
||||
}
|
||||
|
||||
|
@ -663,42 +660,13 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
|
||||
int currNativeWidth, currNativeHeight;
|
||||
EventWaitHandle wakeupEvent, suspendReplyEvent;
|
||||
bool shutdownFlag, suspendFlag;
|
||||
void ThreadProc()
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
Display();
|
||||
|
||||
//wait until we receive something interesting, or just a little while anyway
|
||||
wakeupEvent.WaitOne(1);
|
||||
|
||||
if (suspendFlag)
|
||||
{
|
||||
suspendFlag = false;
|
||||
suspendReplyEvent.Set();
|
||||
wakeupEvent.WaitOne();
|
||||
suspendReplyEvent.Set();
|
||||
wakeupEvent.WaitOne();
|
||||
suspendReplyEvent.Set();
|
||||
}
|
||||
|
||||
if (shutdownFlag) break;
|
||||
}
|
||||
shutdownFlag = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// suspends the display manager so that tricky things can be changed without the display thread going in and getting all confused and hating
|
||||
/// </summary>
|
||||
public void Suspend()
|
||||
{
|
||||
suspendFlag = true;
|
||||
wakeupEvent.Set();
|
||||
suspendReplyEvent.WaitOne();
|
||||
wakeupEvent.Set();
|
||||
suspendReplyEvent.WaitOne();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -706,126 +674,20 @@ namespace BizHawk.MultiClient
|
|||
/// </summary>
|
||||
public void Resume()
|
||||
{
|
||||
wakeupEvent.Set();
|
||||
suspendReplyEvent.WaitOne();
|
||||
}
|
||||
|
||||
void RenderOSD()
|
||||
{
|
||||
Global.OSD.Begin((IBlitter)Global.RenderPanel);
|
||||
((IBlitter)Global.RenderPanel).Open();
|
||||
Global.OSD.DrawScreenInfo((IBlitter)Global.RenderPanel);
|
||||
Global.OSD.DrawMessages((IBlitter)Global.RenderPanel);
|
||||
((IBlitter)Global.RenderPanel).Close();
|
||||
}
|
||||
|
||||
|
||||
SwappableDisplaySurfaceSet nativeDisplaySurfaceSet = new SwappableDisplaySurfaceSet();
|
||||
|
||||
/// <summary>
|
||||
/// internal display worker proc; runs through the multiply layered display pipeline
|
||||
/// </summary>
|
||||
void Display()
|
||||
{
|
||||
var renderPanel = Global.RenderPanel;
|
||||
if (renderPanel == null) return;
|
||||
|
||||
currNativeWidth = Global.RenderPanel.NativeSize.Width;
|
||||
currNativeHeight = Global.RenderPanel.NativeSize.Height;
|
||||
|
||||
//if we're configured to use a scaling filter, apply it now
|
||||
//SHOULD THIS BE RUN REPEATEDLY?
|
||||
//some filters may need to run repeatedly (temporal interpolation, ntsc scanline field alternating)
|
||||
//but its sort of wasted work.
|
||||
//IDisplayFilter filter = new Hq2xBase_Super2xSai();
|
||||
//var tempSurface = filter.Execute(currentSourceSurface);
|
||||
//currentSourceSurface.Dispose();
|
||||
//currentSourceSurface = tempSurface;
|
||||
|
||||
currentSourceSurface = sourceSurfaceSet.GetCurrent();
|
||||
|
||||
if (currentSourceSurface == null) return;
|
||||
|
||||
int w = currNativeWidth;
|
||||
int h = currNativeHeight;
|
||||
|
||||
DisplaySurface luaEmuSurface = luaEmuSurfaceSet.GetCurrent();
|
||||
DisplaySurface luaSurface = luaNativeSurfaceSet.GetCurrent();
|
||||
|
||||
//do we have anything to do?
|
||||
bool complexComposite = false;
|
||||
if (luaEmuSurface != null) complexComposite = true;
|
||||
if (luaSurface != null) complexComposite = true;
|
||||
|
||||
if (!complexComposite)
|
||||
{
|
||||
if (Global.Config.SuppressGui)
|
||||
{
|
||||
Global.RenderPanel.Render(currentSourceSurface);
|
||||
}
|
||||
else
|
||||
{
|
||||
Global.RenderPanel.Render(currentSourceSurface);
|
||||
var nativeBmp = nativeDisplaySurfaceSet.AllocateSurface(w, h, true);
|
||||
using (var g = Graphics.FromImage(nativeBmp.PeekBitmap()))
|
||||
{
|
||||
Global.OSD.DrawScreenInfo(g);
|
||||
Global.OSD.DrawMessages(g);
|
||||
//Thread.Sleep(1);
|
||||
}
|
||||
nativeBmp.FromBitmap();
|
||||
Global.RenderPanel.RenderOverlay(nativeBmp);
|
||||
//release the native resolution image
|
||||
nativeDisplaySurfaceSet.ReleaseSurface(nativeBmp);
|
||||
//Global.RenderPanel.Present();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var nativeBmp = nativeDisplaySurfaceSet.AllocateSurface(w, h, true);
|
||||
using (var g = Graphics.FromImage(nativeBmp.PeekBitmap()))
|
||||
{
|
||||
//scale the source bitmap to the desired size of the render panel
|
||||
g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
|
||||
g.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
g.CompositingMode = CompositingMode.SourceCopy;
|
||||
g.CompositingQuality = CompositingQuality.HighSpeed;
|
||||
g.DrawImage(currentSourceSurface.PeekBitmap(), 0, 0, w, h);
|
||||
|
||||
//switch to fancier composition for OSD overlays and such
|
||||
g.CompositingMode = CompositingMode.SourceOver;
|
||||
|
||||
//this could have been done onto the source surface earlier and then scaled only once but the whole composition system needs revising, soo..
|
||||
if (luaEmuSurface != null) g.DrawImage(luaEmuSurface.PeekBitmap(), 0, 0, w, h);
|
||||
g.Clip = new Region(new Rectangle(0, 0, nativeBmp.Width, nativeBmp.Height));
|
||||
|
||||
//apply a lua layer
|
||||
if (luaSurface != null) g.DrawImageUnscaled(luaSurface.PeekBitmap(), 0, 0);
|
||||
//although we may want to change this if we want to fade out messages or have some other fancy alpha faded gui stuff
|
||||
|
||||
//draw the OSD at native resolution
|
||||
if (!Global.Config.SuppressGui)
|
||||
{
|
||||
Global.OSD.DrawScreenInfo(g);
|
||||
Global.OSD.DrawMessages(g);
|
||||
}
|
||||
g.Clip.Dispose();
|
||||
}
|
||||
|
||||
//send the native resolution image to the render panel
|
||||
Global.RenderPanel.Render(nativeBmp);
|
||||
//Global.RenderPanel.Present();
|
||||
|
||||
//release the native resolution image
|
||||
nativeDisplaySurfaceSet.ReleaseSurface(nativeBmp);
|
||||
}
|
||||
|
||||
Global.RenderPanel.Present();
|
||||
|
||||
if (VsyncRequested)
|
||||
{
|
||||
for (; ; )
|
||||
{
|
||||
//if (Direct3DRenderPanel.vsyncEvent.WaitOne(1)) break;
|
||||
if (VsyncToggle) break;
|
||||
}
|
||||
VsyncToggle = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Thread displayThread;
|
||||
}
|
||||
}
|
|
@ -168,33 +168,28 @@ namespace BizHawk.MultiClient
|
|||
return Convert.ToUInt32((double)lua_arg);
|
||||
}
|
||||
|
||||
public Pen GetPen(object color)
|
||||
{
|
||||
System.Drawing.Pen myPen;
|
||||
if (color.GetType() == typeof(Double))
|
||||
{
|
||||
myPen = new System.Drawing.Pen(System.Drawing.Color.FromArgb(int.Parse(long.Parse(color.ToString()).ToString("X"), System.Globalization.NumberStyles.HexNumber)));
|
||||
}
|
||||
else
|
||||
{
|
||||
myPen = new System.Drawing.Pen(System.Drawing.Color.FromName(color.ToString().ToLower()));
|
||||
}
|
||||
return myPen;
|
||||
}
|
||||
|
||||
public SolidBrush GetBrush(object color)
|
||||
{
|
||||
System.Drawing.SolidBrush myBrush;
|
||||
if (color.GetType() == typeof(Double))
|
||||
{
|
||||
myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(int.Parse(long.Parse(color.ToString()).ToString("X"), System.Globalization.NumberStyles.HexNumber)));
|
||||
}
|
||||
else
|
||||
{
|
||||
myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.FromName(color.ToString().ToLower()));
|
||||
}
|
||||
return myBrush;
|
||||
}
|
||||
public Color GetColor(object color)
|
||||
{
|
||||
if (color.GetType() == typeof(Double))
|
||||
{
|
||||
return System.Drawing.Color.FromArgb(int.Parse(long.Parse(color.ToString()).ToString("X"), System.Globalization.NumberStyles.HexNumber));
|
||||
}
|
||||
else
|
||||
{
|
||||
return System.Drawing.Color.FromName(color.ToString().ToLower());
|
||||
}
|
||||
}
|
||||
|
||||
public SolidBrush GetBrush(object color)
|
||||
{
|
||||
return new System.Drawing.SolidBrush(GetColor(color));
|
||||
}
|
||||
public Pen GetPen(object color)
|
||||
{
|
||||
return new System.Drawing.Pen(GetColor(color));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* LuaInterface requires the exact match of parameter count,
|
||||
|
@ -455,12 +450,12 @@ namespace BizHawk.MultiClient
|
|||
a = LuaInt(anchor);
|
||||
}
|
||||
}
|
||||
Global.OSD.AddGUIText(luaStr.ToString(), LuaInt(luaX), LuaInt(luaY), alert, GetBrush(background), GetBrush(forecolor), a);
|
||||
Global.OSD.AddGUIText(luaStr.ToString(), LuaInt(luaX), LuaInt(luaY), alert, GetColor(background), GetColor(forecolor), a);
|
||||
}
|
||||
|
||||
public void gui_text(object luaX, object luaY, object luaStr, object background = null, object forecolor = null, object anchor = null)
|
||||
public void gui_text(object luaX, object luaY, object luaStr, object background = null, object forecolor = null, object anchor = null)
|
||||
{
|
||||
do_gui_text(luaX, luaY, luaStr, false, background, forecolor, anchor);
|
||||
do_gui_text(luaX, luaY, luaStr, false, background, forecolor, anchor);
|
||||
}
|
||||
|
||||
public void gui_alert(object luaX, object luaY, object luaStr, object anchor = null)
|
||||
|
@ -524,7 +519,8 @@ namespace BizHawk.MultiClient
|
|||
int int_height = LuaInt(height);
|
||||
g.DrawRectangle(GetPen(line), int_x, int_y, int_width, int_height);
|
||||
if (background != null)
|
||||
g.FillRectangle(GetBrush(background), int_x, int_y, int_width, int_height);
|
||||
using(var brush = GetBrush(background))
|
||||
g.FillRectangle(brush, int_x, int_y, int_width, int_height);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
|
@ -572,10 +568,14 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
try
|
||||
{
|
||||
g.DrawEllipse(GetPen(line), LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height));
|
||||
if (background != null)
|
||||
using (var pen = GetPen(line))
|
||||
{
|
||||
g.FillEllipse(GetBrush(background), LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height));
|
||||
g.DrawEllipse(pen, LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height));
|
||||
if (background != null)
|
||||
{
|
||||
using (var brush = GetBrush(background))
|
||||
g.FillEllipse(brush, LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -601,11 +601,15 @@ namespace BizHawk.MultiClient
|
|||
Points[i] = new System.Drawing.Point(LuaInt(point[1]), LuaInt(point[2]));
|
||||
i++;
|
||||
}
|
||||
|
||||
g.DrawPolygon(GetPen(line), Points);
|
||||
if (background != null)
|
||||
|
||||
using (var pen = GetPen(line))
|
||||
{
|
||||
g.FillPolygon(GetBrush(background), Points);
|
||||
g.DrawPolygon(pen, Points);
|
||||
if (background != null)
|
||||
{
|
||||
using (var brush = GetBrush(background))
|
||||
g.FillPolygon(brush, Points);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
|
@ -645,10 +649,14 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
try
|
||||
{
|
||||
g.DrawPie(GetPen(line), LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height), LuaInt(startangle), LuaInt(sweepangle));
|
||||
if (background != null)
|
||||
using(var pen = GetPen(line))
|
||||
{
|
||||
g.FillPie(GetBrush(background), LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height), LuaInt(startangle), LuaInt(sweepangle));
|
||||
g.DrawPie(pen, LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height), LuaInt(startangle), LuaInt(sweepangle));
|
||||
if (background != null)
|
||||
{
|
||||
using(var brush = GetBrush(background))
|
||||
g.FillPie(brush, LuaInt(X), LuaInt(Y), LuaInt(width), LuaInt(height), LuaInt(startangle), LuaInt(sweepangle));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using sysdrawingfont=System.Drawing.Font;
|
||||
using sysdrawing2d=System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
|
@ -11,7 +12,7 @@ using System.Windows.Forms;
|
|||
#if WINDOWS
|
||||
using SlimDX;
|
||||
using SlimDX.Direct3D9;
|
||||
using Font = SlimDX.Direct3D9.Font;
|
||||
using d3d9font=SlimDX.Direct3D9.Font;
|
||||
#endif
|
||||
using BizHawk.Core;
|
||||
|
||||
|
@ -63,7 +64,6 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// If we need to recreate the texture, do so.
|
||||
if (needsRecreating)
|
||||
{
|
||||
|
@ -83,6 +83,8 @@ namespace BizHawk.MultiClient
|
|||
Texture = new Texture(GraphicsDevice, textureWidth, textureHeight, 1, Usage.Dynamic, Format.A8R8G8B8, Pool.Default);
|
||||
}
|
||||
|
||||
surface.FromBitmap();
|
||||
|
||||
// Copy the image data to the texture.
|
||||
using (var Data = Texture.LockRectangle(0, LockFlags.Discard | LockFlags.NoDirtyUpdate).Data)
|
||||
{
|
||||
|
@ -122,34 +124,29 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
public interface IRenderer : IDisposable
|
||||
{
|
||||
void FastRenderAndPresent(DisplaySurface surface);
|
||||
void Render(DisplaySurface surface);
|
||||
void RenderOverlay(DisplaySurface surface);
|
||||
void Clear(System.Drawing.Color color);
|
||||
void Present();
|
||||
bool Resized { get; set; }
|
||||
Size NativeSize { get; }
|
||||
}
|
||||
|
||||
public class SysdrawingRenderPanel : IRenderer
|
||||
public class SysdrawingRenderPanel : IRenderer, IBlitter
|
||||
{
|
||||
sysdrawingfont MessageFont;
|
||||
sysdrawingfont AlertFont;
|
||||
DisplaySurface tempBuffer;
|
||||
Graphics g;
|
||||
|
||||
public bool Resized { get; set; }
|
||||
public void Dispose() { }
|
||||
public void Render(DisplaySurface surface)
|
||||
{
|
||||
backingControl.ReleaseCallback = RetainedViewportPanelDisposeCallback;
|
||||
//Color BackgroundColor = Color.FromArgb(video.BackgroundColor);
|
||||
//int[] data = video.GetVideoBuffer();
|
||||
|
||||
//Bitmap bmp = new Bitmap(video.BufferWidth, video.BufferHeight, PixelFormat.Format32bppArgb);
|
||||
//BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
////TODO - this is not very intelligent. no handling of pitch, for instance
|
||||
//Marshal.Copy(data, 0, bmpdata.Scan0, bmp.Width * bmp.Height);
|
||||
|
||||
//bmp.UnlockBits(bmpdata);
|
||||
|
||||
lock(this)
|
||||
tempBuffer = surfaceSet.AllocateSurface(backingControl.Width, backingControl.Height, false);
|
||||
|
@ -158,7 +155,52 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
SwappableDisplaySurfaceSet surfaceSet = new SwappableDisplaySurfaceSet();
|
||||
|
||||
DisplaySurface tempBuffer;
|
||||
class FontWrapper : IBlitterFont
|
||||
{
|
||||
public FontWrapper(sysdrawingfont font)
|
||||
{
|
||||
this.font = font;
|
||||
}
|
||||
public sysdrawingfont font;
|
||||
}
|
||||
|
||||
public Size NativeSize { get { return backingControl.ClientSize; } }
|
||||
|
||||
IBlitterFont IBlitter.GetFontType(string fontType)
|
||||
{
|
||||
if (fontType == "MessageFont") return new FontWrapper(MessageFont);
|
||||
if (fontType == "AlertFont") return new FontWrapper(AlertFont);
|
||||
return null;
|
||||
}
|
||||
|
||||
void IBlitter.Open()
|
||||
{
|
||||
g = Graphics.FromImage(tempBuffer.PeekBitmap());
|
||||
}
|
||||
|
||||
void IBlitter.Close()
|
||||
{
|
||||
g.Dispose();
|
||||
}
|
||||
|
||||
void IBlitter.DrawString(string s, IBlitterFont font, Color color, float x, float y)
|
||||
{
|
||||
using (var brush = new SolidBrush(color))
|
||||
g.DrawString(s, ((FontWrapper)font).font, brush, x, y);
|
||||
}
|
||||
|
||||
SizeF IBlitter.MeasureString(string s, IBlitterFont _font)
|
||||
{
|
||||
var font = ((FontWrapper)_font).font;
|
||||
return g.MeasureString(s, font);
|
||||
}
|
||||
|
||||
public void Clear(Color color)
|
||||
{
|
||||
//todo
|
||||
}
|
||||
|
||||
Rectangle IBlitter.ClipBounds { get; set; }
|
||||
|
||||
bool RetainedViewportPanelDisposeCallback(Bitmap bmp)
|
||||
{
|
||||
|
@ -205,13 +247,28 @@ namespace BizHawk.MultiClient
|
|||
public SysdrawingRenderPanel(RetainedViewportPanel control)
|
||||
{
|
||||
backingControl = control;
|
||||
MessageFont = new sysdrawingfont("Courier", 14, FontStyle.Bold, GraphicsUnit.Pixel);
|
||||
AlertFont = new sysdrawingfont("Courier", 14, FontStyle.Bold, GraphicsUnit.Pixel);
|
||||
}
|
||||
RetainedViewportPanel backingControl;
|
||||
public Size NativeSize { get { return backingControl.ClientSize; } }
|
||||
}
|
||||
|
||||
public interface IBlitter
|
||||
{
|
||||
void Open();
|
||||
void Close();
|
||||
IBlitterFont GetFontType(string fontType);
|
||||
void DrawString(string s, IBlitterFont font, Color color, float x, float y);
|
||||
SizeF MeasureString(string s, IBlitterFont font);
|
||||
Rectangle ClipBounds { get; set; }
|
||||
}
|
||||
|
||||
public interface IBlitterFont { }
|
||||
|
||||
|
||||
#if WINDOWS
|
||||
public class Direct3DRenderPanel : IRenderer
|
||||
|
||||
public class Direct3DRenderPanel : IRenderer, IBlitter
|
||||
{
|
||||
public Color BackgroundColor { get; set; }
|
||||
public bool Resized { get; set; }
|
||||
|
@ -222,11 +279,48 @@ namespace BizHawk.MultiClient
|
|||
private Control backingControl;
|
||||
public ImageTexture Texture;
|
||||
private Sprite Sprite;
|
||||
private d3d9font MessageFont;
|
||||
private d3d9font AlertFont;
|
||||
|
||||
class FontWrapper : IBlitterFont
|
||||
{
|
||||
public FontWrapper(d3d9font font)
|
||||
{
|
||||
this.font = font;
|
||||
}
|
||||
public d3d9font font;
|
||||
}
|
||||
|
||||
void IBlitter.Open() {}
|
||||
void IBlitter.Close() {}
|
||||
|
||||
private bool Vsync;
|
||||
|
||||
public Size NativeSize { get { return backingControl.ClientSize; } }
|
||||
|
||||
IBlitterFont IBlitter.GetFontType(string fontType)
|
||||
{
|
||||
if (fontType == "MessageFont") return new FontWrapper(MessageFont);
|
||||
if (fontType == "AlertFont") return new FontWrapper(AlertFont);
|
||||
return null;
|
||||
}
|
||||
|
||||
Color4 col(Color c) { return new Color4(c.ToArgb()); }
|
||||
|
||||
void IBlitter.DrawString(string s, IBlitterFont font, Color color, float x, float y)
|
||||
{
|
||||
((FontWrapper)font).font.DrawString(null, s, (int)x + 1, (int)y + 1, col(color));
|
||||
}
|
||||
|
||||
SizeF IBlitter.MeasureString(string s, IBlitterFont _font)
|
||||
{
|
||||
var font = ((FontWrapper)_font).font;
|
||||
Rectangle r = font.MeasureString(null, s, DrawTextFormat.Left);
|
||||
return new SizeF(r.Width, r.Height);
|
||||
}
|
||||
|
||||
Rectangle IBlitter.ClipBounds { get; set; }
|
||||
|
||||
public Direct3DRenderPanel(Direct3D direct3D, Control control)
|
||||
{
|
||||
d3d = direct3D;
|
||||
|
@ -259,6 +353,17 @@ namespace BizHawk.MultiClient
|
|||
Device.Dispose();
|
||||
Device = null;
|
||||
}
|
||||
|
||||
if (MessageFont != null)
|
||||
{
|
||||
MessageFont.Dispose();
|
||||
MessageFont = null;
|
||||
}
|
||||
if (AlertFont != null)
|
||||
{
|
||||
AlertFont.Dispose();
|
||||
AlertFont = null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool VsyncRequested
|
||||
|
@ -291,6 +396,11 @@ namespace BizHawk.MultiClient
|
|||
Sprite = new Sprite(Device);
|
||||
Texture = new ImageTexture(Device);
|
||||
|
||||
MessageFont = new d3d9font(Device, 16, 0, FontWeight.Bold, 1, false, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.Default | PitchAndFamily.DontCare, "Courier");
|
||||
AlertFont = new d3d9font(Device, 16, 0, FontWeight.ExtraBold, 1, true, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.Default | PitchAndFamily.DontCare, "Courier");
|
||||
// NOTE: if you add ANY objects, like new fonts, textures, etc, to this method
|
||||
// ALSO add dispose code in DestroyDevice() or you will be responsible for VRAM memory leaks.
|
||||
|
||||
}
|
||||
|
||||
public void Render()
|
||||
|
@ -342,27 +452,27 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
}
|
||||
|
||||
void RenderPrep()
|
||||
{
|
||||
if (Device == null || Resized || Vsync != VsyncRequested)
|
||||
backingControl.Invoke(() => CreateDevice());
|
||||
Resized = false;
|
||||
}
|
||||
|
||||
public void Clear(Color color)
|
||||
{
|
||||
Device.Clear(ClearFlags.Target, col(color), 0.0f, 0);
|
||||
}
|
||||
|
||||
private void RenderExec(DisplaySurface surface, bool overlay)
|
||||
{
|
||||
RenderPrep();
|
||||
if (surface == null)
|
||||
{
|
||||
Render();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Device == null || Resized || Vsync != VsyncRequested)
|
||||
backingControl.Invoke(() => CreateDevice());
|
||||
Resized = false;
|
||||
|
||||
|
||||
|
||||
//TODO
|
||||
//BackgroundColor = Color.FromArgb(video.BackgroundColor);
|
||||
if (overlay)
|
||||
{
|
||||
//return;
|
||||
}
|
||||
|
||||
Texture.SetImage(surface, surface.Width, surface.Height);
|
||||
|
||||
if(!overlay) Device.Clear(ClearFlags.Target, BackgroundColor, 0.0f, 0);
|
||||
|
@ -380,7 +490,6 @@ namespace BizHawk.MultiClient
|
|||
Device.SetSamplerState(0, SamplerState.MinFilter, TextureFilter.Point);
|
||||
Sprite.Transform = Matrix.Scaling(finalScale, finalScale, 0f);
|
||||
Sprite.Draw(Texture.Texture, new Rectangle(0, 0, surface.Width, surface.Height), new Vector3(surface.Width / 2f, surface.Height / 2f, 0), new Vector3(backingControl.Size.Width / 2f / finalScale, backingControl.Size.Height / 2f / finalScale, 0), Color.White);
|
||||
//if (overlay) Device.SetRenderState(RenderState.AlphaBlendEnable, false);
|
||||
Sprite.End();
|
||||
|
||||
Device.EndScene();
|
||||
|
@ -388,7 +497,6 @@ namespace BizHawk.MultiClient
|
|||
|
||||
public void Present()
|
||||
{
|
||||
//Device.Present(SlimDX.Direct3D9.Present.DoNotWait);
|
||||
Device.Present(SlimDX.Direct3D9.Present.None);
|
||||
vsyncEvent.Set();
|
||||
}
|
||||
|
@ -423,7 +531,7 @@ namespace BizHawk.MultiClient
|
|||
public int Y;
|
||||
public bool Alert;
|
||||
public int Anchor;
|
||||
public Brush ForeColor;
|
||||
public Brush BackGround;
|
||||
public Color ForeColor;
|
||||
public Color BackGround;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace BizHawk.MultiClient
|
|||
{
|
||||
bool alert = Global.CheatList.IsActiveCheat(Domain, watchList[x].address);
|
||||
Global.OSD.AddGUIText(watchList[x].ToString(),
|
||||
Global.Config.DispRamWatchx, (Global.Config.DispRamWatchy + (x * 14)), alert, Brushes.Black, Brushes.White, 0);
|
||||
Global.Config.DispRamWatchx, (Global.Config.DispRamWatchy + (x * 14)), alert, Color.Black, Color.White, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue