cleanup GraphicsImplementations files

This commit is contained in:
adelikat 2020-02-28 12:32:45 -06:00
parent 402acad0f6
commit 4a943f3a60
4 changed files with 130 additions and 139 deletions

View File

@ -1,40 +1,23 @@
using System;
using System.Drawing;
using System.Reflection;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Client.EmuHawk
{
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);
_gdi = gdi;
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);
private readonly IGL_GdiPlus _gdi;
//if(MyBufferedGraphics != null)
}
IGL_GdiPlus Gdi;
public Control Control { get { return this; } }
public Control Control => this;
/// <summary>
@ -44,12 +27,12 @@ namespace BizHawk.Client.EmuHawk
public void SetVsync(bool state)
{
//not really supported now...
// not really supported now...
}
public void Begin()
{
Gdi.BeginControl(this);
_gdi.BeginControl(this);
RenderTargetWrapper.CreateGraphics();
//using (var g = CreateGraphics())
// MyBufferedGraphics = Gdi.MyBufferedGraphicsContext.Allocate(g, ClientRectangle);
@ -63,25 +46,27 @@ namespace BizHawk.Client.EmuHawk
public void End()
{
Gdi.EndControl(this);
_gdi.EndControl(this);
}
public void SwapBuffers()
{
Gdi.SwapControl(this);
_gdi.SwapControl(this);
if (RenderTargetWrapper.MyBufferedGraphics == null)
{
return;
}
using (var g = CreateGraphics())
{
//not sure we had proof we needed this but it cant hurt
g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
// not sure we had proof we needed this but it cant hurt
g.CompositingMode = CompositingMode.SourceCopy;
g.CompositingQuality = CompositingQuality.HighSpeed;
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?
//maybe I should try caching harder, I hate to reallocate these constantly
// 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?
// maybe I should try caching harder, I hate to reallocate these constantly
RenderTargetWrapper.CreateGraphics();
}
}

View File

@ -1,6 +1,4 @@
using System;
using System.Windows.Forms;
using BizHawk.Bizware.BizwareGL;
namespace BizHawk.Client.EmuHawk
@ -23,24 +21,23 @@ namespace BizHawk.Client.EmuHawk
//in case we need it
//GLControl.GetType().GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(GLControl, new object[] { System.Windows.Forms.ControlStyles.UserMouse, true });
IGC = owner.Internal_CreateGraphicsControl();
Managed = IGC as Control;
Managed.Dock = DockStyle.Fill;
Controls.Add(Managed);
_igc = owner.Internal_CreateGraphicsControl();
_managed = _igc as Control;
_managed.Dock = DockStyle.Fill;
Controls.Add(_managed);
//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);
Managed.MouseEnter += (object sender, EventArgs e) => OnMouseEnter(e);
Managed.MouseLeave += (object sender, EventArgs e) => OnMouseLeave(e);
Managed.MouseMove += (object sender, MouseEventArgs e) => OnMouseMove(e);
// pass through these events to the form. I tried really hard to find a better way, but there is none.
// (don't use HTTRANSPARENT, it isn't portable, I would assume)
_managed.MouseDoubleClick += (sender, e) => OnMouseDoubleClick(e);
_managed.MouseClick += (sender, e) => OnMouseClick(e);
_managed.MouseEnter += (sender, e) => OnMouseEnter(e);
_managed.MouseLeave += (sender, e) => OnMouseLeave(e);
_managed.MouseMove += (sender, e) => OnMouseMove(e);
//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);
//So lets capture its paint event and use it for ourselves (it doesn't know how to do anything, anyway)
_managed.Paint += GraphicsControl_Paint;
}
/// <summary>
@ -55,13 +52,12 @@ namespace BizHawk.Client.EmuHawk
public readonly IGL IGL;
IGraphicsControl IGC;
Control Managed;
private readonly IGraphicsControl _igc;
readonly 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(); }
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

@ -1,17 +1,15 @@
//regarding binding and vertex arrays:
//http://stackoverflow.com/questions/8704801/glvertexattribpointer-clarification
//http://stackoverflow.com/questions/9536973/oes-vertex-array-object-and-client-state
//http://www.opengl.org/wiki/Vertex_Specification
// regarding binding and vertex arrays:
// http://stackoverflow.com/questions/8704801/glvertexattribpointer-clarification
// http://stackoverflow.com/questions/9536973/oes-vertex-array-object-and-client-state
// http://www.opengl.org/wiki/Vertex_Specification
//etc
//glBindAttribLocation (programID, 0, "vertexPosition_modelspace");
// etc
// glBindAttribLocation (programID, 0, "vertexPosition_modelspace");
//for future reference: c# tesselators
//http://www.opentk.com/node/437 (AGG#, codes on Tao forums)
// for future reference: c# tesselators
// http://www.opentk.com/node/437 (AGG#, codes on Tao forums)
using System;
using System.Reflection;
using System.Threading;
using System.IO;
using System.Collections.Generic;
@ -35,8 +33,8 @@ namespace BizHawk.Client.EmuHawk
public class IGL_TK : IGL
{
//rendering state
Pipeline _CurrPipeline;
RenderTarget _CurrRenderTarget;
private Pipeline _currPipeline;
private RenderTarget _currRenderTarget;
static IGL_TK()
{
@ -68,11 +66,11 @@ namespace BizHawk.Client.EmuHawk
}
}
public IGL_TK(int major_version, int minor_version, bool forward_compatible)
public IGL_TK(int majorVersion, int minorVersion, bool forwardCompatible)
{
//make an 'offscreen context' so we can at least do things without having to create a window
OffscreenNativeWindow = new NativeWindow { ClientSize = new sd.Size(8, 8) };
GraphicsContext = new GraphicsContext(GraphicsMode.Default, OffscreenNativeWindow.WindowInfo, major_version, minor_version, forward_compatible ? GraphicsContextFlags.ForwardCompatible : GraphicsContextFlags.Default);
GraphicsContext = new GraphicsContext(GraphicsMode.Default, OffscreenNativeWindow.WindowInfo, majorVersion, minorVersion, forwardCompatible ? GraphicsContextFlags.ForwardCompatible : GraphicsContextFlags.Default);
MakeDefaultCurrent();
//this is important for reasons unknown
@ -85,12 +83,12 @@ namespace BizHawk.Client.EmuHawk
public void BeginScene()
{
//seems not to be needed...
// seems not to be needed...
}
public void EndScene()
{
//seems not to be needed...
// seems not to be needed...
}
void IDisposable.Dispose()
@ -102,7 +100,7 @@ namespace BizHawk.Client.EmuHawk
public void Clear(ClearBufferMask mask)
{
GL.Clear((global::OpenTK.Graphics.OpenGL.ClearBufferMask)mask);
GL.Clear(mask);
}
public void SetClearColor(sd.Color color)
{
@ -114,14 +112,14 @@ namespace BizHawk.Client.EmuHawk
var glc = new GLControlWrapper(this);
glc.CreateControl();
//now the control's context will be current. annoying! fix it.
// now the control's context will be current. annoying! fix it.
MakeDefaultCurrent();
return glc;
}
public int GenTexture() { return GL.GenTexture(); }
public int GenTexture() => GL.GenTexture();
public void FreeTexture(Texture2d tex)
{
GL.DeleteTexture((int)tex.Opaque);
@ -131,6 +129,7 @@ namespace BizHawk.Client.EmuHawk
{
return CreateShader(cg, ShaderType.FragmentShader, source, entry, required);
}
public Shader CreateVertexShader(bool cg, string source, string entry, bool required)
{
return CreateShader(cg, ShaderType.VertexShader, source, entry, required);
@ -163,14 +162,14 @@ namespace BizHawk.Client.EmuHawk
public IBlendState BlendNoneOpaque => _rsBlendNoneOpaque;
public IBlendState BlendNormal => _rsBlendNormal;
class ShaderWrapper
private class ShaderWrapper
{
public int sid;
public Dictionary<string, string> MapCodeToNative;
public Dictionary<string, string> MapNativeToCode;
}
class PipelineWrapper
private class PipelineWrapper
{
public int pid;
public Shader FragmentShader, VertexShader;
@ -183,7 +182,7 @@ namespace BizHawk.Client.EmuHawk
/// </exception>
public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, Shader fragmentShader, bool required, string memo)
{
//if the shaders arent available, the pipeline isn't either
// if the shaders aren't available, the pipeline isn't either
if (!vertexShader.Available || !fragmentShader.Available)
{
string errors = $"Vertex Shader:\r\n {vertexShader.Errors} \r\n-------\r\nFragment Shader:\r\n{fragmentShader.Errors}";
@ -240,7 +239,6 @@ namespace BizHawk.Client.EmuHawk
// //GL.BindAttribLocation(pid, kvp.Key, name);
//}
GL.LinkProgram(pid);
errcode = GL.GetError();
@ -327,13 +325,13 @@ namespace BizHawk.Client.EmuHawk
uniforms.Add(ui);
}
//deactivate the program, so we dont accidentally use it
// deactivate the program, so we don't accidentally use it
GL.UseProgram(0);
if (!vertexShader.Available) success = false;
if (!fragmentShader.Available) success = false;
var pw = new PipelineWrapper() { pid = pid, VertexShader = vertexShader, FragmentShader = fragmentShader, SamplerLocs = samplers };
var pw = new PipelineWrapper { pid = pid, VertexShader = vertexShader, FragmentShader = fragmentShader, SamplerLocs = samplers };
return new Pipeline(this, pw, success, vertexLayout, uniforms, memo);
}
@ -342,9 +340,11 @@ namespace BizHawk.Client.EmuHawk
{
var pw = pipeline.Opaque as PipelineWrapper;
//unavailable pipelines will have no opaque
// unavailable pipelines will have no opaque
if (pw == null)
{
return;
}
GL.DeleteProgram(pw.pid);
@ -361,7 +361,7 @@ namespace BizHawk.Client.EmuHawk
/// <exception cref="InvalidOperationException"><paramref name="pipeline"/>.<see cref="Pipeline.Available"/> is <see langword="false"/></exception>
public void BindPipeline(Pipeline pipeline)
{
_CurrPipeline = pipeline;
_currPipeline = pipeline;
if (pipeline == null)
{
@ -384,7 +384,7 @@ namespace BizHawk.Client.EmuHawk
}
public VertexLayout CreateVertexLayout() { return new VertexLayout(this, null); }
public VertexLayout CreateVertexLayout() => new VertexLayout(this, null);
private void BindTexture2d(Texture2d tex)
{
@ -397,10 +397,13 @@ namespace BizHawk.Client.EmuHawk
int mode;
if (clamp)
{
mode = (int)global::OpenTK.Graphics.OpenGL.TextureWrapMode.ClampToEdge;
mode = (int)TextureWrapMode.ClampToEdge;
}
else
mode = (int)global::OpenTK.Graphics.OpenGL.TextureWrapMode.Repeat;
{
mode = (int)TextureWrapMode.Repeat;
}
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, mode);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, mode);
}
@ -412,7 +415,7 @@ namespace BizHawk.Client.EmuHawk
public void DrawArrays(PrimitiveType mode, int first, int count)
{
GL.DrawArrays((global::OpenTK.Graphics.OpenGL.PrimitiveType)mode, first, count);
GL.DrawArrays(mode, first, count);
}
public void SetPipelineUniform(PipelineUniform uniform, bool value)
@ -469,14 +472,14 @@ namespace BizHawk.Client.EmuHawk
GL.ActiveTexture(selectedUnit);
}
//now bind the texture
// now bind the texture
GL.BindTexture(TextureTarget.Texture2D, (int)tex.Opaque);
}
public void TexParameter2d(Texture2d tex, TextureParameterName pname, int param)
public void TexParameter2d(Texture2d tex, TextureParameterName pName, int param)
{
BindTexture2d(tex);
GL.TexParameter(TextureTarget.Texture2D, (global::OpenTK.Graphics.OpenGL.TextureParameterName)pname, param);
GL.TexParameter(TextureTarget.Texture2D, pName, param);
}
public Texture2d LoadTexture(sd.Bitmap bitmap)
@ -504,15 +507,15 @@ namespace BizHawk.Client.EmuHawk
public void LoadTextureData(Texture2d tex, BitmapBuffer bmp)
{
sdi.BitmapData bmp_data = bmp.LockBits();
sdi.BitmapData bmpData = bmp.LockBits();
try
{
GL.BindTexture(TextureTarget.Texture2D, (int)tex.Opaque);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bmp.Width, bmp.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bmp.Width, bmp.Height, PixelFormat.Bgra, PixelType.UnsignedByte, bmpData.Scan0);
}
finally
{
bmp.UnlockBits(bmp_data);
bmp.UnlockBits(bmpData);
}
}
@ -526,41 +529,48 @@ namespace BizHawk.Client.EmuHawk
public unsafe RenderTarget CreateRenderTarget(int w, int h)
{
//create a texture for it
int texid = GenTexture();
Texture2d tex = new Texture2d(this, texid, w, h);
GL.BindTexture(TextureTarget.Texture2D,texid);
int texId = GenTexture();
Texture2d tex = new Texture2d(this, texId, w, h);
GL.BindTexture(TextureTarget.Texture2D, texId);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, w, h, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
tex.SetMagFilter(TextureMagFilter.Nearest);
tex.SetMinFilter(TextureMinFilter.Nearest);
//create the FBO
int fbid = GL.Ext.GenFramebuffer();
GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, fbid);
// create the FBO
int fbId = GL.Ext.GenFramebuffer();
GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, fbId);
//bind the tex to the FBO
GL.Ext.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, texid, 0);
GL.Ext.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, texId, 0);
//do something, I guess say which colorbuffers are used by the framebuffer
// do something, I guess say which color buffers are used by the framebuffer
DrawBuffersEnum* buffers = stackalloc DrawBuffersEnum[1];
buffers[0] = DrawBuffersEnum.ColorAttachment0;
GL.DrawBuffers(1, buffers);
if (GL.Ext.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete)
if (GL.Ext.CheckFramebufferStatus(FramebufferTarget.Framebuffer) !=
FramebufferErrorCode.FramebufferComplete)
{
throw new InvalidOperationException($"Error creating framebuffer (at {nameof(GL.Ext.CheckFramebufferStatus)})");
}
//since we're done configuring unbind this framebuffer, to return to the default
// since we're done configuring unbind this framebuffer, to return to the default
GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
return new RenderTarget(this, fbid, tex);
return new RenderTarget(this, fbId, tex);
}
public void BindRenderTarget(RenderTarget rt)
{
_CurrRenderTarget = rt;
if(rt == null)
_currRenderTarget = rt;
if (rt == null)
{
GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
}
else
{
GL.Ext.BindFramebuffer(FramebufferTarget.Framebuffer, (int)rt.Opaque);
}
}
public Texture2d LoadTexture(BitmapBuffer bmp)
@ -631,7 +641,7 @@ namespace BizHawk.Client.EmuHawk
ret.M42 = (float)dims.Height * 0.5f;
if (autoflip)
{
if (_CurrRenderTarget == null) { }
if (_currRenderTarget == null) { }
else
{
//flip as long as we're not a final render target
@ -795,7 +805,7 @@ namespace BizHawk.Client.EmuHawk
foreach (var kvp in layout.Items)
{
if(_CurrPipeline.Memo == "gui")
if(_currPipeline.Memo == "gui")
{
GL.VertexAttribPointer(kvp.Key, kvp.Value.Components, (VertexAttribPointerType)kvp.Value.AttribType, kvp.Value.Normalized, kvp.Value.Stride, new IntPtr(pData) + kvp.Value.Offset);
GL.EnableVertexAttribArray(kvp.Key);
@ -804,7 +814,7 @@ namespace BizHawk.Client.EmuHawk
else
{
var pw = _CurrPipeline.Opaque as PipelineWrapper;
var pw = _currPipeline.Opaque as PipelineWrapper;
//comment SNACKPANTS
switch (kvp.Value.Usage)

View File

@ -1,12 +1,5 @@
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.Client.EmuHawk
{
@ -18,14 +11,14 @@ namespace BizHawk.Client.EmuHawk
public RetainedGraphicsControl(IGL gl)
: base(gl)
{
GL = gl;
GuiRenderer = new GuiRenderer(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.
/// Of course, even better still is to be able to repaint viewports continually, but sometimes that's annoying.
/// </summary>
public bool Retain
{
@ -34,17 +27,18 @@ namespace BizHawk.Client.EmuHawk
{
if (_retain && !value)
{
rt.Dispose();
rt = null;
_rt.Dispose();
_rt = null;
}
_retain = value;
}
}
bool _retain = true;
IGL GL;
RenderTarget rt;
GuiRenderer GuiRenderer;
private bool _retain = true;
private readonly IGL _gl;
private RenderTarget _rt;
private readonly GuiRenderer _guiRenderer;
public override void Begin()
{
@ -52,52 +46,58 @@ namespace BizHawk.Client.EmuHawk
if (_retain)
{
//TODO - frugalize me
rt?.Dispose();
rt = GL.CreateRenderTarget(Width, Height);
rt.Bind();
// TODO - frugalize me
_rt?.Dispose();
_rt = _gl.CreateRenderTarget(Width, Height);
_rt.Bind();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//todo - check whether we're begun?
// todo - check whether we're begun?
base.Begin();
Draw();
base.End();
}
void Draw()
private void Draw()
{
if (rt == null) return;
GuiRenderer.Begin(Width, Height);
GuiRenderer.SetBlendState(GL.BlendNoneCopy);
GuiRenderer.Draw(rt.Texture2d);
GuiRenderer.End();
if (_rt == null)
{
return;
}
_guiRenderer.Begin(Width, Height);
_guiRenderer.SetBlendState(_gl.BlendNoneCopy);
_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 we're not retaining, then we haven't 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();
// 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();
{
_rt.Unbind();
}
base.End();
}
}
}