improve gdi+ rendering mode (depending on your point of view) to run almost as fast as direct3d and put gui option for it

This commit is contained in:
zeromus 2011-03-21 00:54:30 +00:00
parent ad6c2d0faf
commit 1917f7fc2e
6 changed files with 1299 additions and 1169 deletions

View File

@ -50,6 +50,7 @@
public bool DisplayInput = false;
public int DispInpx = 0;
public int DispInpy = 24;
public bool ForceGDI = false;
// Sound options
public bool SoundEnabled = true;

View File

@ -155,14 +155,15 @@
this.rAMPokeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.hexEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.luaConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator();
this.cheatsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.NESToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.pPUViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.gameGenieCodesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.helpToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator();
this.cheatsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.forceGDIPPresentationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip1.SuspendLayout();
this.SuspendLayout();
//
@ -914,7 +915,8 @@
this.pauseWhenMenuActivatedToolStripMenuItem,
this.saveWindowPositionToolStripMenuItem,
this.startPausedToolStripMenuItem,
this.enableRewindToolStripMenuItem});
this.enableRewindToolStripMenuItem,
this.forceGDIPPresentationToolStripMenuItem});
this.gUIToolStripMenuItem.Name = "gUIToolStripMenuItem";
this.gUIToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.gUIToolStripMenuItem.Text = "GUI";
@ -1147,38 +1149,50 @@
// rAMWatchToolStripMenuItem
//
this.rAMWatchToolStripMenuItem.Name = "rAMWatchToolStripMenuItem";
this.rAMWatchToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.rAMWatchToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
this.rAMWatchToolStripMenuItem.Text = "RAM &Watch";
this.rAMWatchToolStripMenuItem.Click += new System.EventHandler(this.RAMWatchToolStripMenuItem_Click);
//
// rAMSearchToolStripMenuItem
//
this.rAMSearchToolStripMenuItem.Name = "rAMSearchToolStripMenuItem";
this.rAMSearchToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.rAMSearchToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
this.rAMSearchToolStripMenuItem.Text = "RAM &Search";
this.rAMSearchToolStripMenuItem.Click += new System.EventHandler(this.rAMSearchToolStripMenuItem_Click);
//
// rAMPokeToolStripMenuItem
//
this.rAMPokeToolStripMenuItem.Name = "rAMPokeToolStripMenuItem";
this.rAMPokeToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.rAMPokeToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
this.rAMPokeToolStripMenuItem.Text = "RAM &Poke";
this.rAMPokeToolStripMenuItem.Click += new System.EventHandler(this.rAMPokeToolStripMenuItem_Click);
this.rAMPokeToolStripMenuItem.Click += new System.EventHandler(this.RAMPokeToolStripMenuItem_Click);
//
// hexEditorToolStripMenuItem
//
this.hexEditorToolStripMenuItem.Name = "hexEditorToolStripMenuItem";
this.hexEditorToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.hexEditorToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
this.hexEditorToolStripMenuItem.Text = "&Hex Editor";
this.hexEditorToolStripMenuItem.Click += new System.EventHandler(this.hexEditorToolStripMenuItem_Click);
//
// luaConsoleToolStripMenuItem
//
this.luaConsoleToolStripMenuItem.Name = "luaConsoleToolStripMenuItem";
this.luaConsoleToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.luaConsoleToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
this.luaConsoleToolStripMenuItem.Text = "Lua Console";
this.luaConsoleToolStripMenuItem.Click += new System.EventHandler(this.luaConsoleToolStripMenuItem_Click);
//
// toolStripSeparator11
//
this.toolStripSeparator11.Name = "toolStripSeparator11";
this.toolStripSeparator11.Size = new System.Drawing.Size(140, 6);
//
// cheatsToolStripMenuItem
//
this.cheatsToolStripMenuItem.Name = "cheatsToolStripMenuItem";
this.cheatsToolStripMenuItem.Size = new System.Drawing.Size(143, 22);
this.cheatsToolStripMenuItem.Text = "Cheats";
this.cheatsToolStripMenuItem.Click += new System.EventHandler(this.cheatsToolStripMenuItem_Click);
//
// NESToolStripMenuItem
//
this.NESToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -1193,7 +1207,7 @@
this.pPUViewerToolStripMenuItem.Name = "pPUViewerToolStripMenuItem";
this.pPUViewerToolStripMenuItem.Size = new System.Drawing.Size(228, 22);
this.pPUViewerToolStripMenuItem.Text = "&PPU Viewer";
this.pPUViewerToolStripMenuItem.Click += new System.EventHandler(this.pPUViewerToolStripMenuItem_Click);
this.pPUViewerToolStripMenuItem.Click += new System.EventHandler(this.PPUViewerToolStripMenuItem_Click);
//
// gameGenieCodesToolStripMenuItem
//
@ -1226,17 +1240,12 @@
this.aboutToolStripMenuItem.Text = "&About";
this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
//
// toolStripSeparator11
// forceGDIPPresentationToolStripMenuItem
//
this.toolStripSeparator11.Name = "toolStripSeparator11";
this.toolStripSeparator11.Size = new System.Drawing.Size(149, 6);
//
// cheatsToolStripMenuItem
//
this.cheatsToolStripMenuItem.Name = "cheatsToolStripMenuItem";
this.cheatsToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.cheatsToolStripMenuItem.Text = "Cheats";
this.cheatsToolStripMenuItem.Click += new System.EventHandler(this.cheatsToolStripMenuItem_Click);
this.forceGDIPPresentationToolStripMenuItem.Name = "forceGDIPPresentationToolStripMenuItem";
this.forceGDIPPresentationToolStripMenuItem.Size = new System.Drawing.Size(220, 22);
this.forceGDIPPresentationToolStripMenuItem.Text = "Force GDI+ Presentation";
this.forceGDIPPresentationToolStripMenuItem.Click += new System.EventHandler(this.forceGDIPPresentationToolStripMenuItem_Click);
//
// MainForm
//
@ -1395,6 +1404,7 @@
private System.Windows.Forms.ToolStripMenuItem enableRewindToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator11;
private System.Windows.Forms.ToolStripMenuItem cheatsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem forceGDIPPresentationToolStripMenuItem;
}
}

View File

@ -16,7 +16,7 @@ namespace BizHawk.MultiClient
{
partial class MainForm
{
private void rAMPokeToolStripMenuItem_Click(object sender, EventArgs e)
private void RAMPokeToolStripMenuItem_Click(object sender, EventArgs e)
{
RamPoke r = new RamPoke();
r.Show();
@ -383,6 +383,48 @@ namespace BizHawk.MultiClient
LoadRom(file.FullName);
}
private void replayInputLogToolStripMenuItem_Click(object sender, EventArgs e)
{
InputLog.StopMovie();
InputLog.StartPlayback();
LoadRom(CurrentlyOpenRom);
}
private void PPUViewerToolStripMenuItem_Click(object sender, EventArgs e)
{
LoadNESPPU();
}
private void enableRewindToolStripMenuItem_Click(object sender, EventArgs e)
{
Global.Config.RewindEnabled ^= true;
}
private void hexEditorToolStripMenuItem_Click(object sender, EventArgs e)
{
LoadHexEditor();
}
private void MainForm_Shown(object sender, EventArgs e)
{
HandlePlatformMenus();
}
private void gameGenieCodesToolStripMenuItem_Click(object sender, EventArgs e)
{
LoadGameGenieEC();
}
private void cheatsToolStripMenuItem_Click(object sender, EventArgs e)
{
LoadCheatsWindow();
}
private void forceGDIPPresentationToolStripMenuItem_Click(object sender, EventArgs e)
{
Global.Config.ForceGDI ^= true;
SyncPresentationMode();
}
}
}

View File

@ -52,6 +52,8 @@ namespace BizHawk.MultiClient
public MainForm(string[] args)
{
InitializeComponent();
//in order to allow late construction of this database, we hook up a delegate here to dearchive the data and provide it on demand
//we could background thread this later instead if we wanted to be real clever
NES.BootGodDB.GetDatabaseBytes = () => {
@ -60,28 +62,10 @@ namespace BizHawk.MultiClient
};
Global.MainForm = this;
Global.Config = ConfigService.Load<Config>("config.ini");
if (Global.Direct3D != null)
renderTarget = new ViewportPanel();
else renderTarget = retainedPanel = new RetainedViewportPanel();
renderTarget.Dock = DockStyle.Fill;
renderTarget.BackColor = Color.Black;
Controls.Add(renderTarget);
InitializeComponent();
Database.LoadDatabase("gamedb.txt");
if (Global.Direct3D != null)
{
Global.RenderPanel = new Direct3DRenderPanel(Global.Direct3D, renderTarget);
}
else
{
Global.RenderPanel = new SysdrawingRenderPanel(retainedPanel);
}
SyncPresentationMode();
Load += (o, e) =>
{
@ -160,6 +144,44 @@ namespace BizHawk.MultiClient
PauseEmulator();
}
void SyncPresentationMode()
{
bool gdi = Global.Config.ForceGDI;
if (Global.Direct3D == null)
{
gdi = Global.Config.ForceGDI = true;
}
if (renderTarget != null)
{
renderTarget.Dispose();
Controls.Remove(renderTarget);
}
if (retainedPanel != null) retainedPanel.Dispose();
if (Global.RenderPanel != null) Global.RenderPanel.Dispose();
if (gdi)
renderTarget = retainedPanel = new RetainedViewportPanel();
else renderTarget = new ViewportPanel();
Controls.Add(renderTarget);
Controls.SetChildIndex(renderTarget, 0);
renderTarget.Dock = DockStyle.Fill;
renderTarget.BackColor = Color.Black;
if (gdi)
{
Global.RenderPanel = new SysdrawingRenderPanel(retainedPanel);
retainedPanel.ActivateThreaded();
}
else
{
Global.RenderPanel = new Direct3DRenderPanel(Global.Direct3D, renderTarget);
}
}
void SetSpeedPercent(int value)
{
Global.Config.SpeedPercent = value;
@ -503,7 +525,7 @@ namespace BizHawk.MultiClient
Global.Game.Name = (Global.Emulator as NES).GameName;
}
Text = DisplayNameForSystem(game.System) + " - " + game.Name;
Text = DisplayNameForSystem(game.System) + " - " + game.Name + " \\";
ResetRewindBuffer();
Global.Config.RecentRoms.Add(file.CanonicalName);
if (File.Exists(game.SaveRamPath))
@ -731,6 +753,8 @@ namespace BizHawk.MultiClient
{
runloop_second = DateTime.Now;
Global.RenderPanel.FPS = runloop_fps;
Text = Text.Substring(0, Text.IndexOf('\\')) + "\\ " + runloop_fps + " fps";
Global.RenderPanel.FPS = runloop_fps;
runloop_fps = 0;
}
@ -1179,6 +1203,7 @@ namespace BizHawk.MultiClient
saveWindowPositionToolStripMenuItem.Checked = Global.Config.SaveWindowPosition;
startPausedToolStripMenuItem.Checked = Global.Config.StartPaused;
enableRewindToolStripMenuItem.Checked = Global.Config.RewindEnabled;
forceGDIPPresentationToolStripMenuItem.Checked = Global.Config.ForceGDI;
}
private void MainForm_Load(object sender, EventArgs e)
@ -1245,41 +1270,6 @@ namespace BizHawk.MultiClient
ConfigService.Save("config.ini", Global.Config);
}
private void replayInputLogToolStripMenuItem_Click(object sender, EventArgs e)
{
InputLog.StopMovie();
InputLog.StartPlayback();
LoadRom(CurrentlyOpenRom);
}
private void pPUViewerToolStripMenuItem_Click(object sender, EventArgs e)
{
LoadNESPPU();
}
private void enableRewindToolStripMenuItem_Click(object sender, EventArgs e)
{
Global.Config.RewindEnabled ^= true;
}
private void hexEditorToolStripMenuItem_Click(object sender, EventArgs e)
{
LoadHexEditor();
}
private void MainForm_Shown(object sender, EventArgs e)
{
HandlePlatformMenus();
}
private void gameGenieCodesToolStripMenuItem_Click(object sender, EventArgs e)
{
LoadGameGenieEC();
}
private void cheatsToolStripMenuItem_Click(object sender, EventArgs e)
{
LoadCheatsWindow();
}
}
}

View File

@ -13,6 +13,8 @@ namespace BizHawk.MultiClient
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Global.Config = ConfigService.Load<Config>("config.ini");
try { Global.DSound = new DirectSound(); }
catch {
MessageBox.Show("Couldn't initialize DirectSound!");
@ -20,8 +22,10 @@ namespace BizHawk.MultiClient
}
try { Global.Direct3D = new Direct3D(); }
catch {
catch
{
//can fallback to GDI rendering
Global.Config.ForceGDI = true;
}
try {

View File

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
@ -11,17 +13,96 @@ namespace BizHawk.Core
/// </summary>
public class RetainedViewportPanel : Control
{
Thread threadPaint;
EventWaitHandle ewh;
volatile bool killSignal;
/// <summary>
/// Turns this panel into multi-threaded mode.
/// This will sort of glitch out other gdi things on the system, but at least its fast...
/// </summary>
public void ActivateThreaded()
{
ewh = new EventWaitHandle(false, EventResetMode.AutoReset);
threadPaint = new Thread(PaintProc);
threadPaint.Start();
}
public RetainedViewportPanel()
{
CreateHandle();
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.DoubleBuffer, false);
SetStyle(ControlStyles.Opaque, true);
SetStyle(ControlStyles.UserMouse, true);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (threadPaint != null)
{
killSignal = true;
ewh.Set();
ewh.WaitOne();
}
CleanupDisposeQueue();
}
void DoPaint()
{
if (bmp != null)
{
using (Graphics g = CreateGraphics())
{
g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.CompositingMode = CompositingMode.SourceCopy;
g.CompositingQuality = CompositingQuality.HighSpeed;
g.DrawImage(bmp, 0, 0, Width, Height);
}
}
CleanupDisposeQueue();
}
void PaintProc()
{
for (; ; )
{
ewh.WaitOne();
if (killSignal)
{
ewh.Set();
return;
}
DoPaint();
}
}
void CleanupDisposeQueue()
{
lock (this)
{
while (DisposeQueue.Count > 0)
DisposeQueue.Dequeue().Dispose();
}
}
Queue<Bitmap> DisposeQueue = new Queue<Bitmap>();
void SignalPaint()
{
if (threadPaint == null)
DoPaint();
else
ewh.Set();
}
//Size logicalSize;
////int pitch;
//public void SetLogicalSize(int w, int h)
@ -36,24 +117,26 @@ namespace BizHawk.Core
/// </summary>
public void SetBitmap(Bitmap newbmp)
{
if (bmp != null) bmp.Dispose();
lock (this)
{
if(bmp != null) DisposeQueue.Enqueue(bmp);
bmp = newbmp;
Refresh();
}
SignalPaint();
}
Bitmap bmp;
protected override void OnPaintBackground(PaintEventArgs pevent)
{
}
protected override void OnPaint(PaintEventArgs e)
{
SignalPaint();
base.OnPaint(e);
if (bmp != null)
{
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
e.Graphics.CompositingMode = CompositingMode.SourceCopy;
e.Graphics.CompositingQuality = CompositingQuality.HighSpeed;
e.Graphics.DrawImage(bmp, 0, 0, Width, Height);
}
}
}