Ryujinx/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs

292 lines
8.1 KiB
C#
Raw Normal View History

using OpenTK;
2018-02-05 00:08:20 +01:00
using System;
using System.Collections.Concurrent;
2018-02-05 00:08:20 +01:00
using System.Collections.Generic;
namespace Ryujinx.Graphics.Gal.OpenGL
2018-02-05 00:08:20 +01:00
{
public class OpenGLRenderer : IGalRenderer
{
private OGLBlend Blend;
2018-02-05 00:08:20 +01:00
private OGLFrameBuffer FrameBuffer;
2018-02-05 00:08:20 +01:00
private OGLRasterizer Rasterizer;
2018-02-05 00:08:20 +01:00
private OGLShader Shader;
2018-02-05 00:08:20 +01:00
private OGLTexture Texture;
2018-02-05 00:08:20 +01:00
private ConcurrentQueue<Action> ActionsQueue;
2018-02-05 00:08:20 +01:00
public OpenGLRenderer()
{
Blend = new OGLBlend();
FrameBuffer = new OGLFrameBuffer();
Rasterizer = new OGLRasterizer();
Shader = new OGLShader();
2018-02-05 00:08:20 +01:00
Texture = new OGLTexture();
2018-02-05 00:08:20 +01:00
ActionsQueue = new ConcurrentQueue<Action>();
2018-02-05 00:08:20 +01:00
}
public void Initialize(bool TrySPIRV = false)
{
ActionsQueue.Enqueue(() =>
{
Shader.Prepare(TrySPIRV);
});
}
2018-02-05 00:08:20 +01:00
public void QueueAction(Action ActionMthd)
{
ActionsQueue.Enqueue(ActionMthd);
}
public void RunActions()
{
int Count = ActionsQueue.Count;
while (Count-- > 0 && ActionsQueue.TryDequeue(out Action RenderAction))
2018-02-05 00:08:20 +01:00
{
RenderAction();
2018-02-05 00:08:20 +01:00
}
}
2018-02-05 00:08:20 +01:00
public void Render()
{
FrameBuffer.Render();
}
public void SetWindowSize(int Width, int Height)
{
FrameBuffer.SetWindowSize(Width, Height);
2018-02-05 00:08:20 +01:00
}
public void SetBlendEnable(bool Enable)
2018-02-05 00:08:20 +01:00
{
if (Enable)
2018-02-05 00:08:20 +01:00
{
ActionsQueue.Enqueue(() => Blend.Enable());
2018-02-05 00:08:20 +01:00
}
else
2018-02-05 00:08:20 +01:00
{
ActionsQueue.Enqueue(() => Blend.Disable());
2018-02-05 00:08:20 +01:00
}
}
2018-02-05 00:08:20 +01:00
public void SetBlend(
GalBlendEquation Equation,
GalBlendFactor FuncSrc,
GalBlendFactor FuncDst)
{
ActionsQueue.Enqueue(() => Blend.Set(Equation, FuncSrc, FuncDst));
}
2018-02-05 00:08:20 +01:00
public void SetBlendSeparate(
GalBlendEquation EquationRgb,
GalBlendEquation EquationAlpha,
GalBlendFactor FuncSrcRgb,
GalBlendFactor FuncDstRgb,
GalBlendFactor FuncSrcAlpha,
GalBlendFactor FuncDstAlpha)
{
ActionsQueue.Enqueue(() =>
{
Blend.SetSeparate(
EquationRgb,
EquationAlpha,
FuncSrcRgb,
FuncDstRgb,
FuncSrcAlpha,
FuncDstAlpha);
});
}
2018-02-05 00:08:20 +01:00
public void CreateFrameBuffer(long Tag, int Width, int Height)
{
ActionsQueue.Enqueue(() => FrameBuffer.Create(Tag, Width, Height));
}
2018-02-05 00:08:20 +01:00
public void BindFrameBuffer(long Tag)
{
ActionsQueue.Enqueue(() => FrameBuffer.Bind(Tag));
}
2018-02-05 00:08:20 +01:00
public void BindFrameBufferTexture(long Tag, int Index, GalTextureSampler Sampler)
{
ActionsQueue.Enqueue(() =>
{
FrameBuffer.BindTexture(Tag, Index);
OGLTexture.Set(Sampler);
});
}
public void SetFrameBuffer(long Tag)
{
ActionsQueue.Enqueue(() => FrameBuffer.Set(Tag));
}
public void SetFrameBuffer(byte[] Data, int Width, int Height)
{
ActionsQueue.Enqueue(() => FrameBuffer.Set(Data, Width, Height));
}
public void SetFrameBufferTransform(float SX, float SY, float Rotate, float TX, float TY)
{
Matrix2 Transform;
Transform = Matrix2.CreateScale(SX, SY);
Transform *= Matrix2.CreateRotation(Rotate);
Vector2 Offs = new Vector2(TX, TY);
ActionsQueue.Enqueue(() => FrameBuffer.SetTransform(Transform, Offs));
}
2018-02-05 00:08:20 +01:00
public void SetViewport(int X, int Y, int Width, int Height)
{
ActionsQueue.Enqueue(() => FrameBuffer.SetViewport(X, Y, Width, Height));
}
public void GetFrameBufferData(long Tag, Action<byte[]> Callback)
{
ActionsQueue.Enqueue(() => FrameBuffer.GetBufferData(Tag, Callback));
}
public void ClearBuffers(int RtIndex, GalClearBufferFlags Flags)
{
ActionsQueue.Enqueue(() => Rasterizer.ClearBuffers(RtIndex, Flags));
}
2018-02-05 00:08:20 +01:00
public bool IsVboCached(long Tag, long DataSize)
{
return Rasterizer.IsVboCached(Tag, DataSize);
}
2018-02-05 00:08:20 +01:00
public bool IsIboCached(long Tag, long DataSize)
{
return Rasterizer.IsIboCached(Tag, DataSize);
}
public void CreateVbo(long Tag, byte[] Buffer)
{
ActionsQueue.Enqueue(() => Rasterizer.CreateVbo(Tag, Buffer));
}
2018-02-05 00:08:20 +01:00
public void CreateIbo(long Tag, byte[] Buffer)
{
ActionsQueue.Enqueue(() => Rasterizer.CreateIbo(Tag, Buffer));
2018-02-05 00:08:20 +01:00
}
public void SetVertexArray(int VbIndex, int Stride, long VboTag, GalVertexAttrib[] Attribs)
2018-02-05 00:08:20 +01:00
{
if ((uint)VbIndex > 31)
{
throw new ArgumentOutOfRangeException(nameof(VbIndex));
}
if (Attribs == null)
{
throw new ArgumentNullException(nameof(Attribs));
}
ActionsQueue.Enqueue(() => Rasterizer.SetVertexArray(VbIndex, Stride, VboTag, Attribs));
2018-02-05 00:08:20 +01:00
}
public void SetIndexArray(long Tag, int Size, GalIndexFormat Format)
2018-02-05 00:08:20 +01:00
{
ActionsQueue.Enqueue(() => Rasterizer.SetIndexArray(Tag, Size, Format));
}
public void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType)
{
ActionsQueue.Enqueue(() => Rasterizer.DrawArrays(First, PrimCount, PrimType));
}
2018-02-05 00:08:20 +01:00
public void DrawElements(long IboTag, int First, GalPrimitiveType PrimType)
{
ActionsQueue.Enqueue(() => Rasterizer.DrawElements(IboTag, First, PrimType));
2018-02-05 00:08:20 +01:00
}
public void CreateShader(IGalMemory Memory, long Tag, GalShaderType Type)
2018-02-05 00:08:20 +01:00
{
if (Memory == null)
2018-02-05 00:08:20 +01:00
{
throw new ArgumentNullException(nameof(Memory));
2018-02-05 00:08:20 +01:00
}
Shader.Create(Memory, Tag, Type);
}
2018-02-05 00:08:20 +01:00
public void SetConstBuffer(long Tag, int Cbuf, byte[] Data)
{
if (Data == null)
2018-02-05 00:08:20 +01:00
{
throw new ArgumentNullException(nameof(Data));
2018-02-05 00:08:20 +01:00
}
ActionsQueue.Enqueue(() => Shader.SetConstBuffer(Tag, Cbuf, Data));
}
public void SetUniform1(string UniformName, int Value)
{
if (UniformName == null)
2018-02-05 00:08:20 +01:00
{
throw new ArgumentNullException(nameof(UniformName));
2018-02-05 00:08:20 +01:00
}
ActionsQueue.Enqueue(() => Shader.SetUniform1(UniformName, Value));
2018-02-05 00:08:20 +01:00
}
public void SetUniform2F(string UniformName, float X, float Y)
{
if (UniformName == null)
{
throw new ArgumentNullException(nameof(UniformName));
}
ActionsQueue.Enqueue(() => Shader.SetUniform2F(UniformName, X, Y));
}
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long Tag)
2018-02-05 00:08:20 +01:00
{
return Shader.GetTextureUsage(Tag);
}
2018-02-05 00:08:20 +01:00
public void BindShader(long Tag)
{
ActionsQueue.Enqueue(() => Shader.Bind(Tag));
}
2018-02-05 00:08:20 +01:00
public void BindProgram()
{
ActionsQueue.Enqueue(() => Shader.BindProgram());
}
public void SetTextureAndSampler(long Tag, byte[] Data, GalTexture Texture, GalTextureSampler Sampler)
{
ActionsQueue.Enqueue(() =>
{
this.Texture.Create(Tag, Data, Texture);
OGLTexture.Set(Sampler);
});
}
public bool TryGetCachedTexture(long Tag, long DataSize, out GalTexture Texture)
{
return this.Texture.TryGetCachedTexture(Tag, DataSize, out Texture);
}
public void BindTexture(long Tag, int Index)
{
ActionsQueue.Enqueue(() => Texture.Bind(Tag, Index));
2018-02-05 00:08:20 +01:00
}
}
}