From 5d8a615c21eff7888ff4e36c122123560bcb0886 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 28 Feb 2018 23:37:40 -0300 Subject: [PATCH] Enable hardware frame buffer texture scaling --- Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs | 47 +++++++++++++++++-- Ryujinx.Graphics/Gal/IGalRenderer.cs | 13 ++++- Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl | 6 ++- Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs | 6 ++- Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs | 15 ++++-- 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs index 3e45c44196..b745867e92 100644 --- a/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs +++ b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs @@ -35,12 +35,22 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android Acquired } + private struct Rect + { + public int Top; + public int Left; + public int Right; + public int Bottom; + } + private struct BufferEntry { public BufferState State; public HalTransform Transform; + public Rect Crop; + public GbpBuffer Data; } @@ -168,6 +178,11 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android BufferQueue[Slot].Transform = (HalTransform)Transform; + BufferQueue[Slot].Crop.Top = CropTop; + BufferQueue[Slot].Crop.Left = CropLeft; + BufferQueue[Slot].Crop.Right = CropRight; + BufferQueue[Slot].Crop.Bottom = CropBottom; + BufferQueue[Slot].State = BufferState.Queued; SendFrameBuffer(Context, Slot); @@ -256,20 +271,44 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android return; } - BufferQueue[Slot].State = BufferState.Acquired; + BufferQueue[Slot].State = BufferState.Acquired; + + Rect Crop = BufferQueue[Slot].Crop; + + int RealWidth = FbWidth; + int RealHeight = FbHeight; float ScaleX = 1; float ScaleY = 1; + float OffsX = 0; + float OffsY = 0; + + if (Crop.Right != 0 && + Crop.Bottom != 0) + { + RealWidth = Crop.Right - Crop.Left; + RealHeight = Crop.Bottom - Crop.Top; + + ScaleX = (float)FbWidth / RealWidth; + ScaleY = (float)FbHeight / RealHeight; + + OffsX = -(float)Crop.Left / Crop.Right; + OffsY = -(float)Crop.Top / Crop.Bottom; + + OffsX += ScaleX - 1; + OffsY += ScaleY - 1; + } + float Rotate = 0; if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX)) { - ScaleX = -1; + ScaleX = -ScaleX; } if (BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY)) { - ScaleY = -1; + ScaleY = -ScaleY; } if (BufferQueue[Slot].Transform.HasFlag(HalTransform.Rotate90)) @@ -287,6 +326,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android FbHeight, ScaleX, ScaleY, + OffsX, + OffsY, Rotate); BufferQueue[Slot].State = BufferState.Free; diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs index 5854c54a6b..83d2c699f8 100644 --- a/Ryujinx.Graphics/Gal/IGalRenderer.cs +++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs @@ -10,9 +10,20 @@ namespace Ryujinx.Graphics.Gal 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 SetFrameBuffer( + byte* Fb, + int Width, + int Height, + float ScaleX, + float ScaleY, + float OffsX, + float OffsY, + float Rotate); + void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs); + void SendR8G8B8A8Texture(int Index, byte[] Buffer, int Width, int Height); + void BindTexture(int Index); } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl b/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl index 933fa6aa97..35d560c09b 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl +++ b/Ryujinx.Graphics/Gal/OpenGL/FbVtxShader.glsl @@ -2,8 +2,9 @@ precision highp float; -uniform vec2 window_size; uniform mat2 transform; +uniform vec2 window_size; +uniform vec2 offset; layout(location = 0) in vec2 in_position; layout(location = 1) in vec2 in_tex_coord; @@ -22,5 +23,6 @@ vec2 get_scale_ratio(void) { void main(void) { tex_coord = in_tex_coord; - gl_Position = vec4((transform * in_position) * get_scale_ratio(), 0, 1); + vec2 t_pos = (transform * in_position) + offset; + gl_Position = vec4(t_pos * get_scale_ratio(), 0, 1); } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs index c66c0cb754..7dc4bffe34 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/FrameBuffer.cs @@ -135,7 +135,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.BindVertexArray(0); } - public unsafe void Set(byte* Fb, int Width, int Height, Matrix2 Transform) + public unsafe void Set(byte* Fb, int Width, int Height, Matrix2 Transform, Vector2 Offs) { if (Fb == null) { @@ -172,6 +172,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL 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 Render() diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs index 5ae5e22597..bdedfc1a87 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs @@ -1,6 +1,7 @@ using OpenTK; using OpenTK.Graphics.OpenGL; using System; +using System.Collections.Concurrent; using System.Collections.Generic; namespace Ryujinx.Graphics.Gal.OpenGL @@ -24,7 +25,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL private Texture[] Textures; - private Queue ActionsQueue; + private ConcurrentQueue ActionsQueue; private FrameBuffer FbRenderer; @@ -34,7 +35,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL Textures = new Texture[8]; - ActionsQueue = new Queue(); + ActionsQueue = new ConcurrentQueue(); } public void InitializeFrameBuffer() @@ -51,9 +52,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL { int Count = ActionsQueue.Count; - while (Count-- > 0) + while (Count-- > 0 && ActionsQueue.TryDequeue(out Action RenderAction)) { - ActionsQueue.Dequeue()(); + RenderAction(); } } @@ -86,6 +87,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL int Height, float ScaleX, float ScaleY, + float OffsX, + float OffsY, float Rotate) { Matrix2 Transform; @@ -93,7 +96,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL Transform = Matrix2.CreateScale(ScaleX, ScaleY); Transform *= Matrix2.CreateRotation(Rotate); - FbRenderer.Set(Fb, Width, Height, Transform); + Vector2 Offs = new Vector2(OffsX, OffsY); + + FbRenderer.Set(Fb, Width, Height, Transform, Offs); } public void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs)