2018-02-23 16:48:27 -05:00
|
|
|
using OpenTK;
|
2018-02-04 18:08:20 -05:00
|
|
|
using System;
|
2018-02-28 21:37:40 -05:00
|
|
|
using System.Collections.Concurrent;
|
2018-02-04 18:08:20 -05:00
|
|
|
using System.Collections.Generic;
|
|
|
|
|
2018-02-20 15:09:23 -05:00
|
|
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
|
|
|
public class OpenGLRenderer : IGalRenderer
|
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
private OGLBlend Blend;
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
private OGLFrameBuffer FrameBuffer;
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
private OGLRasterizer Rasterizer;
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
private OGLShader Shader;
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
private OGLTexture Texture;
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-02-28 21:37:40 -05:00
|
|
|
private ConcurrentQueue<Action> ActionsQueue;
|
2018-02-04 18:08:20 -05:00
|
|
|
|
|
|
|
public OpenGLRenderer()
|
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
Blend = new OGLBlend();
|
|
|
|
|
|
|
|
FrameBuffer = new OGLFrameBuffer();
|
|
|
|
|
|
|
|
Rasterizer = new OGLRasterizer();
|
|
|
|
|
|
|
|
Shader = new OGLShader();
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
Texture = new OGLTexture();
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-02-28 21:37:40 -05:00
|
|
|
ActionsQueue = new ConcurrentQueue<Action>();
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public void QueueAction(Action ActionMthd)
|
|
|
|
{
|
|
|
|
ActionsQueue.Enqueue(ActionMthd);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void RunActions()
|
|
|
|
{
|
2018-02-23 16:48:27 -05:00
|
|
|
int Count = ActionsQueue.Count;
|
|
|
|
|
2018-02-28 21:37:40 -05:00
|
|
|
while (Count-- > 0 && ActionsQueue.TryDequeue(out Action RenderAction))
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-02-28 21:37:40 -05:00
|
|
|
RenderAction();
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
2018-02-23 19:59:38 -05:00
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
|
|
|
public void Render()
|
|
|
|
{
|
2018-04-13 14:12:58 -04:00
|
|
|
FrameBuffer.Render();
|
2018-02-23 16:48:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public void SetWindowSize(int Width, int Height)
|
|
|
|
{
|
2018-04-14 00:14:42 -04:00
|
|
|
FrameBuffer.SetWindowSize(Width, Height);
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public void SetBlendEnable(bool Enable)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
if (Enable)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
ActionsQueue.Enqueue(() => Blend.Enable());
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
2018-04-08 15:17:35 -04:00
|
|
|
else
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
ActionsQueue.Enqueue(() => Blend.Disable());
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
2018-04-08 15:17:35 -04:00
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public void SetBlend(
|
|
|
|
GalBlendEquation Equation,
|
|
|
|
GalBlendFactor FuncSrc,
|
|
|
|
GalBlendFactor FuncDst)
|
|
|
|
{
|
|
|
|
ActionsQueue.Enqueue(() => Blend.Set(Equation, FuncSrc, FuncDst));
|
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04: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-04 18:08:20 -05:00
|
|
|
|
2018-04-13 14:12:58 -04:00
|
|
|
public void CreateFrameBuffer(long Tag, int Width, int Height)
|
2018-04-08 15:17:35 -04:00
|
|
|
{
|
2018-04-13 14:12:58 -04:00
|
|
|
ActionsQueue.Enqueue(() => FrameBuffer.Create(Tag, Width, Height));
|
2018-04-08 15:17:35 -04:00
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-13 14:12:58 -04:00
|
|
|
public void BindFrameBuffer(long Tag)
|
2018-04-08 15:17:35 -04:00
|
|
|
{
|
2018-04-13 14:12:58 -04:00
|
|
|
ActionsQueue.Enqueue(() => FrameBuffer.Bind(Tag));
|
2018-04-08 15:17:35 -04:00
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-13 14:12:58 -04:00
|
|
|
public void BindFrameBufferTexture(long Tag, int Index, GalTextureSampler Sampler)
|
2018-04-08 15:17:35 -04:00
|
|
|
{
|
2018-04-13 14:12:58 -04:00
|
|
|
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-04-08 15:17:35 -04:00
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-13 23:39:24 -04:00
|
|
|
public void SetViewport(int X, int Y, int Width, int Height)
|
|
|
|
{
|
|
|
|
ActionsQueue.Enqueue(() => FrameBuffer.SetViewport(X, Y, Width, Height));
|
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public void ClearBuffers(int RtIndex, GalClearBufferFlags Flags)
|
|
|
|
{
|
|
|
|
ActionsQueue.Enqueue(() => Rasterizer.ClearBuffers(RtIndex, Flags));
|
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public void SetVertexArray(int VbIndex, int Stride, byte[] Buffer, GalVertexAttrib[] Attribs)
|
|
|
|
{
|
|
|
|
if ((uint)VbIndex > 31)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
throw new ArgumentOutOfRangeException(nameof(VbIndex));
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
ActionsQueue.Enqueue(() => Rasterizer.SetVertexArray(VbIndex, Stride,
|
|
|
|
Buffer ?? throw new ArgumentNullException(nameof(Buffer)),
|
|
|
|
Attribs ?? throw new ArgumentNullException(nameof(Attribs))));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SetIndexArray(byte[] Buffer, GalIndexFormat Format)
|
|
|
|
{
|
|
|
|
if (Buffer == null)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
throw new ArgumentNullException(nameof(Buffer));
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
ActionsQueue.Enqueue(() => Rasterizer.SetIndexArray(Buffer, Format));
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public void DrawArrays(int VbIndex, GalPrimitiveType PrimType)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
if ((uint)VbIndex > 31)
|
|
|
|
{
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(VbIndex));
|
|
|
|
}
|
|
|
|
|
|
|
|
ActionsQueue.Enqueue(() => Rasterizer.DrawArrays(VbIndex, PrimType));
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
if ((uint)VbIndex > 31)
|
|
|
|
{
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(VbIndex));
|
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
ActionsQueue.Enqueue(() => Rasterizer.DrawElements(VbIndex, First, PrimType));
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public void CreateShader(long Tag, GalShaderType Type, byte[] Data)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
if (Data == null)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
throw new ArgumentNullException(nameof(Data));
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
Shader.Create(Tag, Type, Data);
|
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public void SetConstBuffer(long Tag, int Cbuf, byte[] Data)
|
|
|
|
{
|
|
|
|
if (Data == null)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
throw new ArgumentNullException(nameof(Data));
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
ActionsQueue.Enqueue(() => Shader.SetConstBuffer(Tag, Cbuf, Data));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SetUniform1(string UniformName, int Value)
|
|
|
|
{
|
|
|
|
if (UniformName == null)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
throw new ArgumentNullException(nameof(UniformName));
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
ActionsQueue.Enqueue(() => Shader.SetUniform1(UniformName, Value));
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
|
2018-04-13 23:39:24 -04: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));
|
|
|
|
}
|
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public IEnumerable<ShaderDeclInfo> GetTextureUsage(long Tag)
|
2018-02-04 18:08:20 -05:00
|
|
|
{
|
2018-04-08 15:17:35 -04:00
|
|
|
return Shader.GetTextureUsage(Tag);
|
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public void BindShader(long Tag)
|
|
|
|
{
|
|
|
|
ActionsQueue.Enqueue(() => Shader.Bind(Tag));
|
|
|
|
}
|
2018-02-04 18:08:20 -05:00
|
|
|
|
2018-04-08 15:17:35 -04:00
|
|
|
public void BindProgram()
|
|
|
|
{
|
|
|
|
ActionsQueue.Enqueue(() => Shader.BindProgram());
|
|
|
|
}
|
|
|
|
|
2018-04-13 14:12:58 -04:00
|
|
|
public void SetTextureAndSampler(int Index, GalTexture Texture, GalTextureSampler Sampler)
|
2018-04-08 15:17:35 -04:00
|
|
|
{
|
2018-04-13 14:12:58 -04:00
|
|
|
ActionsQueue.Enqueue(() =>
|
|
|
|
{
|
|
|
|
this.Texture.Set(Index, Texture);
|
|
|
|
|
|
|
|
OGLTexture.Set(Sampler);
|
|
|
|
});
|
2018-04-08 15:17:35 -04:00
|
|
|
}
|
|
|
|
|
2018-04-13 14:12:58 -04:00
|
|
|
public void BindTexture(int Index)
|
2018-04-08 15:17:35 -04:00
|
|
|
{
|
2018-04-13 14:12:58 -04:00
|
|
|
ActionsQueue.Enqueue(() => Texture.Bind(Index));
|
2018-02-04 18:08:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|