From 8dbcae1ff88927dc0734d5f0e24fbf8781d68590 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sun, 26 Jul 2020 00:03:40 -0300
Subject: Implement BGRA texture support (#1418)

* Implement BGRA texture support

* Missing AppendLine

* Remove empty lines

* Address PR feedback
---
 Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs | 65 +++++++++++++++++++++++++++-
 1 file changed, 64 insertions(+), 1 deletion(-)

(limited to 'Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs')

diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
index e89d5614..edfbec5f 100644
--- a/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
+++ b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
@@ -11,6 +11,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
         private int _srcFramebuffer;
         private int _dstFramebuffer;
 
+        private int _copyPboHandle;
+        private int _copyPboSize;
+
         public TextureCopy(Renderer renderer)
         {
             _renderer = renderer;
@@ -23,12 +26,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
             Extents2D   dstRegion,
             bool        linearFilter)
         {
+            TextureView srcConverted = src.Format.IsBgra8() != dst.Format.IsBgra8() ? BgraSwap(src) : src;
+
             (int oldDrawFramebufferHandle, int oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers();
 
             GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy());
             GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy());
 
-            Attach(FramebufferTarget.ReadFramebuffer, src.Format, src.Handle);
+            Attach(FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle);
             Attach(FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle);
 
             ClearBufferMask mask = GetMask(src.Format);
@@ -68,6 +73,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
 
             ((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
             ((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
+
+            if (srcConverted != src)
+            {
+                srcConverted.Dispose();
+            }
         }
 
         private static void Attach(FramebufferTarget target, Format format, int handle)
@@ -117,6 +127,52 @@ namespace Ryujinx.Graphics.OpenGL.Image
                    format == Format.D32Float;
         }
 
+        public TextureView BgraSwap(TextureView from)
+        {
+            TextureView to = (TextureView)_renderer.CreateTexture(from.Info, 1f);
+
+            EnsurePbo(from);
+
+            GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPboHandle);
+
+            from.WriteToPbo(0, forceBgra: true);
+
+            GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
+            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, _copyPboHandle);
+
+            to.ReadFromPbo(0, _copyPboSize);
+
+            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
+
+            return to;
+        }
+
+        private void EnsurePbo(TextureView view)
+        {
+            int requiredSize = 0;
+
+            for (int level = 0; level < view.Info.Levels; level++)
+            {
+                requiredSize += view.Info.GetMipSize(level);
+            }
+
+            if (_copyPboSize < requiredSize && _copyPboHandle != 0)
+            {
+                GL.DeleteBuffer(_copyPboHandle);
+
+                _copyPboHandle = 0;
+            }
+
+            if (_copyPboHandle == 0)
+            {
+                _copyPboHandle = GL.GenBuffer();
+                _copyPboSize = requiredSize;
+
+                GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPboHandle);
+                GL.BufferData(BufferTarget.PixelPackBuffer, requiredSize, IntPtr.Zero, BufferUsageHint.DynamicCopy);
+            }
+        }
+
         private int GetSrcFramebufferLazy()
         {
             if (_srcFramebuffer == 0)
@@ -152,6 +208,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
 
                 _dstFramebuffer = 0;
             }
+
+            if (_copyPboHandle != 0)
+            {
+                GL.DeleteBuffer(_copyPboHandle);
+
+                _copyPboHandle = 0;
+            }
         }
     }
 }
-- 
cgit v1.2.3-70-g09d2