diff options
Diffstat (limited to 'Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs')
| -rw-r--r-- | Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs | 203 |
1 files changed, 168 insertions, 35 deletions
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs index f9c42ae0..818af3b3 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs @@ -1,16 +1,30 @@ using OpenTK; using OpenTK.Graphics.OpenGL; using System; +using System.Collections.Generic; namespace Ryujinx.Graphics.Gal.OpenGL { class OGLFrameBuffer { - private struct FrameBuffer + private class FrameBuffer { - public int FbHandle; - public int RbHandle; - public int TexHandle; + public int Width { get; set; } + public int Height { get; set; } + + public int Handle { get; private set; } + public int RbHandle { get; private set; } + public int TexHandle { get; private set; } + + public FrameBuffer(int Width, int Height) + { + this.Width = Width; + this.Height = Height; + + Handle = GL.GenFramebuffer(); + RbHandle = GL.GenRenderbuffer(); + TexHandle = GL.GenTexture(); + } } private struct ShaderProgram @@ -20,83 +34,175 @@ namespace Ryujinx.Graphics.Gal.OpenGL public int FpHandle; } - private FrameBuffer[] Fbs; + private Dictionary<long, FrameBuffer> Fbs; private ShaderProgram Shader; private bool IsInitialized; + private int RawFbTexWidth; + private int RawFbTexHeight; + private int RawFbTexHandle; + + private int CurrFbHandle; + private int CurrTexHandle; + private int VaoHandle; private int VboHandle; public OGLFrameBuffer() { - Fbs = new FrameBuffer[16]; + Fbs = new Dictionary<long, FrameBuffer>(); Shader = new ShaderProgram(); } - public void Set(int Index, int Width, int Height) + public void Create(long Tag, int Width, int Height) { - if (Fbs[Index].FbHandle != 0) + if (Fbs.TryGetValue(Tag, out FrameBuffer Fb)) { - return; - } + if (Fb.Width != Width || + Fb.Height != Height) + { + SetupTexture(Fb.TexHandle, Width, Height); - Fbs[Index].FbHandle = GL.GenFramebuffer(); - Fbs[Index].RbHandle = GL.GenRenderbuffer(); - Fbs[Index].TexHandle = GL.GenTexture(); + Fb.Width = Width; + Fb.Height = Height; + } - GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fbs[Index].FbHandle); + return; + } - GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, Fbs[Index].RbHandle); + Fb = new FrameBuffer(Width, Height); - GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.Depth24Stencil8, 1280, 720); + SetupTexture(Fb.TexHandle, Width, Height); - GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, RenderbufferTarget.Renderbuffer, Fbs[Index].RbHandle); + GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle); - GL.BindTexture(TextureTarget.Texture2D, Fbs[Index].TexHandle); + GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, Fb.RbHandle); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + GL.RenderbufferStorage( + RenderbufferTarget.Renderbuffer, + RenderbufferStorage.Depth24Stencil8, + Width, + Height); - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, 1280, 720, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero); + GL.FramebufferRenderbuffer( + FramebufferTarget.Framebuffer, + FramebufferAttachment.DepthStencilAttachment, + RenderbufferTarget.Renderbuffer, + Fb.RbHandle); - GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, Fbs[Index].TexHandle, 0); + GL.FramebufferTexture( + FramebufferTarget.Framebuffer, + FramebufferAttachment.ColorAttachment0, + Fb.TexHandle, + 0); GL.DrawBuffer(DrawBufferMode.ColorAttachment0); + + Fbs.Add(Tag, Fb); } - public void Bind(int Index) + public void Bind(long Tag) { - if (Fbs[Index].FbHandle == 0) + if (Fbs.TryGetValue(Tag, out FrameBuffer Fb)) { - return; + GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle); + + CurrFbHandle = Fb.Handle; } + } - GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fbs[Index].FbHandle); + public void BindTexture(long Tag, int Index) + { + if (Fbs.TryGetValue(Tag, out FrameBuffer Fb)) + { + GL.ActiveTexture(TextureUnit.Texture0 + Index); + + GL.BindTexture(TextureTarget.Texture2D, Fb.TexHandle); + } } - public void Draw(int Index) + public void Set(long Tag) { - if (Fbs[Index].FbHandle == 0) + if (Fbs.TryGetValue(Tag, out FrameBuffer Fb)) { - return; + CurrTexHandle = Fb.TexHandle; } + } - EnsureInitialized(); + public void Set(byte[] Data, int Width, int Height) + { + if (RawFbTexHandle == 0) + { + RawFbTexHandle = GL.GenTexture(); + } - GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); + if (RawFbTexWidth != Width || + RawFbTexHeight != Height) + { + SetupTexture(RawFbTexHandle, Width, Height); - GL.BindTexture(TextureTarget.Texture2D, Fbs[Index].TexHandle); + RawFbTexWidth = Width; + RawFbTexHeight = Height; + } GL.ActiveTexture(TextureUnit.Texture0); - GL.BindVertexArray(VaoHandle); + GL.BindTexture(TextureTarget.Texture2D, RawFbTexHandle); + + (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8); + + GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, Format, Type, Data); + + CurrTexHandle = RawFbTexHandle; + } + + public void SetTransform(Matrix2 Transform, Vector2 Offs) + { + EnsureInitialized(); + + int CurrentProgram = GL.GetInteger(GetPName.CurrentProgram); GL.UseProgram(Shader.Handle); - GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4); + int TransformUniformLocation = GL.GetUniformLocation(Shader.Handle, "transform"); + + GL.UniformMatrix2(TransformUniformLocation, false, ref Transform); + + int OffsetUniformLocation = GL.GetUniformLocation(Shader.Handle, "offset"); + + GL.Uniform2(OffsetUniformLocation, ref Offs); + + GL.UseProgram(CurrentProgram); + } + + public void Render() + { + if (CurrTexHandle != 0) + { + EnsureInitialized(); + + GL.ActiveTexture(TextureUnit.Texture0); + + GL.BindTexture(TextureTarget.Texture2D, CurrTexHandle); + + int CurrentProgram = GL.GetInteger(GetPName.CurrentProgram); + + GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); + + GL.BindVertexArray(VaoHandle); + + GL.UseProgram(Shader.Handle); + + GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4); + + //Restore the original state. + GL.BindFramebuffer(FramebufferTarget.Framebuffer, CurrFbHandle); + + GL.UseProgram(CurrentProgram); + } } private void EnsureInitialized() @@ -130,7 +236,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.LinkProgram(Shader.Handle); GL.UseProgram(Shader.Handle); - Matrix2 Transform = Matrix2.CreateScale(1, -1); + Matrix2 Transform = Matrix2.Identity; int TexUniformLocation = GL.GetUniformLocation(Shader.Handle, "tex"); @@ -178,5 +284,32 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 16, 8); } + + private void SetupTexture(int Handle, int Width, int Height) + { + GL.BindTexture(TextureTarget.Texture2D, Handle); + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + + (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8); + + const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba; + + const int Level = 0; + const int Border = 0; + + GL.TexImage2D( + TextureTarget.Texture2D, + Level, + InternalFmt, + Width, + Height, + Border, + Format, + Type, + IntPtr.Zero); + } } }
\ No newline at end of file |
