cleanup, namely of GraphicsControl and related systems, and add a RetainedGraphicsControl which should be useful for tool windows

This commit is contained in:
zeromus 2014-01-28 19:33:49 +00:00
parent c4ffc78224
commit 85fe967810
17 changed files with 745 additions and 374 deletions

View File

@ -203,6 +203,12 @@
<Compile Include="config\FirmwaresConfigInfo.Designer.cs">
<DependentUpon>FirmwaresConfigInfo.cs</DependentUpon>
</Compile>
<Compile Include="config\DisplayConfig.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="config\DisplayConfig.Designer.cs">
<DependentUpon>DisplayConfig.cs</DependentUpon>
</Compile>
<Compile Include="config\GB\BmpView.cs">
<SubType>Component</SubType>
</Compile>
@ -887,6 +893,9 @@
<EmbeddedResource Include="config\ControllerConfig\ControllerConfigPanel.resx">
<DependentUpon>ControllerConfigPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="config\DisplayConfig.resx">
<DependentUpon>DisplayConfig.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="config\FirmwaresConfig.resx">
<DependentUpon>FirmwaresConfig.cs</DependentUpon>
</EmbeddedResource>

View File

@ -26,14 +26,14 @@ namespace BizHawk.Client.EmuHawk
{
GL = GlobalWin.GL;
GraphicsControl = GL.CreateGraphicsControl();
GraphicsControl.Control.Dock = DockStyle.Fill;
GraphicsControl.Control.BackColor = Color.Black;
GraphicsControl = new GraphicsControl(GL);
GraphicsControl.Dock = DockStyle.Fill;
GraphicsControl.BackColor = Color.Black;
//pass through these events to the form. we might need a more scalable solution for mousedown etc. for zapper and whatnot.
//http://stackoverflow.com/questions/547172/pass-through-mouse-events-to-parent-control (HTTRANSPARENT)
GraphicsControl.Control.MouseDoubleClick += (o, e) => HandleFullscreenToggle(o, e);
GraphicsControl.Control.MouseClick += (o, e) => GlobalWin.MainForm.MainForm_MouseClick(o, e);
GraphicsControl.MouseDoubleClick += (o, e) => HandleFullscreenToggle(o, e);
GraphicsControl.MouseClick += (o, e) => GlobalWin.MainForm.MainForm_MouseClick(o, e);
}
public void Dispose()
@ -47,8 +47,8 @@ namespace BizHawk.Client.EmuHawk
private bool Vsync;
public Control Control { get { return GraphicsControl.Control; } }
public static implicit operator Control(PresentationPanel self) { return self.GraphicsControl.Control; }
public Control Control { get { return GraphicsControl; } }
public static implicit operator Control(PresentationPanel self) { return self.GraphicsControl; }
private void HandleFullscreenToggle(object sender, MouseEventArgs e)
{
@ -70,7 +70,7 @@ namespace BizHawk.Client.EmuHawk
throw new InvalidOperationException("Not supported right now, sorry");
}
public Size NativeSize { get { return GraphicsControl.Control.ClientSize; } }
public Size NativeSize { get { return GraphicsControl.ClientSize; } }
}

View File

@ -1,234 +0,0 @@
using System;
using System.Drawing;
using sd=System.Drawing;
using sysdrawingfont=System.Drawing.Font;
using sysdrawing2d=System.Drawing.Drawing2D;
using System.IO;
using System.Threading;
using System.Windows.Forms;
#if WINDOWS
using SlimDX;
#endif
using BizHawk.Client.Common;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Client.EmuHawk
{
/// <summary>
/// Handles the EmuHawk main presentation control - final display only.
/// Compositing, filters, etc., should be handled by DisplayManager
/// </summary>
public class PresentationPanel : IBlitter
{
public PresentationPanel()
{
GL = GlobalWin.GL;
GraphicsControl = GL.CreateGraphicsControl();
GraphicsControl.Control.Dock = DockStyle.Fill;
GraphicsControl.Control.BackColor = Color.Black;
//prepare a renderer
Renderer = new GuiRenderer(GL);
//pass through these events to the form. we might need a more scalable solution for mousedown etc. for zapper and whatnot.
//http://stackoverflow.com/questions/547172/pass-through-mouse-events-to-parent-control (HTTRANSPARENT)
GraphicsControl.Control.MouseDoubleClick += (o, e) => HandleFullscreenToggle(o, e);
GraphicsControl.Control.MouseClick += (o, e) => GlobalWin.MainForm.MainForm_MouseClick(o, e);
using (var xml = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.courier16px.fnt"))
using (var tex = typeof(Program).Assembly.GetManifestResourceStream("BizHawk.Client.EmuHawk.Resources.courier16px_0.png"))
TheOneFont = new StringRenderer(GL, xml, tex);
}
public void Dispose()
{
//this hasnt been analyzed real well yet
Renderer.Dispose();
GraphicsControl.Dispose();
TheOneFont.Dispose();
if (LastSurfaceTexture != null)
LastSurfaceTexture.Dispose();
//gl shouldnt be disposed! it should be a global resource! probably managed elsewhere
}
public Control Control { get { return GraphicsControl.Control; } }
public static implicit operator Control(PresentationPanel self) { return self.GraphicsControl.Control; }
StringRenderer TheOneFont;
public Bizware.BizwareGL.GraphicsControl GraphicsControl;
static Bizware.BizwareGL.IGL GL;
GuiRenderer Renderer;
Texture2d LastSurfaceTexture;
private void HandleFullscreenToggle(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
GlobalWin.MainForm.ToggleFullscreen();
}
class FontWrapper : IBlitterFont
{
public FontWrapper(StringRenderer font)
{
this.font = font;
}
public readonly StringRenderer font;
}
void IBlitter.Open()
{
Renderer.Begin(GraphicsControl.Control.ClientSize.Width, GraphicsControl.Control.ClientSize.Height);
Renderer.SetBlendState(GL.BlendNormal);
ClipBounds = new sd.Rectangle(0, 0, NativeSize.Width, NativeSize.Height);
}
void IBlitter.Close() {
Renderer.End();
}
IBlitterFont IBlitter.GetFontType(string fontType) { return new FontWrapper(TheOneFont); }
void IBlitter.DrawString(string s, IBlitterFont font, Color color, float x, float y)
{
var stringRenderer = ((FontWrapper)font).font;
Renderer.SetModulateColor(color);
stringRenderer.RenderString(Renderer, x, y, s);
Renderer.SetModulateColorWhite();
}
SizeF IBlitter.MeasureString(string s, IBlitterFont font)
{
var stringRenderer = ((FontWrapper)font).font;
return stringRenderer.Measure(s);
}
public sd.Rectangle ClipBounds { get; set; }
public bool Resized { get; set; }
public void Clear(Color color)
{
GraphicsControl.Begin();
}
public sd.Point ScreenToScreen(sd.Point p)
{
p = GraphicsControl.Control.PointToClient(p);
sd.Point ret = new sd.Point(p.X * sw / GraphicsControl.Control.Width,
p.Y * sh / GraphicsControl.Control.Height);
return ret;
}
public Size NativeSize { get { return GraphicsControl.Control.ClientSize; } }
//the hell is this doing here? horrible
private bool VsyncRequested
{
get
{
if (Global.ForceNoThrottle)
return false;
return Global.Config.VSyncThrottle || Global.Config.VSync;
}
}
public void RenderOverlay(DisplaySurface surface)
{
RenderExec(null, surface);
}
public void Render(BitmapBuffer surface)
{
RenderExec(surface,null);
}
private bool Vsync;
int sw=1, sh=1;
public void RenderExec(BitmapBuffer surface, DisplaySurface displaySurface)
{
GraphicsControl.Begin();
if (Resized || Vsync != VsyncRequested)
{
GraphicsControl.SetVsync(VsyncRequested);
}
bool overlay = false;
if(displaySurface != null)
{
overlay = true;
displaySurface.ToBitmap(false);
surface = new BitmapBuffer(displaySurface.PeekBitmap(), new BitmapLoadOptions());
}
if (sw != surface.Width || sh != surface.Height || LastSurfaceTexture == null)
{
LastSurfaceTexture = GL.LoadTexture(surface);
}
else
{
GL.LoadTextureData(LastSurfaceTexture, surface);
}
if(Global.Config.DispBlurry)
LastSurfaceTexture.SetFilterLinear();
else
LastSurfaceTexture.SetFilterNearest();
sw = surface.Width;
sh = surface.Height;
Resized = false;
// figure out scaling factor
float vw = (float)GraphicsControl.Control.Width;
float vh = (float)GraphicsControl.Control.Height;
float widthScale = vw / surface.Width;
float heightScale = vh / surface.Height;
float finalScale = Math.Min(widthScale, heightScale);
float dx = (int)((vw - finalScale * surface.Width)/2);
float dy = (int)((vh - finalScale * surface.Height)/2);
if (!overlay)
{
GL.SetClearColor(Color.Black); //TODO GL - set from background color
GL.Clear(OpenTK.Graphics.OpenGL.ClearBufferMask.ColorBufferBit);
}
Renderer.Begin(GraphicsControl.Control.ClientSize.Width, GraphicsControl.Control.ClientSize.Height);
if (overlay)
Renderer.SetBlendState(GL.BlendNormal);
else Renderer.SetBlendState(GL.BlendNone);
Renderer.Modelview.Translate(dx, dy);
Renderer.Modelview.Scale(finalScale);
Renderer.Draw(LastSurfaceTexture);
Renderer.End();
GraphicsControl.End();
}
public void Present()
{
GraphicsControl.Begin();
GraphicsControl.SwapBuffers();
GraphicsControl.End();
}
public void RenderOverlay(BitmapBuffer surface)
{
//TODO GL - draw transparent overlay
}
}
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);
sd.Rectangle ClipBounds { get; set; }
}
public interface IBlitterFont { }
}

View File

@ -0,0 +1,278 @@
namespace BizHawk.Client.EmuHawk.config
{
partial class DisplayConfig
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.button1 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.listView2 = new System.Windows.Forms.ListView();
this.label1 = new System.Windows.Forms.Label();
this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.panel1 = new System.Windows.Forms.Panel();
this.panel2 = new System.Windows.Forms.Panel();
this.button2 = new System.Windows.Forms.Button();
this.panel3 = new System.Windows.Forms.Panel();
this.label2 = new System.Windows.Forms.Label();
this.panel4 = new System.Windows.Forms.Panel();
this.listView1 = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.checkBox1 = new System.Windows.Forms.CheckBox();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel1.SuspendLayout();
this.panel1.SuspendLayout();
this.panel2.SuspendLayout();
this.panel3.SuspendLayout();
this.panel4.SuspendLayout();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.Controls.Add(this.button3, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.panel1, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.panel2, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.panel3, 0, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(557, 433);
this.tableLayoutPanel1.TabIndex = 1;
//
// button1
//
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.button1.Location = new System.Drawing.Point(74, 3);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 2;
this.button1.Text = "OK";
this.button1.UseVisualStyleBackColor = true;
//
// button3
//
this.button3.Location = new System.Drawing.Point(3, 407);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(75, 23);
this.button3.TabIndex = 4;
this.button3.Text = "Defaults";
this.button3.UseVisualStyleBackColor = true;
//
// listView2
//
this.listView2.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader4});
this.listView2.Dock = System.Windows.Forms.DockStyle.Fill;
this.listView2.Location = new System.Drawing.Point(0, 13);
this.listView2.Name = "listView2";
this.listView2.Size = new System.Drawing.Size(224, 385);
this.listView2.TabIndex = 5;
this.listView2.UseCompatibleStateImageBehavior = false;
this.listView2.View = System.Windows.Forms.View.Details;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Dock = System.Windows.Forms.DockStyle.Top;
this.label1.Location = new System.Drawing.Point(0, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(38, 13);
this.label1.TabIndex = 6;
this.label1.Text = "Library";
//
// columnHeader4
//
this.columnHeader4.Text = "";
this.columnHeader4.Width = 101;
//
// panel1
//
this.panel1.Controls.Add(this.listView2);
this.panel1.Controls.Add(this.label1);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(330, 3);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(224, 398);
this.panel1.TabIndex = 7;
//
// panel2
//
this.panel2.AutoSize = true;
this.panel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.panel2.Controls.Add(this.button2);
this.panel2.Controls.Add(this.button1);
this.panel2.Location = new System.Drawing.Point(327, 404);
this.panel2.Margin = new System.Windows.Forms.Padding(0);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(230, 29);
this.panel2.TabIndex = 8;
//
// button2
//
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.button2.Location = new System.Drawing.Point(155, 3);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 3;
this.button2.Text = "Cancel";
this.button2.UseVisualStyleBackColor = true;
//
// panel3
//
this.panel3.Controls.Add(this.listView1);
this.panel3.Controls.Add(this.label2);
this.panel3.Controls.Add(this.panel4);
this.panel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel3.Location = new System.Drawing.Point(3, 3);
this.panel3.Name = "panel3";
this.panel3.Size = new System.Drawing.Size(321, 398);
this.panel3.TabIndex = 9;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Dock = System.Windows.Forms.DockStyle.Top;
this.label2.Location = new System.Drawing.Point(0, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(172, 13);
this.label2.TabIndex = 7;
this.label2.Text = "Current Layers/Filters Configuration";
//
// panel4
//
this.panel4.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.panel4.Controls.Add(this.groupBox1);
this.panel4.Dock = System.Windows.Forms.DockStyle.Bottom;
this.panel4.Location = new System.Drawing.Point(0, 298);
this.panel4.Name = "panel4";
this.panel4.Size = new System.Drawing.Size(321, 100);
this.panel4.TabIndex = 4;
//
// listView1
//
this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2,
this.columnHeader3});
this.listView1.Dock = System.Windows.Forms.DockStyle.Fill;
this.listView1.Location = new System.Drawing.Point(0, 13);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(321, 285);
this.listView1.TabIndex = 9;
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.View = System.Windows.Forms.View.Details;
//
// columnHeader1
//
this.columnHeader1.Text = "Input";
this.columnHeader1.Width = 75;
//
// columnHeader2
//
this.columnHeader2.Text = "Output";
this.columnHeader2.Width = 85;
//
// columnHeader3
//
this.columnHeader3.Text = "Description";
this.columnHeader3.Width = 88;
//
// checkBox1
//
this.checkBox1.AutoSize = true;
this.checkBox1.Location = new System.Drawing.Point(6, 19);
this.checkBox1.Name = "checkBox1";
this.checkBox1.Size = new System.Drawing.Size(85, 17);
this.checkBox1.TabIndex = 0;
this.checkBox1.Text = "Bilinear Filter";
this.checkBox1.UseVisualStyleBackColor = true;
//
// groupBox1
//
this.groupBox1.Controls.Add(this.checkBox1);
this.groupBox1.Location = new System.Drawing.Point(7, 3);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(200, 90);
this.groupBox1.TabIndex = 1;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Final Presentation:";
//
// DisplayConfig
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(557, 433);
this.Controls.Add(this.tableLayoutPanel1);
this.Name = "DisplayConfig";
this.Text = "Display Configuration";
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.panel2.ResumeLayout(false);
this.panel3.ResumeLayout(false);
this.panel3.PerformLayout();
this.panel4.ResumeLayout(false);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.ListView listView2;
private System.Windows.Forms.ColumnHeader columnHeader4;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Panel panel3;
private System.Windows.Forms.ListView listView1;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.ColumnHeader columnHeader3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Panel panel4;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.CheckBox checkBox1;
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace BizHawk.Client.EmuHawk.config
{
public partial class DisplayConfig : Form
{
public DisplayConfig()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -59,6 +59,9 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="GraphicsControl_TK.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="IGL_TK.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -0,0 +1,61 @@
using System;
using System.Reflection;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System.Windows.Forms;
using BizHawk.Bizware.BizwareGL;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK
{
class GLControlWrapper : GLControl, IGraphicsControl
{
//Note: In order to work around bugs in OpenTK which sometimes do things to a context without making that context active first...
//we are going to push and pop the context before doing stuff
public GLControlWrapper(IGL_TK owner)
: base(GraphicsMode.Default, 2, 0, GraphicsContextFlags.Default)
{
Owner = owner;
GLControl = this;
}
global::OpenTK.GLControl GLControl;
IGL_TK Owner;
public Control Control { get { return this; } }
public void SetVsync(bool state)
{
//IGraphicsContext curr = global::OpenTK.Graphics.GraphicsContext.CurrentContext;
GLControl.MakeCurrent();
GLControl.VSync = state;
//Owner.MakeContextCurrent(curr, Owner.NativeWindowsForContexts[curr]);
}
public void Begin()
{
Owner.MakeContextCurrent(GLControl.Context, GLControl.WindowInfo);
}
public void End()
{
//this slows things down too much
//Owner.MakeDefaultCurrent();
}
public new void SwapBuffers()
{
//IGraphicsContext curr = global::OpenTK.Graphics.GraphicsContext.CurrentContext;
base.MakeCurrent();
base.SwapBuffers();
//Owner.MakeContextCurrent(curr, Owner.NativeWindowsForContexts[curr]);
}
}
}

View File

@ -74,71 +74,16 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK
GL.ClearColor(color);
}
class GLControlWrapper : GraphicsControl
IGraphicsControl IGL.Internal_CreateGraphicsControl()
{
//Note: In order to work around bugs in OpenTK which sometimes do things to a context without making that context active first...
//we are going to push and pop the context before doing stuff
public GLControlWrapper(IGL_TK owner)
{
Owner = owner;
}
IGL_TK Owner;
public override swf.Control Control { get { return MyControl; } }
public override void SetVsync(bool state)
{
//IGraphicsContext curr = global::OpenTK.Graphics.GraphicsContext.CurrentContext;
MyControl.MakeCurrent();
MyControl.VSync = state;
//Owner.MakeContextCurrent(curr, Owner.NativeWindowsForContexts[curr]);
}
public override void Begin()
{
Owner.MakeContextCurrent(MyControl.Context, MyControl.WindowInfo);
}
public override void End()
{
//this slows things down too much
//Owner.MakeDefaultCurrent();
}
public override void SwapBuffers()
{
//IGraphicsContext curr = global::OpenTK.Graphics.GraphicsContext.CurrentContext;
MyControl.MakeCurrent();
MyControl.SwapBuffers();
//Owner.MakeContextCurrent(curr, Owner.NativeWindowsForContexts[curr]);
}
public override void Dispose()
{
//TODO - what happens if this context was current?
MyControl.Dispose();
MyControl = null;
}
public GLControl MyControl;
}
GraphicsControl IGL.CreateGraphicsControl()
{
var glc = new GLControl(GraphicsMode.Default, 2, 0, GraphicsContextFlags.Default);
var glc = new GLControlWrapper(this);
glc.CreateControl();
//now the control's context will be current. annoying! fix it.
MakeDefaultCurrent();
GLControlWrapper wrapper = new GLControlWrapper(this);
wrapper.MyControl = glc;
//this might be important.. or it might not. it's ready, in case we need it
//glc.GetType().GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(glc, new object[] { System.Windows.Forms.ControlStyles.UserMouse, true });
return wrapper;
return glc;
}
IntPtr IGL.GenTexture() { return new IntPtr(GL.GenTexture()); }
@ -376,6 +321,12 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK
}
}
void IGL.FreeRenderTarget(RenderTarget rt)
{
rt.Texture2d.Dispose();
GL.DeleteFramebuffer(rt.Id.ToInt32());
}
unsafe RenderTarget IGL.CreateRenderTarget(int w, int h)
{
//create a texture for it
@ -557,12 +508,12 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK
}
}
void MakeDefaultCurrent()
internal void MakeDefaultCurrent()
{
MakeContextCurrent(this.GraphicsContext, OffscreenNativeWindow.WindowInfo);
}
void MakeContextCurrent(IGraphicsContext context, global::OpenTK.Platform.IWindowInfo windowInfo)
internal void MakeContextCurrent(IGraphicsContext context, global::OpenTK.Platform.IWindowInfo windowInfo)
{
//TODO - if we're churning through contexts quickly, this will sort of be a memory leak, since they'll be memoized forever in here
//maybe make it a weakptr or something

View File

@ -57,15 +57,21 @@
<Compile Include="Borrowed\BitmapFontParser\Kerning.cs" />
<Compile Include="Borrowed\BitmapFontParser\Padding.cs" />
<Compile Include="Borrowed\BitmapFontParser\Page.cs" />
<Compile Include="GraphicsControl.cs" />
<Compile Include="GraphicsControl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="GuiRenderer.cs" />
<Compile Include="IGL.cs" />
<Compile Include="ArtManager.cs" />
<Compile Include="IGraphicsControl.cs" />
<Compile Include="MatrixStack.cs" />
<Compile Include="Pipeline.cs" />
<Compile Include="PipelineUniform.cs" />
<Compile Include="RenderStates.cs" />
<Compile Include="RenderTarget.cs" />
<Compile Include="RetainedGraphicsControl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Shader.cs" />
<Compile Include="StringRenderer.cs" />
<Compile Include="TexAtlas.cs" />

View File

@ -1,52 +1,53 @@
using System;
using swf = System.Windows.Forms;
using System.Windows.Forms;
namespace BizHawk.Bizware.BizwareGL
{
/// <summary>
/// Represents
/// a base class for deriving/wrapping from a IGraphicsControl.
/// This is to work around the annoyance that we cant inherit from a control whose type is unknown (it would be delivered by the selected BizwareGL driver)
/// and so we have to resort to composition and c# sucks and events suck.
/// </summary>
public abstract class GraphicsControl : IDisposable
public class GraphicsControl : UserControl
{
/// <summary>
/// Gets the control that this interface is wrapping
/// </summary>
public abstract swf.Control Control { get; }
public GraphicsControl(IGL owner)
{
SetStyle(ControlStyles.Opaque, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserMouse, true);
public static implicit operator swf.Control(GraphicsControl ctrl) { return ctrl.Control; }
//in case we need it
//GLControl.GetType().GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(GLControl, new object[] { System.Windows.Forms.ControlStyles.UserMouse, true });
/// <summary>
/// The width of the control
/// </summary>
public int Width { get { return Control.Width; } }
/// <summary>
/// The height of the control
/// </summary>
public int Height { get { return Control.Height; } }
/// <summary>
/// Sets whether presentation operations on this control will vsync
/// </summary>
public abstract void SetVsync(bool state);
IGC = owner.Internal_CreateGraphicsControl();
Managed = IGC as Control;
Managed.Dock = DockStyle.Fill;
Controls.Add(Managed);
/// <summary>
/// Swaps the buffers for this control
/// </summary>
public abstract void SwapBuffers();
//pass through these events to the form. I tried really hard to find a better way, but there is none.
//(dont use HTTRANSPARENT, it isnt portable, I would assume)
Managed.MouseDoubleClick += (object sender, MouseEventArgs e) => OnMouseDoubleClick(e);
Managed.MouseClick += (object sender, MouseEventArgs e) => OnMouseClick(e);
/// <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
/// </summary>
public abstract void Begin();
//the GraphicsControl is occupying all of our area. So we pretty much never get paint events ourselves.
//So lets capture its paint event and use it for ourselves (it doesnt know how to do anything, anyway)
Managed.Paint += new PaintEventHandler(GraphicsControl_Paint);
}
/// <summary>
/// Ends rendering on the specified control.
/// </summary>
public abstract void End();
void GraphicsControl_Paint(object sender, PaintEventArgs e)
{
OnPaint(e);
}
public abstract void Dispose();
IGraphicsControl IGC;
Control Managed;
//public virtual Control Control { get { return Managed; } } //do we need this anymore?
public virtual void SetVsync(bool state) { IGC.SetVsync(state); }
public virtual void SwapBuffers() { IGC.SwapBuffers(); }
public virtual void Begin() { IGC.Begin(); }
public virtual void End() { IGC.End(); }
}
}

View File

@ -17,10 +17,6 @@ namespace BizHawk.Bizware.BizwareGL
/// </summary>
public interface IGL : IDisposable
{
/// <summary>
/// Returns an a control optimized for drawing onto the screen.
/// </summary>
GraphicsControl CreateGraphicsControl();
/// <summary>
/// Clears the specified buffer parts
@ -113,6 +109,11 @@ namespace BizHawk.Bizware.BizwareGL
/// </summary>
void FreeTexture(IntPtr texHandle);
/// <summary>
/// frees the provided render target
/// </summary>
void FreeRenderTarget(RenderTarget rt);
/// <summary>
/// Binds this texture as the current texture2d target for parameter-specification
/// </summary>
@ -218,5 +219,7 @@ namespace BizHawk.Bizware.BizwareGL
/// Binds a RenderTarget for current rendering
/// </summary>
void BindRenderTarget(RenderTarget rt);
IGraphicsControl Internal_CreateGraphicsControl();
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Windows.Forms;
namespace BizHawk.Bizware.BizwareGL
{
public interface IGraphicsControl : IDisposable
{
/// <summary>
/// Sets whether presentation operations on this control will vsync
/// </summary>
void SetVsync(bool state);
/// <summary>
/// Swaps the buffers for this control
/// </summary>
void SwapBuffers();
/// <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
/// </summary>
void Begin();
/// <summary>
/// Ends rendering on the specified control.
/// </summary>
void End();
}
}

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace BizHawk.Bizware.BizwareGL
{
public class RenderTarget
public class RenderTarget : IDisposable
{
public RenderTarget(IGL owner, IntPtr handle, Texture2d tex)
{
@ -25,5 +25,10 @@ namespace BizHawk.Bizware.BizwareGL
{
Owner.BindRenderTarget(this);
}
public void Dispose()
{
Owner.FreeRenderTarget(this);
}
}
}

View File

@ -0,0 +1,104 @@
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BizHawk.Bizware.BizwareGL;
using OpenTK.Graphics.OpenGL;
namespace BizHawk.Bizware.Test
{
/// <summary>
/// Adapts a GraphicsControl to gain the power of remembering what was drawn to it, and keeping it presented in response to Paint events
/// </summary>
public class RetainedGraphicsControl : GraphicsControl
{
public RetainedGraphicsControl(IGL gl)
: base(gl)
{
GL = gl;
GuiRenderer = new GuiRenderer(gl);
}
/// <summary>
/// Control whether rendering goes into the retaining buffer (it's slower) or straight to the viewport.
/// This could be useful as a performance hack, or if someone was very clever, they could wait for a control to get deactivated, enable retaining, and render it one more time.
/// Of course, even better still is to be able to repaint viewports continually, but sometimes thats annoying.
/// </summary>
public bool Retain
{
get { return _retain; }
set
{
if (_retain && !value)
{
rt.Dispose();
rt = null;
}
_retain = value;
}
}
bool _retain = true;
IGL GL;
RenderTarget rt;
GuiRenderer GuiRenderer;
public override void Begin()
{
base.Begin();
if (_retain)
{
//TODO - frugalize me
if (rt != null)
rt.Dispose();
rt = GL.CreateRenderTarget(Width, Height);
rt.Bind();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//todo - check whether we're begun?
base.Begin();
Draw();
base.End();
}
void Draw()
{
if (rt == null) return;
GuiRenderer.Begin(Width, Height, true);
GuiRenderer.SetBlendState(GL.BlendNone);
GuiRenderer.Draw(rt.Texture2d);
GuiRenderer.End();
base.SwapBuffers();
}
public override void SwapBuffers()
{
//if we're not retaining, then we havent been collecting into a framebuffer. just swap it
if (!_retain)
{
base.SwapBuffers();
return;
}
//if we're retaining, then we cant draw until we unbind! its semantically a bit odd, but we expect users to call SwapBuffers() before end, so we cant unbind in End() even thoug hit makes a bit more sense.
rt.Unbind();
Draw();
}
public override void End()
{
if (_retain)
rt.Unbind();
base.End();
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
@ -11,12 +12,11 @@ namespace BizHawk.Bizware.Test
{
class Program
{
static unsafe void Main(string[] args)
{
BizHawk.Bizware.BizwareGL.IGL igl = new BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK();
List<Art> testArts = new List<Art>();
ArtManager am = new ArtManager(igl);
foreach (var name in typeof(Program).Assembly.GetManifestResourceNames())
@ -31,11 +31,10 @@ namespace BizHawk.Bizware.Test
GuiRenderer gr = new GuiRenderer(igl);
TestForm tf = new TestForm();
GraphicsControl c = igl.CreateGraphicsControl();
RetainedGraphicsControl c = new RetainedGraphicsControl(igl);
tf.Controls.Add(c);
c.Control.Dock = System.Windows.Forms.DockStyle.Fill;
c.Dock = System.Windows.Forms.DockStyle.Fill;
tf.FormClosing += (object sender, System.Windows.Forms.FormClosingEventArgs e) =>
{
tf.Controls.Remove(c);
@ -44,6 +43,8 @@ namespace BizHawk.Bizware.Test
};
tf.Show();
//tf.Paint += (object sender, PaintEventArgs e) => c.Refresh();
c.SetVsync(false);
//create a render target, in the control context
@ -58,45 +59,57 @@ namespace BizHawk.Bizware.Test
rt.Unbind();
c.End();
bool running = true;
c.MouseClick += (object sender, MouseEventArgs e) =>
{
if(e.Button == MouseButtons.Left)
running ^= true;
if (e.Button == MouseButtons.Right)
c.Retain ^= true;
};
DateTime start = DateTime.Now;
int wobble = 0;
for (; ; )
{
if (c == null) break;
c.Begin();
if (running)
{
c.Begin();
igl.SetClearColor(Color.Red);
igl.Clear(ClearBufferMask.ColorBufferBit);
igl.SetClearColor(Color.Red);
igl.Clear(ClearBufferMask.ColorBufferBit);
int frame = (int)((DateTime.Now - start).TotalSeconds) % testArts.Count;
int frame = (int)((DateTime.Now - start).TotalSeconds) % testArts.Count;
gr.Begin(c.ClientSize.Width, c.ClientSize.Height);
gr.Begin(c.Control.ClientSize.Width, c.Control.ClientSize.Height);
gr.SetBlendState(igl.BlendNone);
gr.Draw(rt.Texture2d, 0, 20);
gr.SetBlendState(igl.BlendNormal);
gr.SetBlendState(igl.BlendNone);
gr.Draw(rt.Texture2d, 0, 20);
gr.SetBlendState(igl.BlendNormal);
sr.RenderString(gr, 0, 0, "?? fps");
gr.Modelview.Translate((float)Math.Sin(wobble / 360.0f) * 50, 0);
gr.Modelview.Translate(100, 100);
gr.Modelview.Push();
gr.Modelview.Translate(testArts[frame].Width, 0);
gr.Modelview.Scale(-1, 1);
wobble++;
gr.SetModulateColor(Color.Yellow);
gr.DrawFlipped(testArts[frame], true, false);
gr.SetModulateColorWhite();
gr.Modelview.Pop();
gr.SetBlendState(igl.BlendNormal);
gr.Draw(smile);
gr.End();
sr.RenderString(gr, 0, 0, "?? fps");
gr.Modelview.Translate((float)Math.Sin(wobble / 360.0f) * 50, 0);
gr.Modelview.Translate(100, 100);
gr.Modelview.Push();
gr.Modelview.Translate(testArts[frame].Width, 0);
gr.Modelview.Scale(-1, 1);
wobble++;
gr.SetModulateColor(Color.Yellow);
gr.DrawFlipped(testArts[frame], true, false);
gr.SetModulateColorWhite();
gr.Modelview.Pop();
gr.SetBlendState(igl.BlendNormal);
gr.Draw(smile);
gr.End();
c.SwapBuffers();
c.End();
c.SwapBuffers();
c.End();
}
System.Windows.Forms.Application.DoEvents();
System.Threading.Thread.Sleep(0);
}
}
}