gdi+ display method!

This commit is contained in:
zeromus 2014-12-07 02:26:52 +00:00
parent 415fda2373
commit 556b7b0123
25 changed files with 1794 additions and 180 deletions

View File

@ -105,6 +105,8 @@ namespace BizHawk.Client.Common
}
}
public enum EDispMethod { OpenGL, GdiPlus };
public enum EDispManagerAR { None, System, Custom };
public enum SaveStateTypeE { Default, Binary, Text };
@ -204,6 +206,9 @@ namespace BizHawk.Client.Common
public bool DispFixScaleInteger = true;
public bool DispFullscreenHacks = true;
//warning: we dont even want to deal with changing this at runtime. but we want it changed here for config purposes. so dont check this variable. check in GlobalWin or something like that.
public EDispMethod DispMethod = EDispMethod.OpenGL;
public EDispManagerAR DispManagerAR = EDispManagerAR.System;
public int DispCustomUserARWidth = 1;
public int DispCustomUserARHeight = 1;

View File

@ -1436,6 +1436,10 @@
<Project>{f51946ea-827f-4d82-b841-1f2f6d060312}</Project>
<Name>BizHawk.Emulation.DiscSystem</Name>
</ProjectReference>
<ProjectReference Include="..\Bizware\BizHawk.Bizware.BizwareGL.GdiPlus\BizHawk.Bizware.BizwareGL.GdiPlus.csproj">
<Project>{337CA23E-65E7-44E1-9411-97EE08BB8116}</Project>
<Name>BizHawk.Bizware.BizwareGL.GdiPlus</Name>
</ProjectReference>
<ProjectReference Include="..\Bizware\BizHawk.Bizware.BizwareGL.OpenTK\BizHawk.Bizware.BizwareGL.OpenTK.csproj">
<Project>{5160CFB1-5389-47C1-B7F6-8A0DC97641EE}</Project>
<Name>BizHawk.Bizware.BizwareGL.OpenTK</Name>

View File

@ -13,6 +13,7 @@ using BizHawk.Client.EmuHawk.FilterManager;
using BizHawk.Bizware.BizwareGL;
using OpenTK;
using BizHawk.Bizware.BizwareGL.Drivers.GdiPlus;
namespace BizHawk.Client.EmuHawk
{
@ -43,7 +44,10 @@ namespace BizHawk.Client.EmuHawk
//it's sort of important for these to be initialized to something nonzero
currEmuWidth = currEmuHeight = 1;
Renderer = new GuiRenderer(GL);
if (GL is BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK)
Renderer = new GuiRenderer(GL);
else
Renderer = new GDIPlusGuiRenderer((BizHawk.Bizware.BizwareGL.Drivers.GdiPlus.IGL_GdiPlus)GL);
VideoTextureFrugalizer = new TextureFrugalizer(GL);
@ -57,18 +61,21 @@ namespace BizHawk.Client.EmuHawk
using (var tex = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.courier16px_0.png"))
TheOneFont = new StringRenderer(GL, xml, tex);
var fiHq2x = new FileInfo(Path.Combine(PathManager.GetExeDirectoryAbsolute(),"Shaders/BizHawk/hq2x.cgp"));
if(fiHq2x.Exists)
using(var stream = fiHq2x.OpenRead())
ShaderChain_hq2x = new Filters.RetroShaderChain(GL, new Filters.RetroShaderPreset(stream), Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk"));
var fiScanlines = new FileInfo(Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk/BizScanlines.cgp"));
if (fiScanlines.Exists)
using (var stream = fiScanlines.OpenRead())
ShaderChain_scanlines = new Filters.RetroShaderChain(GL, new Filters.RetroShaderPreset(stream), Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk"));
var fiBicubic = new FileInfo(Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk/bicubic-fast.cgp"));
if (fiBicubic.Exists)
using (var stream = fiBicubic.OpenRead())
ShaderChain_bicubic = new Filters.RetroShaderChain(GL, new Filters.RetroShaderPreset(stream), Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk"));
if (GL is BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK)
{
var fiHq2x = new FileInfo(Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk/hq2x.cgp"));
if (fiHq2x.Exists)
using (var stream = fiHq2x.OpenRead())
ShaderChain_hq2x = new Filters.RetroShaderChain(GL, new Filters.RetroShaderPreset(stream), Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk"));
var fiScanlines = new FileInfo(Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk/BizScanlines.cgp"));
if (fiScanlines.Exists)
using (var stream = fiScanlines.OpenRead())
ShaderChain_scanlines = new Filters.RetroShaderChain(GL, new Filters.RetroShaderPreset(stream), Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk"));
var fiBicubic = new FileInfo(Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk/bicubic-fast.cgp"));
if (fiBicubic.Exists)
using (var stream = fiBicubic.OpenRead())
ShaderChain_bicubic = new Filters.RetroShaderChain(GL, new Filters.RetroShaderPreset(stream), Path.Combine(PathManager.GetExeDirectoryAbsolute(), "Shaders/BizHawk"));
}
LuaSurfaceSets["emu"] = new SwappableDisplaySurfaceSet();
LuaSurfaceSets["native"] = new SwappableDisplaySurfaceSet();
@ -98,7 +105,7 @@ namespace BizHawk.Client.EmuHawk
//rendering resources:
public IGL GL;
StringRenderer TheOneFont;
GuiRenderer Renderer;
IGuiRenderer Renderer;
//layer resources
PresentationPanel presentationPanel; //well, its the final layer's target, at least
@ -180,7 +187,7 @@ namespace BizHawk.Client.EmuHawk
if (Global.Config.DispFinalFilter == 1) finalFilter = Filters.FinalPresentation.eFilterOption.Bilinear;
if (Global.Config.DispFinalFilter == 2) finalFilter = Filters.FinalPresentation.eFilterOption.Bicubic;
//if bicubic is selected and unavailable, dont use it
if (!ShaderChain_bicubic.Available && fPresent.FilterOption == Filters.FinalPresentation.eFilterOption.Bicubic)
if (ShaderChain_bicubic != null && !ShaderChain_bicubic.Available && fPresent.FilterOption == Filters.FinalPresentation.eFilterOption.Bicubic)
{
finalFilter = Filters.FinalPresentation.eFilterOption.None;
}
@ -471,16 +478,13 @@ TESTEROO:
int bufferHeight = videoProvider.BufferHeight;
bool isGlTextureId = videoBuffer.Length == 1;
//TODO - need to do some work here for GDI+ to repair gl texture ID importing
BitmapBuffer bb = null;
Texture2d videoTexture = null;
if (!simulate)
{
if (isGlTextureId)
{
videoTexture = GL.WrapGLTexture2d(new IntPtr(videoBuffer[0]), bufferWidth, bufferHeight);
}
else
//special codepath for GDI+
if (GL is IGL_GdiPlus)
{
//wrap the videoprovider data in a BitmapBuffer (no point to refactoring that many IVideoProviders)
bb = new BitmapBuffer(bufferWidth, bufferHeight, videoBuffer);
@ -489,12 +493,28 @@ TESTEROO:
videoTexture = VideoTextureFrugalizer.Get(bb);
GL.SetTextureWrapMode(videoTexture, true);
}
//TEST (to be removed once we have an actual example of bring in a texture ID from opengl emu core):
if (!isGlTextureId)
else
{
videoBuffer = new int[1] { videoTexture.Id.ToInt32() };
goto TESTEROO;
if (isGlTextureId)
{
videoTexture = GL.WrapGLTexture2d(new IntPtr(videoBuffer[0]), bufferWidth, bufferHeight);
}
else
{
//wrap the videoprovider data in a BitmapBuffer (no point to refactoring that many IVideoProviders)
bb = new BitmapBuffer(bufferWidth, bufferHeight, videoBuffer);
//now, acquire the data sent from the videoProvider into a texture
videoTexture = VideoTextureFrugalizer.Get(bb);
GL.SetTextureWrapMode(videoTexture, true);
}
//TEST (to be removed once we have an actual example of bring in a texture ID from opengl emu core):
if (!isGlTextureId)
{
videoBuffer = new int[1] { videoTexture.Id.ToInt32() };
goto TESTEROO;
}
}
}

View File

@ -69,7 +69,7 @@ namespace BizHawk.Client.EmuHawk.FilterManager
}
//services to filters:
public GuiRenderer GuiRenderer;
public IGuiRenderer GuiRenderer;
public IGL GL;
public IRenderTargetProvider RenderTargetProvider;
public RenderTarget GetRenderTarget(string channel = "default") { return CurrRenderTarget; }

View File

@ -172,7 +172,7 @@ namespace BizHawk.Client.EmuHawk.Filters
Size OutputSize, InputSize;
public Size TextureSize, VirtualTextureSize;
public int BackgroundColor;
public GuiRenderer GuiRenderer;
public IGuiRenderer GuiRenderer;
public IGL GL;
bool nop;
LetterboxingLogic LL;
@ -261,7 +261,7 @@ namespace BizHawk.Client.EmuHawk.Filters
GuiRenderer.Begin(OutputSize.Width, OutputSize.Height);
GuiRenderer.SetBlendState(GL.BlendNone);
GuiRenderer.Modelview.Push();
if(FilterOption != eFilterOption.None)
InputTexture.SetFilterLinear();
else

View File

@ -62,7 +62,7 @@ namespace BizHawk.Client.EmuHawk.Filters
public override void Run()
{
GuiRenderer renderer = FilterProgram.GuiRenderer;
var renderer = FilterProgram.GuiRenderer;
renderer.Begin(FindOutput().SurfaceFormat.Size);
renderer.SetBlendState(FilterProgram.GL.BlendNone);
renderer.Draw(InputTexture);

View File

@ -12,6 +12,7 @@ namespace BizHawk.Client.EmuHawk
public static DirectSound DSound;
#endif
public static IGL GL;
public static Bizware.BizwareGL.Drivers.OpenTK.IGL_TK IGL_GL;
public static GLManager.ContextRef CR_GL;
public static Sound Sound;
public static PresentationPanel PresentationPanel;

View File

@ -77,9 +77,12 @@ namespace BizHawk.Client.EmuHawk
}
#endif
//create IGL context.
//at some point in the future, we may need to select from several drivers
GlobalWin.GL = new Bizware.BizwareGL.Drivers.OpenTK.IGL_TK();
//create IGL context. we do this whether or not the user has selected OpenGL, so that we can run opengl-based emulator cores
GlobalWin.IGL_GL = new Bizware.BizwareGL.Drivers.OpenTK.IGL_TK();
if(Global.Config.DispMethod == Config.EDispMethod.GdiPlus)
GlobalWin.GL = new Bizware.BizwareGL.Drivers.GdiPlus.IGL_GdiPlus();
else
GlobalWin.GL = new Bizware.BizwareGL.Drivers.OpenTK.IGL_TK();
GlobalWin.GLManager = new GLManager();
GlobalWin.CR_GL = GlobalWin.GLManager.GetContextForIGL(GlobalWin.GL);

View File

@ -49,28 +49,41 @@
this.rbUseRaw = new System.Windows.Forms.RadioButton();
this.rbUseSystem = new System.Windows.Forms.RadioButton();
this.grpARSelection = new System.Windows.Forms.GroupBox();
this.label4 = new System.Windows.Forms.Label();
this.txtCustomARHeight = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.txtCustomARWidth = new System.Windows.Forms.TextBox();
this.rbUseCustom = new System.Windows.Forms.RadioButton();
this.checkFullscreenHacks = new System.Windows.Forms.CheckBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.label2 = new System.Windows.Forms.Label();
this.checkSnowyNullEmulator = new System.Windows.Forms.CheckBox();
this.label1 = new System.Windows.Forms.Label();
this.rbUseCustom = new System.Windows.Forms.RadioButton();
this.txtCustomARWidth = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.txtCustomARHeight = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.rbOpenGL = new System.Windows.Forms.RadioButton();
this.label5 = new System.Windows.Forms.Label();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tpAR = new System.Windows.Forms.TabPage();
this.tpDispMethod = new System.Windows.Forms.TabPage();
this.tpMisc = new System.Windows.Forms.TabPage();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.rbGDIPlus = new System.Windows.Forms.RadioButton();
this.label6 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.tbScanlineIntensity)).BeginInit();
this.grpFinalFilter.SuspendLayout();
this.grpARSelection.SuspendLayout();
this.groupBox2.SuspendLayout();
this.tabControl1.SuspendLayout();
this.tpAR.SuspendLayout();
this.tpDispMethod.SuspendLayout();
this.tpMisc.SuspendLayout();
this.groupBox3.SuspendLayout();
this.SuspendLayout();
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(544, 297);
this.btnCancel.Location = new System.Drawing.Point(360, 404);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 5;
@ -80,7 +93,7 @@
// btnOk
//
this.btnOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnOk.Location = new System.Drawing.Point(463, 297);
this.btnOk.Location = new System.Drawing.Point(279, 404);
this.btnOk.Name = "btnOk";
this.btnOk.Size = new System.Drawing.Size(75, 23);
this.btnOk.TabIndex = 4;
@ -98,7 +111,7 @@
this.groupBox1.Controls.Add(this.rbNone);
this.groupBox1.Controls.Add(this.rbScanlines);
this.groupBox1.Controls.Add(this.rbHq2x);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Location = new System.Drawing.Point(6, 6);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(193, 132);
this.groupBox1.TabIndex = 7;
@ -193,7 +206,7 @@
// checkLetterbox
//
this.checkLetterbox.AutoSize = true;
this.checkLetterbox.Location = new System.Drawing.Point(12, 154);
this.checkLetterbox.Location = new System.Drawing.Point(6, 148);
this.checkLetterbox.Name = "checkLetterbox";
this.checkLetterbox.Size = new System.Drawing.Size(173, 17);
this.checkLetterbox.TabIndex = 8;
@ -204,7 +217,7 @@
// checkPadInteger
//
this.checkPadInteger.AutoSize = true;
this.checkPadInteger.Location = new System.Drawing.Point(21, 290);
this.checkPadInteger.Location = new System.Drawing.Point(15, 284);
this.checkPadInteger.Name = "checkPadInteger";
this.checkPadInteger.Size = new System.Drawing.Size(248, 17);
this.checkPadInteger.TabIndex = 9;
@ -217,7 +230,7 @@
this.grpFinalFilter.Controls.Add(this.rbFinalFilterBicubic);
this.grpFinalFilter.Controls.Add(this.rbFinalFilterNone);
this.grpFinalFilter.Controls.Add(this.rbFinalFilterBilinear);
this.grpFinalFilter.Location = new System.Drawing.Point(211, 12);
this.grpFinalFilter.Location = new System.Drawing.Point(205, 6);
this.grpFinalFilter.Name = "grpFinalFilter";
this.grpFinalFilter.Size = new System.Drawing.Size(187, 132);
this.grpFinalFilter.TabIndex = 8;
@ -290,62 +303,44 @@
this.grpARSelection.Controls.Add(this.rbUseCustom);
this.grpARSelection.Controls.Add(this.rbUseRaw);
this.grpARSelection.Controls.Add(this.rbUseSystem);
this.grpARSelection.Location = new System.Drawing.Point(21, 177);
this.grpARSelection.Location = new System.Drawing.Point(15, 171);
this.grpARSelection.Name = "grpARSelection";
this.grpARSelection.Size = new System.Drawing.Size(377, 107);
this.grpARSelection.TabIndex = 13;
this.grpARSelection.TabStop = false;
this.grpARSelection.Text = "Aspect Ratio Selection";
//
// checkFullscreenHacks
// label4
//
this.checkFullscreenHacks.AutoSize = true;
this.checkFullscreenHacks.Location = new System.Drawing.Point(6, 19);
this.checkFullscreenHacks.Name = "checkFullscreenHacks";
this.checkFullscreenHacks.Size = new System.Drawing.Size(191, 17);
this.checkFullscreenHacks.TabIndex = 14;
this.checkFullscreenHacks.Text = "Enable Windows Fullscreen Hacks";
this.checkFullscreenHacks.UseVisualStyleBackColor = true;
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(23, 41);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(257, 13);
this.label4.TabIndex = 12;
this.label4.Text = "Allow pixel distortion (e.g. 2x1 pixels, for better AR fit):";
//
// groupBox2
// txtCustomARHeight
//
this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Controls.Add(this.checkSnowyNullEmulator);
this.groupBox2.Controls.Add(this.label1);
this.groupBox2.Controls.Add(this.checkFullscreenHacks);
this.groupBox2.Location = new System.Drawing.Point(404, 12);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(217, 272);
this.groupBox2.TabIndex = 15;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Misc.";
this.txtCustomARHeight.Location = new System.Drawing.Point(230, 79);
this.txtCustomARHeight.Name = "txtCustomARHeight";
this.txtCustomARHeight.Size = new System.Drawing.Size(72, 20);
this.txtCustomARHeight.TabIndex = 15;
//
// label2
// label3
//
this.label2.Location = new System.Drawing.Point(7, 190);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(204, 45);
this.label2.TabIndex = 17;
this.label2.Text = "Some people think the whitenoise is a great idea, and some people don\'t. Enabling" +
" this displays an Oxoo instead.";
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(212, 84);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(12, 13);
this.label3.TabIndex = 12;
this.label3.Text = "x";
//
// checkSnowyNullEmulator
// txtCustomARWidth
//
this.checkSnowyNullEmulator.AutoSize = true;
this.checkSnowyNullEmulator.Location = new System.Drawing.Point(6, 165);
this.checkSnowyNullEmulator.Name = "checkSnowyNullEmulator";
this.checkSnowyNullEmulator.Size = new System.Drawing.Size(159, 17);
this.checkSnowyNullEmulator.TabIndex = 16;
this.checkSnowyNullEmulator.Text = "Enable Snowy Null Emulator";
this.checkSnowyNullEmulator.UseVisualStyleBackColor = true;
//
// label1
//
this.label1.Location = new System.Drawing.Point(7, 42);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(204, 117);
this.label1.TabIndex = 15;
this.label1.Text = resources.GetString("label1.Text");
this.txtCustomARWidth.Location = new System.Drawing.Point(134, 79);
this.txtCustomARWidth.Name = "txtCustomARWidth";
this.txtCustomARWidth.Size = new System.Drawing.Size(72, 20);
this.txtCustomARWidth.TabIndex = 14;
//
// rbUseCustom
//
@ -358,37 +353,157 @@
this.rbUseCustom.Text = "Use custom Size:";
this.rbUseCustom.UseVisualStyleBackColor = true;
//
// txtCustomARWidth
// checkFullscreenHacks
//
this.txtCustomARWidth.Location = new System.Drawing.Point(134, 79);
this.txtCustomARWidth.Name = "txtCustomARWidth";
this.txtCustomARWidth.Size = new System.Drawing.Size(72, 20);
this.txtCustomARWidth.TabIndex = 14;
this.checkFullscreenHacks.AutoSize = true;
this.checkFullscreenHacks.Location = new System.Drawing.Point(2, 7);
this.checkFullscreenHacks.Name = "checkFullscreenHacks";
this.checkFullscreenHacks.Size = new System.Drawing.Size(191, 17);
this.checkFullscreenHacks.TabIndex = 14;
this.checkFullscreenHacks.Text = "Enable Windows Fullscreen Hacks";
this.checkFullscreenHacks.UseVisualStyleBackColor = true;
//
// label3
// label2
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(212, 84);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(12, 13);
this.label3.TabIndex = 12;
this.label3.Text = "x";
this.label2.Location = new System.Drawing.Point(3, 131);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(398, 45);
this.label2.TabIndex = 17;
this.label2.Text = "Some people think the whitenoise is a great idea, and some people don\'t. Enabling" +
" this displays an Oxoo instead.";
//
// txtCustomARHeight
// checkSnowyNullEmulator
//
this.txtCustomARHeight.Location = new System.Drawing.Point(230, 79);
this.txtCustomARHeight.Name = "txtCustomARHeight";
this.txtCustomARHeight.Size = new System.Drawing.Size(72, 20);
this.txtCustomARHeight.TabIndex = 15;
this.checkSnowyNullEmulator.AutoSize = true;
this.checkSnowyNullEmulator.Location = new System.Drawing.Point(2, 106);
this.checkSnowyNullEmulator.Name = "checkSnowyNullEmulator";
this.checkSnowyNullEmulator.Size = new System.Drawing.Size(159, 17);
this.checkSnowyNullEmulator.TabIndex = 16;
this.checkSnowyNullEmulator.Text = "Enable Snowy Null Emulator";
this.checkSnowyNullEmulator.UseVisualStyleBackColor = true;
//
// label4
// label1
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(23, 41);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(257, 13);
this.label4.TabIndex = 12;
this.label4.Text = "Allow pixel distortion (e.g. 2x1 pixels, for better AR fit):";
this.label1.Location = new System.Drawing.Point(3, 30);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(398, 73);
this.label1.TabIndex = 15;
this.label1.Text = resources.GetString("label1.Text");
//
// rbOpenGL
//
this.rbOpenGL.AutoSize = true;
this.rbOpenGL.Checked = true;
this.rbOpenGL.Location = new System.Drawing.Point(9, 19);
this.rbOpenGL.Name = "rbOpenGL";
this.rbOpenGL.Size = new System.Drawing.Size(65, 17);
this.rbOpenGL.TabIndex = 3;
this.rbOpenGL.TabStop = true;
this.rbOpenGL.Text = "OpenGL";
this.rbOpenGL.UseVisualStyleBackColor = true;
//
// label5
//
this.label5.Location = new System.Drawing.Point(24, 39);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(359, 47);
this.label5.TabIndex = 16;
this.label5.Text = " • May malfunction on some systems.\r\n • May have increased performance for OpenGL" +
"-based emulation cores.\r\n • May have reduced performance on some systems.\r\n";
//
// tabControl1
//
this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.tabControl1.Controls.Add(this.tpAR);
this.tabControl1.Controls.Add(this.tpDispMethod);
this.tabControl1.Controls.Add(this.tpMisc);
this.tabControl1.Location = new System.Drawing.Point(12, 12);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(423, 382);
this.tabControl1.TabIndex = 17;
//
// tpAR
//
this.tpAR.Controls.Add(this.groupBox1);
this.tpAR.Controls.Add(this.checkLetterbox);
this.tpAR.Controls.Add(this.checkPadInteger);
this.tpAR.Controls.Add(this.grpARSelection);
this.tpAR.Controls.Add(this.grpFinalFilter);
this.tpAR.Location = new System.Drawing.Point(4, 22);
this.tpAR.Name = "tpAR";
this.tpAR.Padding = new System.Windows.Forms.Padding(3);
this.tpAR.Size = new System.Drawing.Size(415, 356);
this.tpAR.TabIndex = 0;
this.tpAR.Text = "Scaling & Filtering";
this.tpAR.UseVisualStyleBackColor = true;
//
// tpDispMethod
//
this.tpDispMethod.Controls.Add(this.label6);
this.tpDispMethod.Controls.Add(this.groupBox3);
this.tpDispMethod.Location = new System.Drawing.Point(4, 22);
this.tpDispMethod.Name = "tpDispMethod";
this.tpDispMethod.Size = new System.Drawing.Size(415, 356);
this.tpDispMethod.TabIndex = 2;
this.tpDispMethod.Text = "Display Method";
this.tpDispMethod.UseVisualStyleBackColor = true;
//
// tpMisc
//
this.tpMisc.Controls.Add(this.label2);
this.tpMisc.Controls.Add(this.checkSnowyNullEmulator);
this.tpMisc.Controls.Add(this.checkFullscreenHacks);
this.tpMisc.Controls.Add(this.label1);
this.tpMisc.Location = new System.Drawing.Point(4, 22);
this.tpMisc.Name = "tpMisc";
this.tpMisc.Size = new System.Drawing.Size(415, 356);
this.tpMisc.TabIndex = 3;
this.tpMisc.Text = "Misc";
this.tpMisc.UseVisualStyleBackColor = true;
//
// groupBox3
//
this.groupBox3.Controls.Add(this.label7);
this.groupBox3.Controls.Add(this.rbGDIPlus);
this.groupBox3.Controls.Add(this.label5);
this.groupBox3.Controls.Add(this.rbOpenGL);
this.groupBox3.Location = new System.Drawing.Point(4, 3);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(389, 165);
this.groupBox3.TabIndex = 16;
this.groupBox3.TabStop = false;
//
// rbGDIPlus
//
this.rbGDIPlus.AutoSize = true;
this.rbGDIPlus.Checked = true;
this.rbGDIPlus.Location = new System.Drawing.Point(6, 89);
this.rbGDIPlus.Name = "rbGDIPlus";
this.rbGDIPlus.Size = new System.Drawing.Size(50, 17);
this.rbGDIPlus.TabIndex = 17;
this.rbGDIPlus.TabStop = true;
this.rbGDIPlus.Text = "GDI+";
this.rbGDIPlus.UseVisualStyleBackColor = true;
//
// label6
//
this.label6.Location = new System.Drawing.Point(3, 171);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(359, 47);
this.label6.TabIndex = 18;
this.label6.Text = "Changes require restart of program to take effect.\r\n";
//
// label7
//
this.label7.Location = new System.Drawing.Point(24, 109);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(359, 47);
this.label7.TabIndex = 18;
this.label7.Text = " • Mainly for compatibility purposes\r\n • Missing some features\r\n • Works better o" +
"ver Remote Desktop, etc.\r\n";
//
// DisplayConfigLite
//
@ -396,13 +511,8 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(631, 332);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.grpARSelection);
this.Controls.Add(this.grpFinalFilter);
this.Controls.Add(this.checkPadInteger);
this.Controls.Add(this.checkLetterbox);
this.Controls.Add(this.groupBox1);
this.ClientSize = new System.Drawing.Size(451, 439);
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOk);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
@ -416,10 +526,15 @@
this.grpFinalFilter.PerformLayout();
this.grpARSelection.ResumeLayout(false);
this.grpARSelection.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.tabControl1.ResumeLayout(false);
this.tpAR.ResumeLayout(false);
this.tpAR.PerformLayout();
this.tpDispMethod.ResumeLayout(false);
this.tpMisc.ResumeLayout(false);
this.tpMisc.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
@ -445,7 +560,6 @@
private System.Windows.Forms.RadioButton rbUseSystem;
private System.Windows.Forms.GroupBox grpARSelection;
private System.Windows.Forms.CheckBox checkFullscreenHacks;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.CheckBox checkSnowyNullEmulator;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
@ -455,5 +569,15 @@
private System.Windows.Forms.TextBox txtCustomARWidth;
private System.Windows.Forms.RadioButton rbUseCustom;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.RadioButton rbOpenGL;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tpAR;
private System.Windows.Forms.TabPage tpDispMethod;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.RadioButton rbGDIPlus;
private System.Windows.Forms.TabPage tpMisc;
}
}

View File

@ -36,6 +36,9 @@ namespace BizHawk.Client.EmuHawk.config
checkPadInteger.Checked = Global.Config.DispFixScaleInteger;
checkFullscreenHacks.Checked = Global.Config.DispFullscreenHacks;
rbOpenGL.Checked = Global.Config.DispMethod == Config.EDispMethod.OpenGL;
rbGDIPlus.Checked = Global.Config.DispMethod == Config.EDispMethod.GdiPlus;
// null emulator config hack
{
NullEmulator.NullEmulatorSettings s;
@ -106,6 +109,11 @@ namespace BizHawk.Client.EmuHawk.config
int.TryParse(txtCustomARWidth.Text, out Global.Config.DispCustomUserARWidth);
int.TryParse(txtCustomARHeight.Text, out Global.Config.DispCustomUserARHeight);
if(rbOpenGL.Checked)
Global.Config.DispMethod = Config.EDispMethod.OpenGL;
if(rbGDIPlus.Checked)
Global.Config.DispMethod = Config.EDispMethod.GdiPlus;
Global.Config.DispUserFilterPath = PathSelection;
GlobalWin.DisplayManager.RefreshUserShader();

View File

@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.BizwareGL.O
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Client.DBMan", "BizHawk.Client.DBMan\BizHawk.Client.DBMan.csproj", "{2D2890A8-C338-4439-AD8B-CB9EE85A94F9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BizHawk.Bizware.BizwareGL.GdiPlus", "Bizware\BizHawk.Bizware.BizwareGL.GdiPlus\BizHawk.Bizware.BizwareGL.GdiPlus.csproj", "{337CA23E-65E7-44E1-9411-97EE08BB8116}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -159,6 +161,18 @@ Global
{2D2890A8-C338-4439-AD8B-CB9EE85A94F9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{2D2890A8-C338-4439-AD8B-CB9EE85A94F9}.Release|Win32.ActiveCfg = Release|Any CPU
{2D2890A8-C338-4439-AD8B-CB9EE85A94F9}.Release|x86.ActiveCfg = Release|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Debug|Any CPU.Build.0 = Debug|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Debug|Win32.ActiveCfg = Debug|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Debug|x86.ActiveCfg = Debug|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Release|Any CPU.ActiveCfg = Release|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Release|Any CPU.Build.0 = Release|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Release|Win32.ActiveCfg = Release|Any CPU
{337CA23E-65E7-44E1-9411-97EE08BB8116}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -173,6 +187,7 @@ Global
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA} = {3627C08B-3E43-4224-9DA4-40BD69495FBC}
{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465} = {0540A9A6-977E-466D-8BD3-1D8590BD5282}
{5160CFB1-5389-47C1-B7F6-8A0DC97641EE} = {0540A9A6-977E-466D-8BD3-1D8590BD5282}
{337CA23E-65E7-44E1-9411-97EE08BB8116} = {0540A9A6-977E-466D-8BD3-1D8590BD5282}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = BizHawk.Client.EmuHawk\BizHawk.Client.EmuHawk.csproj

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{337CA23E-65E7-44E1-9411-97EE08BB8116}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BizHawk.Bizware.BizwareGL.GdiPlus</RootNamespace>
<AssemblyName>BizHawk.Bizware.BizwareGL.GdiPlus</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\References\OpenTK.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\BizHawk.Common\BizHawk.Common.csproj">
<Project>{866F8D13-0678-4FF9-80A4-A3993FD4D8A3}</Project>
<Name>BizHawk.Common</Name>
</ProjectReference>
<ProjectReference Include="..\BizHawk.Bizware.BizwareGL\BizHawk.Bizware.BizwareGL.csproj">
<Project>{9F84A0B2-861E-4EF4-B89B-5E2A3F38A465}</Project>
<Name>BizHawk.Bizware.BizwareGL</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="GdiPlusGuiRenderer.cs" />
<Compile Include="GLControlWrapper_GdiPlus.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="IGL_GdiPlus.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,82 @@
using System;
using System.Drawing;
using System.Reflection;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System.Windows.Forms;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
{
public class GLControlWrapper_GdiPlus : Control, IGraphicsControl
{
public GLControlWrapper_GdiPlus(IGL_GdiPlus gdi)
{
Gdi = gdi;
//uhhh not sure what we need to be doing here
//SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.Opaque, true);
SetStyle(ControlStyles.UserMouse, true);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
//if(MyBufferedGraphics != null)
}
IGL_GdiPlus Gdi;
public Control Control { get { return this; } }
/// <summary>
/// the render target for rendering to this control
/// </summary>
public IGL_GdiPlus.RenderTargetWrapper RenderTargetWrapper;
public void SetVsync(bool state)
{
//not really supported now...
}
public void Begin()
{
Gdi.BeginControl(this);
RenderTargetWrapper.CreateGraphics();
//using (var g = CreateGraphics())
// MyBufferedGraphics = Gdi.MyBufferedGraphicsContext.Allocate(g, ClientRectangle);
//MyBufferedGraphics.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
////not sure about this stuff...
////it will wreck alpha blending, for one thing
//MyBufferedGraphics.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
//MyBufferedGraphics.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
}
public void End()
{
Gdi.EndControl(this);
}
public void SwapBuffers()
{
Gdi.SwapControl(this);
if (RenderTargetWrapper.MyBufferedGraphics == null)
return;
using (var g = CreateGraphics())
RenderTargetWrapper.MyBufferedGraphics.Render(g);
//not too sure about this.. i think we have to re-allocate it so we can support a changed window size. did we do this at the right time anyway?
RenderTargetWrapper.CreateGraphics();
}
}
}

View File

@ -0,0 +1,227 @@
//this is full of bugs probably, related to state from old rendering sessions being all messed up. its only barely good enough to work at all
using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using sd = System.Drawing;
using System.Drawing.Imaging;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
{
public class GDIPlusGuiRenderer : IGuiRenderer
{
public GDIPlusGuiRenderer(IGL_GdiPlus gl)
{
Owner = gl;
Gdi = gl as IGL_GdiPlus;
}
OpenTK.Graphics.Color4[] CornerColors = new OpenTK.Graphics.Color4[4] {
new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f)
};
public void SetCornerColor(int which, OpenTK.Graphics.Color4 color)
{
CornerColors[which] = color;
}
public void SetCornerColors(OpenTK.Graphics.Color4[] colors)
{
Flush(); //dont really need to flush with current implementation. we might as well roll modulate color into it too.
if (colors.Length != 4) throw new ArgumentException("array must be size 4", "colors");
for (int i = 0; i < 4; i++)
CornerColors[i] = colors[i];
}
public void Dispose()
{
if (CurrentImageAttributes != null)
CurrentImageAttributes.Dispose();
}
public void SetPipeline(Pipeline pipeline)
{
}
public void SetDefaultPipeline()
{
}
public void SetModulateColorWhite()
{
SetModulateColor(sd.Color.White);
}
ImageAttributes CurrentImageAttributes;
public void SetModulateColor(sd.Color color)
{
//white is really no color at all
if (color.ToArgb() == sd.Color.White.ToArgb())
{
CurrentImageAttributes.ClearColorMatrix(ColorAdjustType.Bitmap);
return;
}
float r = color.R / 255.0f;
float g = color.G / 255.0f;
float b = color.B / 255.0f;
float a = color.A / 255.0f;
float[][] colorMatrixElements = {
new float[] {r, 0, 0, 0, 0},
new float[] {0, g, 0, 0, 0},
new float[] {0, 0, b, 0, 0},
new float[] {0, 0, 0, a, 0},
new float[] {0, 0, 0, 0, 1}};
ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);
CurrentImageAttributes.SetColorMatrix(colorMatrix,ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
}
sd.Color CurrentModulateColor = sd.Color.White;
public void SetBlendState(IBlendState rsBlend)
{
}
MatrixStack _Projection, _Modelview;
public MatrixStack Projection
{
get { return _Projection; }
set
{
_Projection = value;
_Projection.IsDirty = true;
}
}
public MatrixStack Modelview
{
get { return _Modelview; }
set
{
_Modelview = value;
_Modelview.IsDirty = true;
}
}
public void Begin(sd.Size size) { Begin(size.Width, size.Height); }
public void Begin(int width, int height, bool yflipped = false)
{
Begin();
Projection = Owner.CreateGuiProjectionMatrix(width, height);
Modelview = Owner.CreateGuiViewMatrix(width, height);
}
public void Begin()
{
//uhhmmm I want to throw an exception if its already active, but its annoying.
IsActive = true;
CurrentImageAttributes = new ImageAttributes();
}
public void Flush()
{
//no batching, nothing to do here yet
}
public void End()
{
if (!IsActive)
throw new InvalidOperationException("GuiRenderer is not active!");
IsActive = false;
if (CurrentImageAttributes != null)
{
CurrentImageAttributes.Dispose();
CurrentImageAttributes = null;
}
}
public void RectFill(float x, float y, float w, float h)
{
}
public void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1)
{
var tw = Gdi.TextureWrapperForTexture(tex);
var g = Gdi.GetCurrentGraphics();
PrepDraw(g, tw);
float x0 = u0 * tex.Width;
float y0 = v0 * tex.Height;
float x1 = u1 * tex.Width;
float y1 = v1 * tex.Height;
sd.PointF[] destPoints = new sd.PointF[] {
new sd.PointF(x,y),
new sd.PointF(x+w,y),
new sd.PointF(x,y+h),
};
g.DrawImage(tw.SDBitmap, destPoints, new sd.RectangleF(x0, y0, x1 - x0, y1 - y0), sd.GraphicsUnit.Pixel, CurrentImageAttributes);
//g.DrawImage(tw.SDBitmap, 0, 0); //test
}
public void Draw(Art art) { DrawInternal(art, 0, 0, art.Width, art.Height, false, false); }
public void Draw(Art art, float x, float y) { DrawInternal(art, x, y, art.Width, art.Height, false, false); }
public void Draw(Art art, float x, float y, float width, float height) { DrawInternal(art, x, y, width, height, false, false); }
public void Draw(Art art, Vector2 pos) { DrawInternal(art, pos.X, pos.Y, art.Width, art.Height, false, false); }
public void Draw(Texture2d tex) { DrawInternal(tex, 0, 0, tex.Width, tex.Height); }
public void Draw(Texture2d tex, float x, float y) { DrawInternal(tex, x, y, tex.Width, tex.Height); }
public void DrawFlipped(Art art, bool xflip, bool yflip) { DrawInternal(art, 0, 0, art.Width, art.Height, xflip, yflip); }
public void Draw(Texture2d art, float x, float y, float width, float height)
{
DrawInternal(art, x, y, width, height);
}
void PrepDraw(sd.Graphics g, TextureWrapper tw)
{
//TODO - we can support bicubic for the final presentation..
if ((int)tw.MagFilter != (int)tw.MinFilter)
throw new InvalidOperationException("tw.MagFilter != tw.MinFilter");
if (tw.MagFilter == TextureMagFilter.Linear)
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
if (tw.MagFilter == TextureMagFilter.Nearest)
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
}
unsafe void DrawInternal(Texture2d tex, float x, float y, float w, float h)
{
var tw = Gdi.TextureWrapperForTexture(tex);
var g = Gdi.GetCurrentGraphics();
PrepDraw(g,tw);
//a little bit of a fastpath.. I think it's safe
if (w == tex.Width && h == tex.Height && x == (int)x && y == (int)y)
g.DrawImageUnscaled(tw.SDBitmap, (int)x, (int)y);
else
g.DrawImage(tw.SDBitmap, x, y, w, h);
}
unsafe void DrawInternal(Art art, float x, float y, float w, float h, bool fx, bool fy)
{
}
public bool IsActive { get; private set; }
public IGL Owner { get; private set; }
public IGL_GdiPlus Gdi;
}
}

View File

@ -0,0 +1,453 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using swf = System.Windows.Forms;
using sd = System.Drawing;
using sdi = System.Drawing.Imaging;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using BizHawk.Bizware.BizwareGL;
//TODO - maybe a layer to cache Graphics parameters (notably, filtering) ?
namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
{
public class ResourceIdManager
{
int Last = 1;
Queue<int> Available = new Queue<int>();
public Dictionary<int, object> Lookup = new Dictionary<int, object>();
public enum EResourceType
{
Texture,
RenderTarget
}
public IntPtr Alloc(EResourceType type)
{
if (Available.Count == 0)
{
return new IntPtr(Last++);
}
else return new IntPtr(Available.Dequeue());
}
public void Free(IntPtr handle)
{
int n = handle.ToInt32();
object o;
if (Lookup.TryGetValue(n, out o))
{
if (o is IDisposable)
{
((IDisposable)o).Dispose();
}
Lookup.Remove(n);
}
Available.Enqueue(n);
}
}
public class TextureWrapper : IDisposable
{
public sd.Bitmap SDBitmap;
public TextureMinFilter MinFilter = TextureMinFilter.Nearest;
public TextureMagFilter MagFilter = TextureMagFilter.Nearest;
public void Dispose()
{
if (SDBitmap != null)
{
SDBitmap.Dispose();
SDBitmap = null;
}
}
}
public class IGL_GdiPlus : IGL
{
public IGL_GdiPlus()
{
MyBufferedGraphicsContext = new BufferedGraphicsContext();
}
void IDisposable.Dispose()
{
}
public void Clear(OpenTK.Graphics.OpenGL.ClearBufferMask mask)
{
}
public IBlendState CreateBlendState(BlendingFactorSrc colorSource, BlendEquationMode colorEquation, BlendingFactorDest colorDest,
BlendingFactorSrc alphaSource, BlendEquationMode alphaEquation, BlendingFactorDest alphaDest)
{
return null;
}
public void SetClearColor(sd.Color color)
{
}
public unsafe void BindArrayData(void* pData)
{
}
public IntPtr GenTexture() { return ResourceIDs.Alloc(ResourceIdManager.EResourceType.Texture); }
public void FreeTexture(IntPtr texHandle) { ResourceIDs.Free(texHandle); }
public IntPtr GetEmptyHandle() { return new IntPtr(0); }
public IntPtr GetEmptyUniformHandle() { return new IntPtr(-1); }
public Shader CreateFragmentShader(string source, bool required)
{
return null;
}
public Shader CreateVertexShader(string source, bool required)
{
return null;
}
public void FreeShader(IntPtr shader) { }
public void SetBlendState(IBlendState rsBlend)
{
//TODO for real
}
class MyBlendState : IBlendState { }
static MyBlendState _rsBlendNone = new MyBlendState(), _rsBlendNormal = new MyBlendState();
public IBlendState BlendNone { get { return _rsBlendNone; } }
public IBlendState BlendNormal { get { return _rsBlendNormal; } }
public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required)
{
return null;
}
public VertexLayout CreateVertexLayout() { return new VertexLayout(this, new IntPtr(0)); }
public void BindTexture2d(Texture2d tex)
{
CurrentBoundTexture = tex;
}
public void SetTextureWrapMode(Texture2d tex, bool clamp)
{
if (CurrentBoundTexture == null)
throw new InvalidOperationException();
}
public void DrawArrays(PrimitiveType mode, int first, int count)
{
}
public void BindPipeline(Pipeline pipeline)
{
}
public void SetPipelineUniform(PipelineUniform uniform, bool value)
{
}
public unsafe void SetPipelineUniformMatrix(PipelineUniform uniform, Matrix4 mat, bool transpose)
{
}
public unsafe void SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix4 mat, bool transpose)
{
}
public void SetPipelineUniform(PipelineUniform uniform, Vector4 value)
{
}
public void SetPipelineUniform(PipelineUniform uniform, Vector2 value)
{
}
public void SetPipelineUniform(PipelineUniform uniform, float value)
{
}
public unsafe void SetPipelineUniform(PipelineUniform uniform, Vector4[] values)
{
}
public void SetPipelineUniformSampler(PipelineUniform uniform, IntPtr texHandle)
{
}
public void TexParameter2d(TextureParameterName pname, int param)
{
if (CurrentBoundTexture == null)
return;
TextureWrapper tw = TextureWrapperForTexture(CurrentBoundTexture);
if (pname == TextureParameterName.TextureMinFilter)
tw.MinFilter = (TextureMinFilter)param;
if (pname == TextureParameterName.TextureMagFilter)
tw.MagFilter = (TextureMagFilter)param;
}
public Texture2d LoadTexture(sd.Bitmap bitmap)
{
var sdbmp = (sd.Bitmap)bitmap.Clone();
TextureWrapper tw = new TextureWrapper();
tw.SDBitmap = sdbmp;
IntPtr id = GenTexture();
ResourceIDs.Lookup[id.ToInt32()] = tw;
return new Texture2d(this, id, bitmap.Width, bitmap.Height);
}
public Texture2d LoadTexture(Stream stream)
{
using (var bmp = new BitmapBuffer(stream, new BitmapLoadOptions()))
return (this as IGL).LoadTexture(bmp);
}
public Texture2d CreateTexture(int width, int height)
{
return null;
}
public Texture2d WrapGLTexture2d(IntPtr glTexId, int width, int height)
{
//TODO - need to rip the texturedata. we had code for that somewhere...
return null;
}
public void LoadTextureData(Texture2d tex, BitmapBuffer bmp)
{
bmp.ToSysdrawingBitmap(BitmapForTexture(tex));
}
public Texture2d LoadTexture(BitmapBuffer bmp)
{
//definitely needed (by TextureFrugalizer at least)
var sdbmp = bmp.ToSysdrawingBitmap();
IntPtr id = GenTexture();
var tw = new TextureWrapper();
tw.SDBitmap = sdbmp;
ResourceIDs.Lookup[id.ToInt32()] = tw;
return new Texture2d(this, id, bmp.Width, bmp.Height);
}
public unsafe BitmapBuffer ResolveTexture2d(Texture2d tex)
{
//todo
return null;
}
public Texture2d LoadTexture(string path)
{
//todo
//using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
// return (this as IGL).LoadTexture(fs);
return null;
}
public Matrix4 CreateGuiProjectionMatrix(int w, int h)
{
return CreateGuiProjectionMatrix(new sd.Size(w, h));
}
public Matrix4 CreateGuiViewMatrix(int w, int h)
{
return CreateGuiViewMatrix(new sd.Size(w, h));
}
public Matrix4 CreateGuiProjectionMatrix(sd.Size dims)
{
Matrix4 ret = Matrix4.Identity;
ret.M11 = 2.0f / (float)dims.Width;
ret.M22 = 2.0f / (float)dims.Height;
return ret;
}
public Matrix4 CreateGuiViewMatrix(sd.Size dims)
{
Matrix4 ret = Matrix4.Identity;
ret.M22 = -1.0f;
ret.M41 = -(float)dims.Width * 0.5f; // -0.5f;
ret.M42 = (float)dims.Height * 0.5f; // +0.5f;
return ret;
}
public void SetViewport(int x, int y, int width, int height)
{
}
public void SetViewport(int width, int height)
{
}
public void SetViewport(sd.Size size)
{
SetViewport(size.Width, size.Height);
}
public void SetViewport(swf.Control control)
{
}
public void BeginControl(GLControlWrapper_GdiPlus control)
{
CurrentControl = control;
}
public void EndControl(GLControlWrapper_GdiPlus control)
{
CurrentControl = null;
}
public void SwapControl(GLControlWrapper_GdiPlus control)
{
}
public class RenderTargetWrapper
{
public RenderTargetWrapper(IGL_GdiPlus gdi)
{
Gdi = gdi;
}
IGL_GdiPlus Gdi;
/// <summary>
/// the control associated with this render target (if any)
/// </summary>
public GLControlWrapper_GdiPlus Control;
/// <summary>
/// the offscreen render target, if that's what this is representing
/// </summary>
public RenderTarget Target;
public BufferedGraphics MyBufferedGraphics;
public void CreateGraphics()
{
Graphics refGraphics;
Rectangle r;
if (Control != null)
{
r = Control.ClientRectangle;
refGraphics = Control.CreateGraphics();
}
else
{
r = Target.Texture2d.Rectangle;
refGraphics = Graphics.FromImage(Gdi.BitmapForTexture(Target.Texture2d));
}
if (MyBufferedGraphics != null)
MyBufferedGraphics.Dispose();
MyBufferedGraphics = Gdi.MyBufferedGraphicsContext.Allocate(refGraphics, r);
//MyBufferedGraphics.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
////not sure about this stuff...
////it will wreck alpha blending, for one thing
//MyBufferedGraphics.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
//MyBufferedGraphics.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
}
}
public IGraphicsControl Internal_CreateGraphicsControl()
{
var ret = new GLControlWrapper_GdiPlus(this);
//create a render target for this control
RenderTargetWrapper rtw = new RenderTargetWrapper(this);
rtw.Control = ret;
ret.RenderTargetWrapper = rtw;
return ret;
}
public void FreeRenderTarget(RenderTarget rt)
{
int id = rt.Id.ToInt32();
var rtw = ResourceIDs.Lookup[id] as RenderTargetWrapper;
rtw.Target.Dispose();
ResourceIDs.Free(rt.Id);
}
public unsafe RenderTarget CreateRenderTarget(int w, int h)
{
Texture2d tex = null;
var rt = new RenderTarget(this, ResourceIDs.Alloc(ResourceIdManager.EResourceType.RenderTarget), tex);
int id = rt.Id.ToInt32();
RenderTargetWrapper rtw = new RenderTargetWrapper(this);
rtw.Target = rt;
ResourceIDs.Lookup[id] = rtw;
return rt;
}
public void BindRenderTarget(RenderTarget rt)
{
if (rt == null)
{
//null means to use the default RT for the current control
CurrentRenderTargetWrapper = CurrentControl.RenderTargetWrapper;
}
else
{
CurrentRenderTargetWrapper = RenderTargetWrapperForRt(rt);
}
}
public sd.Bitmap BitmapForTexture(Texture2d tex)
{
return TextureWrapperForTexture(tex).SDBitmap;
}
public TextureWrapper TextureWrapperForTexture(Texture2d tex)
{
return ResourceIDs.Lookup[tex.Id.ToInt32()] as TextureWrapper;
}
public RenderTargetWrapper RenderTargetWrapperForRt(RenderTarget rt)
{
return ResourceIDs.Lookup[rt.Id.ToInt32()] as RenderTargetWrapper;
}
public Graphics GetCurrentGraphics()
{
var rtw = CurrentRenderTargetWrapper;
return rtw.MyBufferedGraphics.Graphics;
}
public GLControlWrapper_GdiPlus CurrentControl;
public RenderTargetWrapper CurrentRenderTargetWrapper;
Texture2d CurrentBoundTexture;
//todo - not thread safe
public static ResourceIdManager ResourceIDs = new ResourceIdManager();
public BufferedGraphicsContext MyBufferedGraphicsContext;
} //class IGL_GdiPlus
}

View File

@ -0,0 +1,96 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK
{
/// <summary>
/// Handles RetroArch's GLSL shader pass format
/// This isnt implemented in BizwareGL abstract layer because it relies too much on GLSL peculiarities
/// </summary>
public class RetroShader : IDisposable
{
public RetroShader(IGL owner, string source, bool debug = false)
{
Owner = owner as IGL_TK;
VertexLayout = owner.CreateVertexLayout();
VertexLayout.DefineVertexAttribute("VertexCoord", 0, 4, VertexAttribPointerType.Float, false, 40, 0); //VertexCoord
VertexLayout.DefineVertexAttribute("ColorShit", 1, 4, VertexAttribPointerType.Float, false, 40, 16); //COLOR
VertexLayout.DefineVertexAttribute("TexCoord", 2, 2, VertexAttribPointerType.Float, false, 40, 32); //TexCoord (is this vec2 or vec4? the glsl converted from cg had vec4 but the cg had vec2...)
VertexLayout.Close();
string vsSource = "#define VERTEX\r\n" + source;
string psSource = "#define FRAGMENT\r\n" + source;
var vs = Owner.CreateVertexShader(vsSource, debug);
var ps = Owner.CreateFragmentShader(psSource, debug);
Pipeline = Owner.CreatePipeline(VertexLayout, vs, ps, debug);
}
public void Dispose()
{
VertexLayout.Dispose();
VertexLayout = null;
}
public void Bind()
{
//lame...
Owner.BindPipeline(Pipeline);
}
public unsafe void Run(Texture2d tex, Size InputSize, Size OutputSize, bool flip)
{
//ack! make sure to set the pipeline before setting
Bind();
Pipeline["InputSize"].Set(new Vector2(InputSize.Width,InputSize.Height));
Pipeline["TextureSize"].Set(new Vector2(InputSize.Width, InputSize.Height));
Pipeline["OutputSize"].Set(new Vector2(OutputSize.Width, OutputSize.Height));
Pipeline["FrameCount"].Set(0); //todo
Pipeline["FrameDirection"].Set(1); //todo
var Projection = Owner.CreateGuiProjectionMatrix(OutputSize);
var Modelview = Owner.CreateGuiViewMatrix(OutputSize);
Pipeline["MVPMatrix"].Set(Modelview * Projection, false);
Owner.SetTextureWrapMode(tex, true);
Pipeline["Texture"].Set(tex);
Owner.SetViewport(OutputSize);
int w = OutputSize.Width;
int h = OutputSize.Height;
float v0,v1;
if (flip) { v0 = 1; v1 = 0; }
else { v0 = 0; v1 = 1; }
float* pData = stackalloc float[10*4];
int i=0;
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 1; //topleft vert
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //junk
pData[i++] = 0; pData[i++] = v0; //texcoord
pData[i++] = w; pData[i++] = 0; pData[i++] = 0; pData[i++] = 1; //topright vert
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //junk
pData[i++] = 1; pData[i++] = v0; //texcoord
pData[i++] = 0; pData[i++] = h; pData[i++] = 0; pData[i++] = 1; //bottomleft vert
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //junk
pData[i++] = 0; pData[i++] = v1; //texcoord
pData[i++] = w; pData[i++] = h; pData[i++] = 0; pData[i++] = 1; //bottomright vert
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //junk
pData[i++] = 1; pData[i++] = v1; //texcoord
Owner.SetBlendState(Owner.BlendNone);
Owner.BindArrayData(pData);
Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
}
public IGL_TK Owner { get; private set; }
VertexLayout VertexLayout;
public Pipeline Pipeline;
}
}

View File

@ -460,11 +460,20 @@ namespace BizHawk.Bizware.BizwareGL
/// <summary>
/// Dumps this BitmapBuffer to a System.Drawing.Bitmap
/// Dumps this BitmapBuffer to a new System.Drawing.Bitmap
/// </summary>
public unsafe Bitmap ToSysdrawingBitmap()
{
Bitmap bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
ToSysdrawingBitmap(bmp);
return bmp;
}
/// <summary>
/// Dumps this BitmapBuffer to an existing System.Drawing.Bitmap
/// </summary>
public unsafe void ToSysdrawingBitmap(Bitmap bmp)
{
var bmpdata = bmp.LockBits(new sd.Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
int* ptr = (int*)bmpdata.Scan0.ToPointer();
@ -481,7 +490,6 @@ namespace BizHawk.Bizware.BizwareGL
}
bmp.UnlockBits(bmpdata);
return bmp;
}
}

View File

@ -66,6 +66,9 @@
<Compile Include="IGL.cs" />
<Compile Include="ArtManager.cs" />
<Compile Include="IGraphicsControl.cs" />
<Compile Include="IGuiRenderer.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="MatrixStack.cs" />
<Compile Include="Pipeline.cs" />
<Compile Include="PipelineUniform.cs" />

View File

@ -1,5 +1,7 @@
//http://stackoverflow.com/questions/6893302/decode-rgb-value-to-single-float-without-bit-shift-in-glsl
//why this stupid assert on the blendstate. just set one by default, geeze.
using System;
using System.Diagnostics;
using System.Collections;
@ -17,7 +19,7 @@ namespace BizHawk.Bizware.BizwareGL
/// Call Begin, then draw, then End, and dont use other Renderers or GL calls in the meantime, unless you know what youre doing.
/// This can perform batching (well.. maybe not yet), which is occasionally necessary for drawing large quantities of things.
/// </summary>
public class GuiRenderer : IDisposable
public class GuiRenderer : IDisposable, IGuiRenderer
{
public GuiRenderer(IGL owner)
{
@ -41,18 +43,14 @@ namespace BizHawk.Bizware.BizwareGL
new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f)
};
/// <summary>
/// Sets the specified corner color (for the gradient effect)
/// </summary>
public void SetCornerColor(int which, OpenTK.Graphics.Color4 color)
{
Flush(); //dont really need to flush with current implementation. we might as well roll modulate color into it too.
CornerColors[which] = color;
}
/// <summary>
/// Sets all four corner colors at once
/// </summary>
public void SetCornerColors(OpenTK.Graphics.Color4[] colors)
{
Flush(); //dont really need to flush with current implementation. we might as well roll modulate color into it too.
@ -69,10 +67,7 @@ namespace BizHawk.Bizware.BizwareGL
DefaultPipeline = null;
}
/// <summary>
/// Sets the pipeline for this GuiRenderer to use. We won't keep possession of it.
/// This pipeline must work in certain ways, which can be discerned by inspecting the built-in one
/// </summary>
public void SetPipeline(Pipeline pipeline)
{
if (IsActive)
@ -86,9 +81,6 @@ namespace BizHawk.Bizware.BizwareGL
//save the modulate color? user beware, I guess, for now.
}
/// <summary>
/// Restores the pipeline to the default
/// </summary>
public void SetDefaultPipeline()
{
SetPipeline(DefaultPipeline);
@ -136,10 +128,6 @@ namespace BizHawk.Bizware.BizwareGL
public void Begin(sd.Size size) { Begin(size.Width, size.Height); }
/// <summary>
/// begin rendering, initializing viewport and projections to the given dimensions
/// </summary>
/// <param name="yflipped">Whether the matrices should be Y-flipped, for use with render targets</param>
public void Begin(int width, int height, bool yflipped = false)
{
Begin();
@ -156,9 +144,7 @@ namespace BizHawk.Bizware.BizwareGL
Owner.SetViewport(width, height);
}
/// <summary>
/// Begins rendering
/// </summary>
public void Begin()
{
//uhhmmm I want to throw an exception if its already active, but its annoying.
@ -181,18 +167,13 @@ namespace BizHawk.Bizware.BizwareGL
#endif
}
/// <summary>
/// Use this, if you must do something sneaky to openGL without this GuiRenderer knowing.
/// It might be faster than End and Beginning again, and certainly prettier
/// </summary>
public void Flush()
{
//no batching, nothing to do here yet
}
/// <summary>
/// Ends rendering
/// </summary>
public void End()
{
if (!IsActive)
@ -206,47 +187,31 @@ namespace BizHawk.Bizware.BizwareGL
EmitRectangleInternal(x, y, w, h, 0, 0, 0, 0);
}
/// <summary>
/// Draws a subrectangle from the provided texture. For advanced users only
/// </summary>
public void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1)
{
DrawSubrectInternal(tex, x, y, w, h, u0, v0, u1, v1);
}
/// <summary>
/// draws the specified Art resource
/// </summary>
public void Draw(Art art) { DrawInternal(art, 0, 0, art.Width, art.Height, false, false); }
/// <summary>
/// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
public void Draw(Art art, float x, float y) { DrawInternal(art, x, y, art.Width, art.Height, false, false); }
/// <summary>
/// draws the specified Art resource with the specified offset, with the specified size. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
public void Draw(Art art, float x, float y, float width, float height) { DrawInternal(art, x, y, width, height, false, false); }
/// <summary>
/// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
public void Draw(Art art, Vector2 pos) { DrawInternal(art, pos.X, pos.Y, art.Width, art.Height, false, false); }
/// <summary>
/// draws the specified texture2d resource.
/// </summary>
public void Draw(Texture2d tex) { DrawInternal(tex, 0, 0, tex.Width, tex.Height); }
/// <summary>
/// draws the specified texture2d resource.
/// </summary>
public void Draw(Texture2d tex, float x, float y) { DrawInternal(tex, x, y, tex.Width, tex.Height); }
/// <summary>
/// draws the specified Art resource with the given flip flags
/// </summary>
public void DrawFlipped(Art art, bool xflip, bool yflip) { DrawInternal(art, 0, 0, art.Width, art.Height, xflip, yflip); }
public void Draw(Texture2d art, float x, float y, float width, float height)

View File

@ -0,0 +1,414 @@
//http://stackoverflow.com/questions/6893302/decode-rgb-value-to-single-float-without-bit-shift-in-glsl
using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using sd=System.Drawing;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace BizHawk.Bizware.BizwareGL
{
public class GDIPlusGuiRenderer : IGuiRenderer
{
public GDIPlusGuiRenderer(IGL owner)
{
Owner = owner;
VertexLayout = owner.CreateVertexLayout();
VertexLayout.DefineVertexAttribute("aPosition", 0, 2, VertexAttribPointerType.Float, false, 32, 0);
VertexLayout.DefineVertexAttribute("aTexcoord", 1, 2, VertexAttribPointerType.Float, false, 32, 8);
VertexLayout.DefineVertexAttribute("aColor", 2, 4, VertexAttribPointerType.Float, false, 32, 16);
VertexLayout.Close();
_Projection = new MatrixStack();
_Modelview = new MatrixStack();
var vs = Owner.CreateVertexShader(DefaultVertexShader,true);
var ps = Owner.CreateFragmentShader(DefaultPixelShader, true);
CurrPipeline = DefaultPipeline = Owner.CreatePipeline(VertexLayout, vs, ps, true);
}
OpenTK.Graphics.Color4[] CornerColors = new OpenTK.Graphics.Color4[4] {
new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f)
};
/// <summary>
/// Sets the specified corner color (for the gradient effect)
/// </summary>
public void SetCornerColor(int which, OpenTK.Graphics.Color4 color)
{
Flush(); //dont really need to flush with current implementation. we might as well roll modulate color into it too.
CornerColors[which] = color;
}
/// <summary>
/// Sets all four corner colors at once
/// </summary>
public void SetCornerColors(OpenTK.Graphics.Color4[] colors)
{
Flush(); //dont really need to flush with current implementation. we might as well roll modulate color into it too.
if (colors.Length != 4) throw new ArgumentException("array must be size 4", "colors");
for (int i = 0; i < 4; i++)
CornerColors[i] = colors[i];
}
public void Dispose()
{
VertexLayout.Dispose();
VertexLayout = null;
DefaultPipeline.Dispose();
DefaultPipeline = null;
}
/// <summary>
/// Sets the pipeline for this GuiRenderer to use. We won't keep possession of it.
/// This pipeline must work in certain ways, which can be discerned by inspecting the built-in one
/// </summary>
public void SetPipeline(Pipeline pipeline)
{
if (IsActive)
throw new InvalidOperationException("Can't change pipeline while renderer is running!");
Flush();
CurrPipeline = pipeline;
//clobber state cache
sTexture = null;
//save the modulate color? user beware, I guess, for now.
}
/// <summary>
/// Restores the pipeline to the default
/// </summary>
public void SetDefaultPipeline()
{
SetPipeline(DefaultPipeline);
}
public void SetModulateColorWhite()
{
SetModulateColor(sd.Color.White);
}
public void SetModulateColor(sd.Color color)
{
Flush();
CurrPipeline["uModulateColor"].Set(new Vector4(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, color.A / 255.0f));
}
public void SetBlendState(IBlendState rsBlend)
{
#if DEBUG
BlendStateSet = true;
#endif
Flush();
Owner.SetBlendState(rsBlend);
}
MatrixStack _Projection, _Modelview;
public MatrixStack Projection
{
get { return _Projection; }
set
{
_Projection = value;
_Projection.IsDirty = true;
}
}
public MatrixStack Modelview
{
get { return _Modelview; }
set
{
_Modelview = value;
_Modelview.IsDirty = true;
}
}
public void Begin(sd.Size size) { Begin(size.Width, size.Height); }
/// <summary>
/// begin rendering, initializing viewport and projections to the given dimensions
/// </summary>
/// <param name="yflipped">Whether the matrices should be Y-flipped, for use with render targets</param>
public void Begin(int width, int height, bool yflipped = false)
{
Begin();
Projection = Owner.CreateGuiProjectionMatrix(width, height);
Modelview = Owner.CreateGuiViewMatrix(width, height);
if (yflipped)
{
//not sure this is the best way to do it. could be done in the view matrix creation
Modelview.Scale(1, -1);
Modelview.Translate(0, -height);
}
Owner.SetViewport(width, height);
}
/// <summary>
/// Begins rendering
/// </summary>
public void Begin()
{
//uhhmmm I want to throw an exception if its already active, but its annoying.
if(CurrPipeline == null)
throw new InvalidOperationException("Pipeline hasn't been set!");
IsActive = true;
Owner.BindPipeline(CurrPipeline);
//clear state cache
sTexture = null;
CurrPipeline["uSamplerEnable"].Set(false);
Modelview.Clear();
Projection.Clear();
SetModulateColorWhite();
#if DEBUG
BlendStateSet = false;
#endif
}
/// <summary>
/// Use this, if you must do something sneaky to openGL without this GuiRenderer knowing.
/// It might be faster than End and Beginning again, and certainly prettier
/// </summary>
public void Flush()
{
//no batching, nothing to do here yet
}
/// <summary>
/// Ends rendering
/// </summary>
public void End()
{
if (!IsActive)
throw new InvalidOperationException("GuiRenderer is not active!");
IsActive = false;
}
public void RectFill(float x, float y, float w, float h)
{
PrepDrawSubrectInternal(null);
EmitRectangleInternal(x, y, w, h, 0, 0, 0, 0);
}
/// <summary>
/// Draws a subrectangle from the provided texture. For advanced users only
/// </summary>
public void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1)
{
DrawSubrectInternal(tex, x, y, w, h, u0, v0, u1, v1);
}
/// <summary>
/// draws the specified Art resource
/// </summary>
public void Draw(Art art) { DrawInternal(art, 0, 0, art.Width, art.Height, false, false); }
/// <summary>
/// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
public void Draw(Art art, float x, float y) { DrawInternal(art, x, y, art.Width, art.Height, false, false); }
/// <summary>
/// draws the specified Art resource with the specified offset, with the specified size. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
public void Draw(Art art, float x, float y, float width, float height) { DrawInternal(art, x, y, width, height, false, false); }
/// <summary>
/// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
public void Draw(Art art, Vector2 pos) { DrawInternal(art, pos.X, pos.Y, art.Width, art.Height, false, false); }
/// <summary>
/// draws the specified texture2d resource.
/// </summary>
public void Draw(Texture2d tex) { DrawInternal(tex, 0, 0, tex.Width, tex.Height); }
/// <summary>
/// draws the specified texture2d resource.
/// </summary>
public void Draw(Texture2d tex, float x, float y) { DrawInternal(tex, x, y, tex.Width, tex.Height); }
/// <summary>
/// draws the specified Art resource with the given flip flags
/// </summary>
public void DrawFlipped(Art art, bool xflip, bool yflip) { DrawInternal(art, 0, 0, art.Width, art.Height, xflip, yflip); }
public void Draw(Texture2d art, float x, float y, float width, float height)
{
DrawInternal(art, x, y, width, height);
}
unsafe void DrawInternal(Texture2d tex, float x, float y, float w, float h)
{
Art art = new Art(null);
art.Width = w;
art.Height = h;
art.u0 = art.v0 = 0;
art.u1 = art.v1 = 1;
art.BaseTexture = tex;
DrawInternal(art,x,y,w,h,false,tex.IsUpsideDown);
}
unsafe void DrawInternal(Art art, float x, float y, float w, float h, bool fx, bool fy)
{
float u0,v0,u1,v1;
if(fx) { u0 = art.u1; u1 = art.u0; }
else { u0 = art.u0; u1 = art.u1; }
if(fy) { v0 = art.v1; v1 = art.v0; }
else { v0 = art.v0; v1 = art.v1; }
float[] data = new float[32] {
x,y, u0,v0, CornerColors[0].R, CornerColors[0].G, CornerColors[0].B, CornerColors[0].A,
x+art.Width,y, u1,v0, CornerColors[1].R, CornerColors[1].G, CornerColors[1].B, CornerColors[1].A,
x,y+art.Height, u0,v1, CornerColors[2].R, CornerColors[2].G, CornerColors[2].B, CornerColors[2].A,
x+art.Width,y+art.Height, u1,v1, CornerColors[3].R, CornerColors[3].G, CornerColors[3].B, CornerColors[3].A,
};
Texture2d tex = art.BaseTexture;
PrepDrawSubrectInternal(tex);
fixed (float* pData = &data[0])
{
Owner.BindArrayData(pData);
Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
}
}
unsafe void PrepDrawSubrectInternal(Texture2d tex)
{
if (sTexture != tex)
{
sTexture = tex;
CurrPipeline["uSampler0"].Set(tex);
if (sTexture == null)
{
CurrPipeline["uSamplerEnable"].Set(false);
}
else
{
CurrPipeline["uSamplerEnable"].Set(true);
}
}
if (_Projection.IsDirty)
{
CurrPipeline["um44Projection"].Set(ref _Projection.Top);
_Projection.IsDirty = false;
}
if (_Modelview.IsDirty)
{
CurrPipeline["um44Modelview"].Set(ref _Modelview.Top);
_Modelview.IsDirty = false;
}
}
unsafe void EmitRectangleInternal(float x, float y, float w, float h, float u0, float v0, float u1, float v1)
{
float* pData = stackalloc float[32];
pData[0] = x;
pData[1] = y;
pData[2] = u0;
pData[3] = v0;
pData[4] = CornerColors[0].R;
pData[5] = CornerColors[0].G;
pData[6] = CornerColors[0].B;
pData[7] = CornerColors[0].A;
pData[8] = x + w;
pData[9] = y;
pData[10] = u1;
pData[11] = v0;
pData[12] = CornerColors[1].R;
pData[13] = CornerColors[1].G;
pData[14] = CornerColors[1].B;
pData[15] = CornerColors[1].A;
pData[16] = x;
pData[17] = y + h;
pData[18] = u0;
pData[19] = v1;
pData[20] = CornerColors[2].R;
pData[21] = CornerColors[2].G;
pData[22] = CornerColors[2].B;
pData[23] = CornerColors[2].A;
pData[24] = x + w;
pData[25] = y + h;
pData[26] = u1;
pData[27] = v1;
pData[28] = CornerColors[3].R;
pData[29] = CornerColors[3].G;
pData[30] = CornerColors[3].B;
pData[31] = CornerColors[3].A;
Owner.BindArrayData(pData);
Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
#if DEBUG
Debug.Assert(BlendStateSet);
#endif
}
unsafe void DrawSubrectInternal(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1)
{
PrepDrawSubrectInternal(tex);
EmitRectangleInternal(x, y, w, h, u0, v0, u1, v1);
}
public bool IsActive { get; private set; }
public IGL Owner { get; private set; }
VertexLayout VertexLayout;
Pipeline CurrPipeline, DefaultPipeline;
//state cache
Texture2d sTexture;
#if DEBUG
bool BlendStateSet;
#endif
public readonly string DefaultVertexShader = @"
#version 110 //opengl 2.0 ~ 2004
uniform mat4 um44Modelview, um44Projection;
uniform vec4 uModulateColor;
attribute vec2 aPosition;
attribute vec2 aTexcoord;
attribute vec4 aColor;
varying vec2 vTexcoord0;
varying vec4 vCornerColor;
void main()
{
vec4 temp = vec4(aPosition,0,1);
gl_Position = um44Projection * (um44Modelview * temp);
vTexcoord0 = aTexcoord;
vCornerColor = aColor * uModulateColor;
}";
public readonly string DefaultPixelShader = @"
#version 110 //opengl 2.0 ~ 2004
uniform bool uSamplerEnable;
uniform sampler2D uSampler0;
varying vec2 vTexcoord0;
varying vec4 vCornerColor;
void main()
{
vec4 temp = vCornerColor;
if(uSamplerEnable) temp *= texture2D(uSampler0,vTexcoord0);
gl_FragColor = temp;
}";
}
}

View File

@ -18,12 +18,16 @@ namespace BizHawk.Bizware.BizwareGL
/// <summary>
/// Makes this control current for rendering operations.
/// Note that at this time, the window size shouldnt change until End() or else something bad might happen
/// Please be aware that this might change the rendering context, meaning that some things you set without calling BeginControl/EndControl might not be affected
/// Please be aware that this might change the rendering context, meaning that some things you set without calling Begin/End might not be affected
/// </summary>
void Begin();
/// <summary>
/// Ends rendering on the specified control.
/// NOTE: DO NOT EXPECT TO SEE BEGIN/END CALLED IN PAIRS, STRICTLY.
/// this is more about GL context management than anything else.
/// See GLManager for details.
/// In particular, dont expect to have End() called before doing certain things. Maybe use SwapBuffers instead
/// </summary>
void End();
}

View File

@ -0,0 +1,104 @@
using System;
namespace BizHawk.Bizware.BizwareGL
{
public interface IGuiRenderer : IDisposable
{
/// <summary>
/// Begins rendering
/// </summary>
void Begin();
void Begin(System.Drawing.Size size);
/// <summary>
/// begin rendering, initializing viewport and projections to the given dimensions
/// </summary>
/// <param name="yflipped">Whether the matrices should be Y-flipped, for use with render targets</param>
void Begin(int width, int height, bool yflipped = false);
/// <summary>
/// draws the specified Art resource
/// </summary>
void Draw(Art art);
/// <summary>
/// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
void Draw(Art art, OpenTK.Vector2 pos);
/// <summary>
/// draws the specified Art resource with the specified offset. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
void Draw(Art art, float x, float y);
/// <summary>
/// draws the specified Art resource with the specified offset, with the specified size. This could be tricky if youve applied other rotate or scale transforms first.
/// </summary>
void Draw(Art art, float x, float y, float width, float height);
void Draw(Texture2d art, float x, float y, float width, float height);
/// <summary>
/// draws the specified texture2d resource.
/// </summary>
void Draw(Texture2d tex);
/// <summary>
/// draws the specified texture2d resource.
/// </summary>
void Draw(Texture2d tex, float x, float y);
/// <summary>
/// draws the specified Art resource with the given flip flags
/// </summary>
void DrawFlipped(Art art, bool xflip, bool yflip);
/// <summary>
/// Draws a subrectangle from the provided texture. For advanced users only
/// </summary>
void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1);
/// <summary>
/// Ends rendering
/// </summary>
void End();
/// <summary>
/// Use this, if you must do something sneaky to openGL without this GuiRenderer knowing.
/// It might be faster than End and Beginning again, and certainly prettier
/// </summary>
void Flush();
bool IsActive { get; }
MatrixStack Modelview { get; set; }
IGL Owner { get; }
MatrixStack Projection { get; set; }
void RectFill(float x, float y, float w, float h);
void SetBlendState(IBlendState rsBlend);
/// <summary>
/// Sets the specified corner color (for the gradient effect)
/// </summary>
void SetCornerColor(int which, OpenTK.Graphics.Color4 color);
/// <summary>
/// Sets all four corner colors at once
/// </summary>
void SetCornerColors(OpenTK.Graphics.Color4[] colors);
/// <summary>
/// Restores the pipeline to the default
/// </summary>
void SetDefaultPipeline();
void SetModulateColor(System.Drawing.Color color);
void SetModulateColorWhite();
/// <summary>
/// Sets the pipeline for this GuiRenderer to use. We won't keep possession of it.
/// This pipeline must work in certain ways, which can be discerned by inspecting the built-in one
/// </summary>
void SetPipeline(Pipeline pipeline);
}
}

View File

@ -45,7 +45,7 @@ namespace BizHawk.Bizware.BizwareGL
return new sd.SizeF(x, FontInfo.LineHeight);
}
public void RenderString(GuiRenderer renderer, float x, float y, string str)
public void RenderString(IGuiRenderer renderer, float x, float y, string str)
{
int len = str.Length;
for (int i = 0; i < len; i++)

View File

@ -77,6 +77,7 @@ namespace BizHawk.Bizware.BizwareGL
public int IntWidth { get { return (int)Width; } }
public int IntHeight { get { return (int)Height; } }
public Rectangle Rectangle { get { return new Rectangle(0, 0, IntWidth, IntHeight); } }
public Size Size { get { return new Size(IntWidth, IntHeight); } }
/// <summary>

View File

@ -98,6 +98,7 @@ namespace BizHawk.Bizware.Test
int frame = (int)((DateTime.Now - start).TotalSeconds) % testArts.Count;
gr.Begin(c.ClientSize.Width, c.ClientSize.Height);
gr.SetBlendState(igl.BlendNormal);
gr.SetModulateColor(Color.Green);
gr.RectFill(250, 0, 16, 16);