mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-24 19:27:11 +02:00
Fix for current framebuffer issues (#78)
[GPU] Fix some of the current framebuffer issues
This commit is contained in:
parent
262b5b8054
commit
c8c86a3854
23 changed files with 482 additions and 891 deletions
|
@ -1,250 +0,0 @@
|
|||
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;
|
||||
|
||||
private object FbPtrLock;
|
||||
|
||||
public FrameBuffer(int Width, int Height)
|
||||
{
|
||||
if (Width < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Width));
|
||||
}
|
||||
|
||||
if (Height < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Height));
|
||||
}
|
||||
|
||||
FbPtrLock = new object();
|
||||
|
||||
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, Vector2 Offs)
|
||||
{
|
||||
if (Fb == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Fb));
|
||||
}
|
||||
|
||||
if (Width < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Width));
|
||||
}
|
||||
|
||||
if (Height < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Height));
|
||||
}
|
||||
|
||||
lock (FbPtrLock)
|
||||
{
|
||||
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));
|
||||
|
||||
int OffsetUniformLocation = GL.GetUniformLocation(PrgShaderHandle, "offset");
|
||||
|
||||
GL.Uniform2(OffsetUniformLocation, Offs);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
lock (FbPtrLock)
|
||||
{
|
||||
FbPtr = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
lock (FbPtrLock)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -127,17 +127,72 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
public static BlendEquationMode GetBlendEquation(GalBlendEquation BlendEquation)
|
||||
{
|
||||
return (BlendEquationMode)BlendEquation;
|
||||
switch (BlendEquation)
|
||||
{
|
||||
case GalBlendEquation.FuncAdd: return BlendEquationMode.FuncAdd;
|
||||
case GalBlendEquation.FuncSubtract: return BlendEquationMode.FuncSubtract;
|
||||
case GalBlendEquation.FuncReverseSubtract: return BlendEquationMode.FuncReverseSubtract;
|
||||
case GalBlendEquation.Min: return BlendEquationMode.Min;
|
||||
case GalBlendEquation.Max: return BlendEquationMode.Max;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(BlendEquation));
|
||||
}
|
||||
|
||||
public static BlendingFactorSrc GetBlendFactorSrc(GalBlendFactor BlendFactor)
|
||||
{
|
||||
return (BlendingFactorSrc)(BlendFactor - 0x4000);
|
||||
switch (BlendFactor)
|
||||
{
|
||||
case GalBlendFactor.Zero: return BlendingFactorSrc.Zero;
|
||||
case GalBlendFactor.One: return BlendingFactorSrc.One;
|
||||
case GalBlendFactor.SrcColor: return BlendingFactorSrc.SrcColor;
|
||||
case GalBlendFactor.OneMinusSrcColor: return BlendingFactorSrc.OneMinusSrcColor;
|
||||
case GalBlendFactor.DstColor: return BlendingFactorSrc.DstColor;
|
||||
case GalBlendFactor.OneMinusDstColor: return BlendingFactorSrc.OneMinusDstColor;
|
||||
case GalBlendFactor.SrcAlpha: return BlendingFactorSrc.SrcAlpha;
|
||||
case GalBlendFactor.OneMinusSrcAlpha: return BlendingFactorSrc.OneMinusSrcAlpha;
|
||||
case GalBlendFactor.DstAlpha: return BlendingFactorSrc.DstAlpha;
|
||||
case GalBlendFactor.OneMinusDstAlpha: return BlendingFactorSrc.OneMinusDstAlpha;
|
||||
case GalBlendFactor.ConstantColor: return BlendingFactorSrc.ConstantColor;
|
||||
case GalBlendFactor.OneMinusConstantColor: return BlendingFactorSrc.OneMinusConstantColor;
|
||||
case GalBlendFactor.ConstantAlpha: return BlendingFactorSrc.ConstantAlpha;
|
||||
case GalBlendFactor.OneMinusConstantAlpha: return BlendingFactorSrc.OneMinusConstantAlpha;
|
||||
case GalBlendFactor.SrcAlphaSaturate: return BlendingFactorSrc.SrcAlphaSaturate;
|
||||
case GalBlendFactor.Src1Color: return BlendingFactorSrc.Src1Color;
|
||||
case GalBlendFactor.OneMinusSrc1Color: return BlendingFactorSrc.OneMinusSrc1Color;
|
||||
case GalBlendFactor.Src1Alpha: return BlendingFactorSrc.Src1Alpha;
|
||||
case GalBlendFactor.OneMinusSrc1Alpha: return BlendingFactorSrc.OneMinusSrc1Alpha;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(BlendFactor));
|
||||
}
|
||||
|
||||
public static BlendingFactorDest GetBlendFactorDst(GalBlendFactor BlendFactor)
|
||||
{
|
||||
return (BlendingFactorDest)(BlendFactor - 0x4000);
|
||||
switch (BlendFactor)
|
||||
{
|
||||
case GalBlendFactor.Zero: return BlendingFactorDest.Zero;
|
||||
case GalBlendFactor.One: return BlendingFactorDest.One;
|
||||
case GalBlendFactor.SrcColor: return BlendingFactorDest.SrcColor;
|
||||
case GalBlendFactor.OneMinusSrcColor: return BlendingFactorDest.OneMinusSrcColor;
|
||||
case GalBlendFactor.DstColor: return BlendingFactorDest.DstColor;
|
||||
case GalBlendFactor.OneMinusDstColor: return BlendingFactorDest.OneMinusDstColor;
|
||||
case GalBlendFactor.SrcAlpha: return BlendingFactorDest.SrcAlpha;
|
||||
case GalBlendFactor.OneMinusSrcAlpha: return BlendingFactorDest.OneMinusSrcAlpha;
|
||||
case GalBlendFactor.DstAlpha: return BlendingFactorDest.DstAlpha;
|
||||
case GalBlendFactor.OneMinusDstAlpha: return BlendingFactorDest.OneMinusDstAlpha;
|
||||
case GalBlendFactor.ConstantColor: return BlendingFactorDest.ConstantColor;
|
||||
case GalBlendFactor.OneMinusConstantColor: return BlendingFactorDest.OneMinusConstantColor;
|
||||
case GalBlendFactor.ConstantAlpha: return BlendingFactorDest.ConstantAlpha;
|
||||
case GalBlendFactor.OneMinusConstantAlpha: return BlendingFactorDest.OneMinusConstantAlpha;
|
||||
case GalBlendFactor.SrcAlphaSaturate: return BlendingFactorDest.SrcAlphaSaturate;
|
||||
case GalBlendFactor.Src1Color: return BlendingFactorDest.Src1Color;
|
||||
case GalBlendFactor.OneMinusSrc1Color: return BlendingFactorDest.OneMinusSrc1Color;
|
||||
case GalBlendFactor.Src1Alpha: return BlendingFactorDest.Src1Alpha;
|
||||
case GalBlendFactor.OneMinusSrc1Alpha: return BlendingFactorDest.OneMinusSrc1Alpha;
|
||||
}
|
||||
|
||||
throw new ArgumentException(nameof(BlendFactor));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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))
|
||||
{
|
||||
if (Fb.Width != Width ||
|
||||
Fb.Height != Height)
|
||||
{
|
||||
SetupTexture(Fb.TexHandle, Width, Height);
|
||||
|
||||
Fb.Width = Width;
|
||||
Fb.Height = Height;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Fbs[Index].FbHandle = GL.GenFramebuffer();
|
||||
Fbs[Index].RbHandle = GL.GenRenderbuffer();
|
||||
Fbs[Index].TexHandle = GL.GenTexture();
|
||||
Fb = new FrameBuffer(Width, Height);
|
||||
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fbs[Index].FbHandle);
|
||||
SetupTexture(Fb.TexHandle, Width, Height);
|
||||
|
||||
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, Fbs[Index].RbHandle);
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle);
|
||||
|
||||
GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.Depth24Stencil8, 1280, 720);
|
||||
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, Fb.RbHandle);
|
||||
|
||||
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, RenderbufferTarget.Renderbuffer, Fbs[Index].RbHandle);
|
||||
GL.RenderbufferStorage(
|
||||
RenderbufferTarget.Renderbuffer,
|
||||
RenderbufferStorage.Depth24Stencil8,
|
||||
Width,
|
||||
Height);
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, Fbs[Index].TexHandle);
|
||||
GL.FramebufferRenderbuffer(
|
||||
FramebufferTarget.Framebuffer,
|
||||
FramebufferAttachment.DepthStencilAttachment,
|
||||
RenderbufferTarget.Renderbuffer,
|
||||
Fb.RbHandle);
|
||||
|
||||
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, 1280, 720, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
|
||||
|
||||
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);
|
||||
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fbs[Index].FbHandle);
|
||||
CurrFbHandle = Fb.Handle;
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(int Index)
|
||||
public void BindTexture(long Tag, int Index)
|
||||
{
|
||||
if (Fbs[Index].FbHandle == 0)
|
||||
if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
|
||||
{
|
||||
return;
|
||||
GL.ActiveTexture(TextureUnit.Texture0 + Index);
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, Fb.TexHandle);
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(long Tag)
|
||||
{
|
||||
if (Fbs.TryGetValue(Tag, out FrameBuffer Fb))
|
||||
{
|
||||
CurrTexHandle = Fb.TexHandle;
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(byte[] Data, int Width, int Height)
|
||||
{
|
||||
if (RawFbTexHandle == 0)
|
||||
{
|
||||
RawFbTexHandle = GL.GenTexture();
|
||||
}
|
||||
|
||||
EnsureInitialized();
|
||||
if (RawFbTexWidth != Width ||
|
||||
RawFbTexHeight != Height)
|
||||
{
|
||||
SetupTexture(RawFbTexHandle, Width, Height);
|
||||
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,10 +15,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{
|
||||
GL.ActiveTexture(TextureUnit.Texture0 + Index);
|
||||
|
||||
int Handle = EnsureTextureInitialized(Index);
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, Handle);
|
||||
Bind(Index);
|
||||
|
||||
const int Level = 0; //TODO: Support mipmap textures.
|
||||
const int Border = 0;
|
||||
|
||||
if (IsCompressedTextureFormat(Texture.Format))
|
||||
|
@ -27,7 +26,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
GL.CompressedTexImage2D(
|
||||
TextureTarget.Texture2D,
|
||||
0,
|
||||
Level,
|
||||
InternalFmt,
|
||||
Texture.Width,
|
||||
Texture.Height,
|
||||
|
@ -39,27 +38,30 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
{
|
||||
const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
|
||||
|
||||
(PixelFormat, PixelType) Format = OGLEnumConverter.GetTextureFormat(Texture.Format);
|
||||
(PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(Texture.Format);
|
||||
|
||||
GL.TexImage2D(
|
||||
TextureTarget.Texture2D,
|
||||
0,
|
||||
Level,
|
||||
InternalFmt,
|
||||
Texture.Width,
|
||||
Texture.Height,
|
||||
Border,
|
||||
Format.Item1,
|
||||
Format.Item2,
|
||||
Format,
|
||||
Type,
|
||||
Texture.Data);
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(int Index, GalTextureSampler Sampler)
|
||||
public void Bind(int Index)
|
||||
{
|
||||
int Handle = EnsureTextureInitialized(Index);
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, Handle);
|
||||
}
|
||||
|
||||
public static void Set(GalTextureSampler Sampler)
|
||||
{
|
||||
int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU);
|
||||
int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
private ConcurrentQueue<Action> ActionsQueue;
|
||||
|
||||
private FrameBuffer FbRenderer;
|
||||
|
||||
public OpenGLRenderer()
|
||||
{
|
||||
Blend = new OGLBlend();
|
||||
|
@ -36,16 +34,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
ActionsQueue = new ConcurrentQueue<Action>();
|
||||
}
|
||||
|
||||
public void InitializeFrameBuffer()
|
||||
{
|
||||
FbRenderer = new FrameBuffer(1280, 720);
|
||||
}
|
||||
|
||||
public void ResetFrameBuffer()
|
||||
{
|
||||
FbRenderer.Reset();
|
||||
}
|
||||
|
||||
public void QueueAction(Action ActionMthd)
|
||||
{
|
||||
ActionsQueue.Enqueue(ActionMthd);
|
||||
|
@ -63,33 +51,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
|
||||
public void Render()
|
||||
{
|
||||
FbRenderer.Render();
|
||||
FrameBuffer.Render();
|
||||
}
|
||||
|
||||
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 OffsX,
|
||||
float OffsY,
|
||||
float Rotate)
|
||||
{
|
||||
Matrix2 Transform;
|
||||
|
||||
Transform = Matrix2.CreateScale(ScaleX, ScaleY);
|
||||
Transform *= Matrix2.CreateRotation(Rotate);
|
||||
|
||||
Vector2 Offs = new Vector2(OffsX, OffsY);
|
||||
|
||||
FbRenderer.Set(Fb, Width, Height, Transform, Offs);
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void SetBlendEnable(bool Enable)
|
||||
|
@ -132,19 +99,46 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
});
|
||||
}
|
||||
|
||||
public void SetFb(int FbIndex, int Width, int Height)
|
||||
public void CreateFrameBuffer(long Tag, int Width, int Height)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.Set(FbIndex, Width, Height));
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.Create(Tag, Width, Height));
|
||||
}
|
||||
|
||||
public void BindFrameBuffer(int FbIndex)
|
||||
public void BindFrameBuffer(long Tag)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.Bind(FbIndex));
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.Bind(Tag));
|
||||
}
|
||||
|
||||
public void DrawFrameBuffer(int FbIndex)
|
||||
public void BindFrameBufferTexture(long Tag, int Index, GalTextureSampler Sampler)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => FrameBuffer.Draw(FbIndex));
|
||||
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));
|
||||
}
|
||||
|
||||
public void ClearBuffers(int RtIndex, GalClearBufferFlags Flags)
|
||||
|
@ -239,14 +233,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
|||
ActionsQueue.Enqueue(() => Shader.BindProgram());
|
||||
}
|
||||
|
||||
public void SetTexture(int Index, GalTexture Tex)
|
||||
public void SetTextureAndSampler(int Index, GalTexture Texture, GalTextureSampler Sampler)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Texture.Set(Index, Tex));
|
||||
ActionsQueue.Enqueue(() =>
|
||||
{
|
||||
this.Texture.Set(Index, Texture);
|
||||
|
||||
OGLTexture.Set(Sampler);
|
||||
});
|
||||
}
|
||||
|
||||
public void SetSampler(int Index, GalTextureSampler Sampler)
|
||||
public void BindTexture(int Index)
|
||||
{
|
||||
ActionsQueue.Enqueue(() => Texture.Set(Index, Sampler));
|
||||
ActionsQueue.Enqueue(() => Texture.Bind(Index));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue