Somewhat better NvFlinger (I guess) (fixes #30)
This commit is contained in:
parent
eafc58c9f2
commit
2ed733b1d5
14 changed files with 820 additions and 444 deletions
20
Ryujinx.Graphics/Gal/EmbeddedResource.cs
Normal file
20
Ryujinx.Graphics/Gal/EmbeddedResource.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal
|
||||
{
|
||||
static class EmbeddedResource
|
||||
{
|
||||
public static string GetString(string Name)
|
||||
{
|
||||
Assembly Asm = typeof(EmbeddedResource).Assembly;
|
||||
|
||||
using (Stream ResStream = Asm.GetManifestResourceStream(Name))
|
||||
{
|
||||
StreamReader Reader = new StreamReader(ResStream);
|
||||
|
||||
return Reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,14 +2,15 @@ using System;
|
|||
|
||||
namespace Ryujinx.Graphics.Gal
|
||||
{
|
||||
public interface IGalRenderer
|
||||
public unsafe interface IGalRenderer
|
||||
{
|
||||
long FrameBufferPtr { get; set; }
|
||||
|
||||
void QueueAction(Action ActionMthd);
|
||||
void RunActions();
|
||||
|
||||
void InitializeFrameBuffer();
|
||||
void Render();
|
||||
void SetWindowSize(int Width, int Height);
|
||||
void SetFrameBuffer(byte* Fb, int Width, int Height, float SX, float SY, float R);
|
||||
void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs);
|
||||
void SendR8G8B8A8Texture(int Index, byte[] Buffer, int Width, int Height);
|
||||
void BindTexture(int Index);
|
||||
|
|
13
Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl
Normal file
13
Ryujinx.Graphics/Gal/OpenGL/FbFragShader.glsl
Normal file
|
@ -0,0 +1,13 @@
|
|||
#version 330 core
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
in vec2 tex_coord;
|
||||
|
||||
out vec4 out_frag_color;
|
||||
|
||||
void main(void) {
|
||||
out_frag_color = texture(tex, tex_coord);
|
||||
}
|
26
Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl
Normal file
26
Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl
Normal file
|
@ -0,0 +1,26 @@
|
|||
#version 330 core
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform vec2 window_size;
|
||||
uniform mat2 transform;
|
||||
|
||||
layout(location = 0) in vec2 in_position;
|
||||
layout(location = 1) in vec2 in_tex_coord;
|
||||
|
||||
out vec2 tex_coord;
|
||||
|
||||
// Have a fixed aspect ratio, fit the image within the available space.
|
||||
vec2 get_scale_ratio(void) {
|
||||
vec2 native_size = vec2(1280, 720);
|
||||
vec2 ratio = vec2(
|
||||
(window_size.y * native_size.x) / (native_size.y * window_size.x),
|
||||
(window_size.x * native_size.y) / (native_size.x * window_size.y)
|
||||
);
|
||||
return min(ratio, 1);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
tex_coord = in_tex_coord;
|
||||
gl_Position = vec4((transform * in_position) * get_scale_ratio(), 0, 1);
|
||||
}
|
228
Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs
Normal file
228
Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs
Normal file
|
@ -0,0 +1,228 @@
|
|||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
unsafe class FrameBuffer
|
||||
{
|
||||
public int WindowWidth { get; set; }
|
||||
public int WindowHeight { get; set; }
|
||||
|
||||
private int VtxShaderHandle;
|
||||
private int FragShaderHandle;
|
||||
private int PrgShaderHandle;
|
||||
|
||||
private int TexHandle;
|
||||
private int TexWidth;
|
||||
private int TexHeight;
|
||||
|
||||
private int VaoHandle;
|
||||
private int VboHandle;
|
||||
|
||||
private int[] Pixels;
|
||||
|
||||
private byte* FbPtr;
|
||||
|
||||
public FrameBuffer(int Width, int Height)
|
||||
{
|
||||
if (Width < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Width));
|
||||
}
|
||||
|
||||
if (Height < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Height));
|
||||
}
|
||||
|
||||
TexWidth = Width;
|
||||
TexHeight = Height;
|
||||
|
||||
WindowWidth = Width;
|
||||
WindowHeight = Height;
|
||||
|
||||
SetupShaders();
|
||||
SetupTexture();
|
||||
SetupVertex();
|
||||
}
|
||||
|
||||
private void SetupShaders()
|
||||
{
|
||||
VtxShaderHandle = GL.CreateShader(ShaderType.VertexShader);
|
||||
FragShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
|
||||
|
||||
string VtxShaderSource = EmbeddedResource.GetString("GlFbVtxShader");
|
||||
string FragShaderSource = EmbeddedResource.GetString("GlFbFragShader");
|
||||
|
||||
GL.ShaderSource(VtxShaderHandle, VtxShaderSource);
|
||||
GL.ShaderSource(FragShaderHandle, FragShaderSource);
|
||||
GL.CompileShader(VtxShaderHandle);
|
||||
GL.CompileShader(FragShaderHandle);
|
||||
|
||||
PrgShaderHandle = GL.CreateProgram();
|
||||
|
||||
GL.AttachShader(PrgShaderHandle, VtxShaderHandle);
|
||||
GL.AttachShader(PrgShaderHandle, FragShaderHandle);
|
||||
GL.LinkProgram(PrgShaderHandle);
|
||||
GL.UseProgram(PrgShaderHandle);
|
||||
|
||||
int TexUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "tex");
|
||||
|
||||
GL.Uniform1(TexUniformLocation, 0);
|
||||
|
||||
int WindowSizeUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "window_size");
|
||||
|
||||
GL.Uniform2(WindowSizeUniformLocation, new Vector2(1280.0f, 720.0f));
|
||||
}
|
||||
|
||||
private void SetupTexture()
|
||||
{
|
||||
Pixels = new int[TexWidth * TexHeight];
|
||||
|
||||
if (TexHandle == 0)
|
||||
{
|
||||
TexHandle = GL.GenTexture();
|
||||
}
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, TexHandle);
|
||||
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,
|
||||
TexWidth,
|
||||
TexHeight,
|
||||
0,
|
||||
PixelFormat.Rgba,
|
||||
PixelType.UnsignedByte,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
|
||||
private void SetupVertex()
|
||||
{
|
||||
VaoHandle = GL.GenVertexArray();
|
||||
VboHandle = GL.GenBuffer();
|
||||
|
||||
float[] Buffer = new float[]
|
||||
{
|
||||
-1, 1, 0, 0,
|
||||
1, 1, 1, 0,
|
||||
-1, -1, 0, 1,
|
||||
1, -1, 1, 1
|
||||
};
|
||||
|
||||
IntPtr Length = new IntPtr(Buffer.Length * 4);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
||||
GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||
|
||||
GL.BindVertexArray(VaoHandle);
|
||||
|
||||
GL.EnableVertexAttribArray(0);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
||||
|
||||
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 16, 0);
|
||||
|
||||
GL.EnableVertexAttribArray(1);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
||||
|
||||
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 16, 8);
|
||||
|
||||
GL.BindVertexArray(0);
|
||||
}
|
||||
|
||||
public unsafe void Set(byte* Fb, int Width, int Height, Matrix2 Transform)
|
||||
{
|
||||
if (Fb == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Fb));
|
||||
}
|
||||
|
||||
if (Width < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Width));
|
||||
}
|
||||
|
||||
if (Height < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Height));
|
||||
}
|
||||
|
||||
FbPtr = Fb;
|
||||
|
||||
if (Width != TexWidth ||
|
||||
Height != TexHeight)
|
||||
{
|
||||
TexWidth = Width;
|
||||
TexHeight = Height;
|
||||
|
||||
SetupTexture();
|
||||
}
|
||||
|
||||
GL.UseProgram(PrgShaderHandle);
|
||||
|
||||
int TransformUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "transform");
|
||||
|
||||
GL.UniformMatrix2(TransformUniformLocation, false, ref Transform);
|
||||
|
||||
int WindowSizeUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "window_size");
|
||||
|
||||
GL.Uniform2(WindowSizeUniformLocation, new Vector2(WindowWidth, WindowHeight));
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
if (FbPtr == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int Y = 0; Y < TexHeight; Y++)
|
||||
for (int X = 0; X < TexWidth; X++)
|
||||
{
|
||||
Pixels[X + Y * TexWidth] = *((int*)(FbPtr + GetSwizzleOffset(X, Y)));
|
||||
}
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, TexHandle);
|
||||
GL.TexSubImage2D(TextureTarget.Texture2D,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
TexWidth,
|
||||
TexHeight,
|
||||
PixelFormat.Rgba,
|
||||
PixelType.UnsignedByte,
|
||||
Pixels);
|
||||
|
||||
GL.ActiveTexture(TextureUnit.Texture0);
|
||||
|
||||
GL.BindVertexArray(VaoHandle);
|
||||
|
||||
GL.UseProgram(PrgShaderHandle);
|
||||
|
||||
GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
|
||||
}
|
||||
|
||||
private int GetSwizzleOffset(int X, int Y)
|
||||
{
|
||||
int Pos;
|
||||
|
||||
Pos = (Y & 0x7f) >> 4;
|
||||
Pos += (X >> 4) << 3;
|
||||
Pos += (Y >> 7) * ((TexWidth >> 4) << 3);
|
||||
Pos *= 1024;
|
||||
Pos += ((Y & 0xf) >> 3) << 9;
|
||||
Pos += ((X & 0xf) >> 3) << 8;
|
||||
Pos += ((Y & 0x7) >> 1) << 6;
|
||||
Pos += ((X & 0x7) >> 2) << 5;
|
||||
Pos += ((Y & 0x1) >> 0) << 4;
|
||||
Pos += ((X & 0x3) >> 0) << 2;
|
||||
|
||||
return Pos;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||
{
|
||||
public class OpenGLRenderer : IGalRenderer
|
||||
|
@ -25,6 +27,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
private Queue<Action> ActionsQueue;
|
||||
|
||||
private FrameBuffer FbRenderer;
|
||||
|
||||
public long FrameBufferPtr { get; set; }
|
||||
|
||||
public OpenGLRenderer()
|
||||
|
@ -36,6 +40,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
ActionsQueue = new Queue<Action>();
|
||||
}
|
||||
|
||||
public void InitializeFrameBuffer()
|
||||
{
|
||||
FbRenderer = new FrameBuffer(1280, 720);
|
||||
}
|
||||
|
||||
public void QueueAction(Action ActionMthd)
|
||||
{
|
||||
ActionsQueue.Enqueue(ActionMthd);
|
||||
|
@ -43,14 +52,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
public void RunActions()
|
||||
{
|
||||
while (ActionsQueue.Count > 0)
|
||||
int Count = ActionsQueue.Count;
|
||||
|
||||
while (Count-- > 0)
|
||||
{
|
||||
ActionsQueue.Dequeue()();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
FbRenderer.Render();
|
||||
|
||||
for (int Index = 0; Index < VertexBuffers.Count; Index++)
|
||||
{
|
||||
VertexBuffer Vb = VertexBuffers[Index];
|
||||
|
@ -62,7 +75,28 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
GL.DrawArrays(PrimitiveType.TriangleStrip, 0, Vb.PrimCount);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void SetWindowSize(int Width, int Height)
|
||||
{
|
||||
FbRenderer.WindowWidth = Width;
|
||||
FbRenderer.WindowHeight = Height;
|
||||
}
|
||||
|
||||
public unsafe void SetFrameBuffer(
|
||||
byte* Fb,
|
||||
int Width,
|
||||
int Height,
|
||||
float ScaleX,
|
||||
float ScaleY,
|
||||
float Rotate)
|
||||
{
|
||||
Matrix2 Transform;
|
||||
|
||||
Transform = Matrix2.CreateScale(ScaleX, ScaleY);
|
||||
Transform *= Matrix2.CreateRotation(Rotate);
|
||||
|
||||
FbRenderer.Set(Fb, Width, Height, Transform);
|
||||
}
|
||||
|
||||
public void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs)
|
||||
|
|
|
@ -4,6 +4,14 @@
|
|||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK.NETCore" Version="1.1.2749.6433" />
|
||||
</ItemGroup>
|
||||
|
@ -12,4 +20,13 @@
|
|||
<ProjectReference Include="..\ChocolArm64\ChocolArm64.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Gal\OpenGL\FbVtxShader.glsl">
|
||||
<LogicalName>GlFbVtxShader</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Gal\OpenGL\FbFragShader.glsl">
|
||||
<LogicalName>GlFbFragShader</LogicalName>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue