From bc4a7e70a75d3282d5389a1ba840e44f1320c2a1 Mon Sep 17 00:00:00 2001 From: zeromus Date: Mon, 27 Jan 2014 09:36:18 +0000 Subject: [PATCH] BizwareGL-rendertarget support --- .../IGL_TK.cs | 62 ++++++++++++++++--- .../BizHawk.Bizware.BizwareGL/BitmapBuffer.cs | 31 +++++++--- .../BizHawk.Bizware.BizwareGL.csproj | 1 + .../BizHawk.Bizware.BizwareGL/GuiRenderer.cs | 18 +++++- Bizware/BizHawk.Bizware.BizwareGL/IGL.cs | 15 +++++ .../BizHawk.Bizware.BizwareGL/RenderTarget.cs | 29 +++++++++ Bizware/BizHawk.Bizware.Test/Program.cs | 23 ++++++- 7 files changed, 159 insertions(+), 20 deletions(-) create mode 100644 Bizware/BizHawk.Bizware.BizwareGL/RenderTarget.cs diff --git a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs index 4915a074de..b8ef661bc6 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs @@ -55,6 +55,7 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK //misc initialization CreateRenderStates(); + GL.Enable(EnableCap.Texture2D); } void IDisposable.Dispose() @@ -155,6 +156,7 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK { int sid = GL.CreateShader(ShaderType.VertexShader); CompileShaderSimple(sid, source); + return new Shader(this, new IntPtr(sid)); } @@ -237,17 +239,22 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK if (validateStatus == 0) throw new InvalidOperationException("Error creating pipeline (validateStatus status false returned from glValidateProgram): " + errcode + "\r\n\r\n" + resultLog); + //set the program to active, in case we need to set sampler uniforms on it + GL.UseProgram(pid); + //get all the uniforms List uniforms = new List(); int nUniforms; int nSamplers = 0; GL.GetProgram(pid,GetProgramParameterName.ActiveUniforms,out nUniforms); + for (int i = 0; i < nUniforms; i++) { int size, length; ActiveUniformType type; var sbName = new System.Text.StringBuilder(); GL.GetActiveUniform(pid, i, 1024, out length, out size, out type, sbName); + errcode = GL.GetError(); string name = sbName.ToString(); int loc = GL.GetUniformLocation(pid, name); var ui = new UniformInfo(); @@ -266,6 +273,8 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK uniforms.Add(ui); } + //deactivate the program, so we dont accidentally use it + GL.UseProgram(0); return new Pipeline(this, new IntPtr(pid), uniforms); } @@ -316,7 +325,7 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK void IGL.SetPipelineUniformSampler(PipelineUniform uniform, IntPtr texHandle) { //set the sampler index into the uniform first - GL.Uniform1(uniform.Id.ToInt32(), uniform.SamplerIndex); + //GL.Uniform1(uniform.Id.ToInt32(), uniform.SamplerIndex); //now bind the texture GL.ActiveTexture((TextureUnit)((int)TextureUnit.Texture0 + uniform.SamplerIndex)); GL.BindTexture(TextureTarget.Texture2D, texHandle.ToInt32()); @@ -359,6 +368,45 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK } } + unsafe RenderTarget IGL.CreateRenderTarget(int w, int h) + { + //create a texture for it + IntPtr texid = (this as IGL).GenTexture(); + Texture2d tex = new Texture2d(this, texid, w, h); + GL.BindTexture(TextureTarget.Texture2D,texid.ToInt32()); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, w,h, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero); + tex.SetMagFilter(TextureMagFilter.Nearest); + tex.SetMinFilter(TextureMinFilter.Nearest); + + //create the FBO + int fbid = GL.GenFramebuffer(); + GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbid); + + //bind the tex to the FBO + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, texid.ToInt32(), 0); + + //do something, I guess say which colorbuffers are used by the framebuffer + DrawBuffersEnum* buffers = stackalloc DrawBuffersEnum[1]; + buffers[0] = DrawBuffersEnum.ColorAttachment0; + GL.DrawBuffers(1, buffers); + + if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete) + throw new InvalidOperationException("Error creating framebuffer (at CheckFramebufferStatus)"); + + //since we're done configuring unbind this framebuffer, to return to the default + GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); + + return new RenderTarget(this, new IntPtr(fbid), tex); + } + + void IGL.BindRenderTarget(RenderTarget rt) + { + if(rt == null) + GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); + else + GL.BindFramebuffer(FramebufferTarget.Framebuffer, rt.Id.ToInt32()); + } + Texture2d IGL.LoadTexture(BitmapBuffer bmp) { Texture2d ret = null; @@ -408,9 +456,12 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK void IGL.SetViewport(int x, int y, int width, int height) { - ErrorCode errcode; GL.Viewport(x, y, width, height); - errcode = GL.GetError(); + } + + void IGL.SetViewport(int width, int height) + { + GL.Viewport(0, 0, width, height); } void IGL.SetViewport(swf.Control control) @@ -450,11 +501,6 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK string result = GL.GetShaderInfoLog(sid); if (result != "") throw new InvalidOperationException("Error compiling shader:\r\n\r\n" + result); - - //HAX??? - GL.Enable(EnableCap.Texture2D); - //GL.PolygonMode(MaterialFace.Back, PolygonMode.Line); //?? - //GL.PolygonMode(MaterialFace.Front, PolygonMode.Line); //?? } Dictionary StateCurrentVertexLayouts = new Dictionary(); diff --git a/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs b/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs index 6588ea8f56..5d15763061 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL/BitmapBuffer.cs @@ -200,6 +200,18 @@ namespace BizHawk.Bizware.BizwareGL else LoadInternal(null, bitmap, options); } + + /// + /// Initializes a BitmapBuffer --WRAPPED-- from the supplied parameters, which should definitely have a stride==width and be in the standard color format + /// + public BitmapBuffer(int width, int height, int[] pixels) + { + this.Pixels = pixels; + this.Width = width; + this.Height = height; + } + + void LoadInternal(Stream stream, sd.Bitmap bitmap, BitmapLoadOptions options) { bool cleanup = options.CleanupAlpha0; @@ -344,8 +356,19 @@ namespace BizHawk.Bizware.BizwareGL InitSize(width, height); } + /// + /// Makes a new bitmap buffer, in ??? state + /// public BitmapBuffer() { } + /// + /// initializes an empty BitmapBuffer, cleared to all 0 + /// + public BitmapBuffer(Size size) + { + InitSize(size.Width, size.Height); + } + /// /// clears this instance to (0,0,0,0) -- without allocating a new array (to avoid GC churn) /// @@ -386,14 +409,6 @@ namespace BizHawk.Bizware.BizwareGL Pixels = arr; } - /// - /// initializes an empty BitmapBuffer, cleared to all 0 - /// - public BitmapBuffer(Size size) - { - InitSize(size.Width, size.Height); - } - void InitSize(int width, int height) { Pixels = new int[width * height]; diff --git a/Bizware/BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj b/Bizware/BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj index 989e85ae47..8d66bd272e 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj +++ b/Bizware/BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj @@ -66,6 +66,7 @@ + diff --git a/Bizware/BizHawk.Bizware.BizwareGL/GuiRenderer.cs b/Bizware/BizHawk.Bizware.BizwareGL/GuiRenderer.cs index 313dad3bff..df12136681 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL/GuiRenderer.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL/GuiRenderer.cs @@ -98,16 +98,25 @@ namespace BizHawk.Bizware.BizwareGL } } + /// /// begin rendering, initializing viewport and projections to the given dimensions /// - public void Begin(int width, int height) + /// Whether the matrices should be Y-flipped, for use with render targets + public void Begin(int width, int height, bool yflipped = false) { Begin(); Projection = Owner.CreateGuiProjectionMatrix(width, height); Modelview = Owner.CreateGuiViewMatrix(width, height); - Owner.SetViewport(0, 0, 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); } /// @@ -183,6 +192,11 @@ namespace BizHawk.Bizware.BizwareGL /// public void Draw(Texture2d tex) { DrawInternal(tex, 0, 0, tex.Width, tex.Height); } + /// + /// draws the specified texture2d resource. + /// + public void Draw(Texture2d tex, float x, float y) { DrawInternal(tex, x, y, tex.Width, tex.Height); } + /// /// draws the specified Art resource with the given flip flags /// diff --git a/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs b/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs index 710bc288a4..2cf4b2dcf2 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL/IGL.cs @@ -187,6 +187,11 @@ namespace BizHawk.Bizware.BizwareGL /// void SetViewport(int x, int y, int width, int height); + /// + /// sets the viewport according to the provided specifications + /// + void SetViewport(int width, int height); + /// /// sets the viewport according to the client area of the provided control /// @@ -202,5 +207,15 @@ namespace BizHawk.Bizware.BizwareGL /// re-establishing of a normal 2d graphics top-left origin. suitable for use in a GUI /// Matrix4 CreateGuiViewMatrix(int w, int h); + + /// + /// Creates a render target. Includes a color buffer. Pixel format control TBD + /// + RenderTarget CreateRenderTarget(int w, int h); + + /// + /// Binds a RenderTarget for current rendering + /// + void BindRenderTarget(RenderTarget rt); } } diff --git a/Bizware/BizHawk.Bizware.BizwareGL/RenderTarget.cs b/Bizware/BizHawk.Bizware.BizwareGL/RenderTarget.cs new file mode 100644 index 0000000000..2dc8736b04 --- /dev/null +++ b/Bizware/BizHawk.Bizware.BizwareGL/RenderTarget.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; + +namespace BizHawk.Bizware.BizwareGL +{ + public class RenderTarget + { + public RenderTarget(IGL owner, IntPtr handle, Texture2d tex) + { + Owner = owner; + Id = handle; + Texture2d = tex; + } + + public IntPtr Id { get; private set; } + public IGL Owner { get; private set; } + public Texture2d Texture2d { get; private set; } + + public void Unbind() + { + Owner.BindRenderTarget(null); + } + + public void Bind() + { + Owner.BindRenderTarget(this); + } + } +} \ No newline at end of file diff --git a/Bizware/BizHawk.Bizware.Test/Program.cs b/Bizware/BizHawk.Bizware.Test/Program.cs index 2dcf882c52..eeb331f897 100644 --- a/Bizware/BizHawk.Bizware.Test/Program.cs +++ b/Bizware/BizHawk.Bizware.Test/Program.cs @@ -30,6 +30,7 @@ namespace BizHawk.Bizware.Test GuiRenderer gr = new GuiRenderer(igl); + TestForm tf = new TestForm(); GraphicsControl c = igl.CreateGraphicsControl(); tf.Controls.Add(c); @@ -44,6 +45,18 @@ namespace BizHawk.Bizware.Test c.SetVsync(false); + //create a render target, in the control context + c.Begin(); + RenderTarget rt = igl.CreateRenderTarget(60, 60); + rt.Bind(); + igl.ClearColor(Color.Blue); + igl.Clear(ClearBufferMask.ColorBufferBit); + gr.Begin(60, 60, true); + gr.Draw(smile); + gr.End(); + rt.Unbind(); + c.End(); + DateTime start = DateTime.Now; int wobble = 0; for (; ; ) @@ -51,14 +64,20 @@ namespace BizHawk.Bizware.Test if (c == null) break; c.Begin(); - + + igl.ClearColor(Color.Red); igl.Clear(BizwareGL.ClearBufferMask.ColorBufferBit); int frame = (int)((DateTime.Now - start).TotalSeconds) % testArts.Count; gr.Begin(c.Control.ClientSize.Width, c.Control.ClientSize.Height); - sr.RenderString(gr, 0, 0, "60 fps"); + + 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();