aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs')
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs282
1 files changed, 282 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs
new file mode 100644
index 00000000..7429569b
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs
@@ -0,0 +1,282 @@
+using OpenTK.Graphics.OpenGL;
+using System;
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics.Gal.OpenGL
+{
+ public class OpenGLRenderer : IGalRenderer
+ {
+ private struct VertexBuffer
+ {
+ public int VaoHandle;
+ public int VboHandle;
+
+ public int PrimCount;
+ }
+
+ private struct Texture
+ {
+ public int Handle;
+ }
+
+ private List<VertexBuffer> VertexBuffers;
+
+ private Texture[] Textures;
+
+ private Queue<Action> ActionsQueue;
+
+ public long FrameBufferPtr { get; set; }
+
+ public OpenGLRenderer()
+ {
+ VertexBuffers = new List<VertexBuffer>();
+
+ Textures = new Texture[8];
+
+ ActionsQueue = new Queue<Action>();
+ }
+
+ public void QueueAction(Action ActionMthd)
+ {
+ ActionsQueue.Enqueue(ActionMthd);
+ }
+
+ public void RunActions()
+ {
+ while (ActionsQueue.Count > 0)
+ {
+ ActionsQueue.Dequeue()();
+ }
+ }
+
+ public void Render()
+ {
+ for (int Index = 0; Index < VertexBuffers.Count; Index++)
+ {
+ VertexBuffer Vb = VertexBuffers[Index];
+
+ if (Vb.VaoHandle != 0 &&
+ Vb.PrimCount != 0)
+ {
+ GL.BindVertexArray(Vb.VaoHandle);
+ GL.DrawArrays(PrimitiveType.TriangleStrip, 0, Vb.PrimCount);
+ }
+ }
+
+ }
+
+ public void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs)
+ {
+ if (Index < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(Index));
+ }
+
+ if (Buffer.Length == 0 || Stride == 0)
+ {
+ return;
+ }
+
+ EnsureVbInitialized(Index);
+
+ VertexBuffer Vb = VertexBuffers[Index];
+
+ Vb.PrimCount = Buffer.Length / Stride;
+
+ VertexBuffers[Index] = Vb;
+
+ IntPtr Length = new IntPtr(Buffer.Length);
+
+ GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle);
+ GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
+ GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
+
+ GL.BindVertexArray(Vb.VaoHandle);
+
+ for (int Attr = 0; Attr < 16; Attr++)
+ {
+ GL.DisableVertexAttribArray(Attr);
+ }
+
+ foreach (GalVertexAttrib Attrib in Attribs)
+ {
+ if (Attrib.Index >= 3) break;
+
+ GL.EnableVertexAttribArray(Attrib.Index);
+
+ GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle);
+
+ int Size = 0;
+
+ switch (Attrib.Size)
+ {
+ case GalVertexAttribSize._8:
+ case GalVertexAttribSize._16:
+ case GalVertexAttribSize._32:
+ Size = 1;
+ break;
+ case GalVertexAttribSize._8_8:
+ case GalVertexAttribSize._16_16:
+ case GalVertexAttribSize._32_32:
+ Size = 2;
+ break;
+ case GalVertexAttribSize._8_8_8:
+ case GalVertexAttribSize._11_11_10:
+ case GalVertexAttribSize._16_16_16:
+ case GalVertexAttribSize._32_32_32:
+ Size = 3;
+ break;
+ case GalVertexAttribSize._8_8_8_8:
+ case GalVertexAttribSize._10_10_10_2:
+ case GalVertexAttribSize._16_16_16_16:
+ case GalVertexAttribSize._32_32_32_32:
+ Size = 4;
+ break;
+ }
+
+ bool Signed =
+ Attrib.Type == GalVertexAttribType.Snorm ||
+ Attrib.Type == GalVertexAttribType.Sint ||
+ Attrib.Type == GalVertexAttribType.Sscaled;
+
+ bool Normalize =
+ Attrib.Type == GalVertexAttribType.Snorm ||
+ Attrib.Type == GalVertexAttribType.Unorm;
+
+ VertexAttribPointerType Type = 0;
+
+ switch (Attrib.Type)
+ {
+ case GalVertexAttribType.Snorm:
+ case GalVertexAttribType.Unorm:
+ case GalVertexAttribType.Sint:
+ case GalVertexAttribType.Uint:
+ case GalVertexAttribType.Uscaled:
+ case GalVertexAttribType.Sscaled:
+ {
+ switch (Attrib.Size)
+ {
+ case GalVertexAttribSize._8:
+ case GalVertexAttribSize._8_8:
+ case GalVertexAttribSize._8_8_8:
+ case GalVertexAttribSize._8_8_8_8:
+ {
+ Type = Signed
+ ? VertexAttribPointerType.Byte
+ : VertexAttribPointerType.UnsignedByte;
+
+ break;
+ }
+
+ case GalVertexAttribSize._16:
+ case GalVertexAttribSize._16_16:
+ case GalVertexAttribSize._16_16_16:
+ case GalVertexAttribSize._16_16_16_16:
+ {
+ Type = Signed
+ ? VertexAttribPointerType.Short
+ : VertexAttribPointerType.UnsignedShort;
+
+ break;
+ }
+
+ case GalVertexAttribSize._10_10_10_2:
+ case GalVertexAttribSize._11_11_10:
+ case GalVertexAttribSize._32:
+ case GalVertexAttribSize._32_32:
+ case GalVertexAttribSize._32_32_32:
+ case GalVertexAttribSize._32_32_32_32:
+ {
+ Type = Signed
+ ? VertexAttribPointerType.Int
+ : VertexAttribPointerType.UnsignedInt;
+
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case GalVertexAttribType.Float:
+ {
+ Type = VertexAttribPointerType.Float;
+
+ break;
+ }
+ }
+
+ GL.VertexAttribPointer(
+ Attrib.Index,
+ Size,
+ Type,
+ Normalize,
+ Stride,
+ Attrib.Offset);
+ }
+
+ GL.BindVertexArray(0);
+ }
+
+ public void SendR8G8B8A8Texture(int Index, byte[] Buffer, int Width, int Height)
+ {
+ EnsureTexInitialized(Index);
+
+ GL.BindTexture(TextureTarget.Texture2D, Textures[Index].Handle);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
+ GL.TexImage2D(TextureTarget.Texture2D,
+ 0,
+ PixelInternalFormat.Rgba,
+ Width,
+ Height,
+ 0,
+ PixelFormat.Rgba,
+ PixelType.UnsignedByte,
+ Buffer);
+ }
+
+ public void BindTexture(int Index)
+ {
+ GL.ActiveTexture(TextureUnit.Texture0 + Index);
+
+ GL.BindTexture(TextureTarget.Texture2D, Textures[Index].Handle);
+ }
+
+ private void EnsureVbInitialized(int VbIndex)
+ {
+ while (VbIndex >= VertexBuffers.Count)
+ {
+ VertexBuffers.Add(new VertexBuffer());
+ }
+
+ VertexBuffer Vb = VertexBuffers[VbIndex];
+
+ if (Vb.VaoHandle == 0)
+ {
+ Vb.VaoHandle = GL.GenVertexArray();
+ }
+
+ if (Vb.VboHandle == 0)
+ {
+ Vb.VboHandle = GL.GenBuffer();
+ }
+
+ VertexBuffers[VbIndex] = Vb;
+ }
+
+ private void EnsureTexInitialized(int TexIndex)
+ {
+ Texture Tex = Textures[TexIndex];
+
+ if (Tex.Handle == 0)
+ {
+ Tex.Handle = GL.GenTexture();
+ }
+
+ Textures[TexIndex] = Tex;
+ }
+ }
+} \ No newline at end of file