diff --git a/Ryujinx.Graphics.GAL/Format.cs b/Ryujinx.Graphics.GAL/Format.cs
index 19939c38a0..a666736141 100644
--- a/Ryujinx.Graphics.GAL/Format.cs
+++ b/Ryujinx.Graphics.GAL/Format.cs
@@ -230,6 +230,25 @@ namespace Ryujinx.Graphics.GAL
             return false;
         }
 
+        /// <summary>
+        /// Checks if the texture format is a BGRA format with 8-bit components.
+        /// </summary>
+        /// <param name="format">Texture format</param>
+        /// <returns>True if the texture format is a BGRA format with 8-bit components, false otherwise</returns>
+        public static bool IsBgra8(this Format format)
+        {
+            switch (format)
+            {
+                case Format.B8G8R8X8Unorm:
+                case Format.B8G8R8A8Unorm:
+                case Format.B8G8R8X8Srgb:
+                case Format.B8G8R8A8Srgb:
+                    return true;
+            }
+
+            return false;
+        }
+
         /// <summary>
         /// Checks if the texture format is a depth, stencil or depth-stencil format.
         /// </summary>
diff --git a/Ryujinx.Graphics.OpenGL/FormatTable.cs b/Ryujinx.Graphics.OpenGL/FormatTable.cs
index b178553cd8..4200ea7e0f 100644
--- a/Ryujinx.Graphics.OpenGL/FormatTable.cs
+++ b/Ryujinx.Graphics.OpenGL/FormatTable.cs
@@ -164,10 +164,10 @@ namespace Ryujinx.Graphics.OpenGL
             Add(Format.B5G5R5X1Unorm,       new FormatInfo(4, true,  false, All.Rgb5,              PixelFormat.Bgra,           PixelType.UnsignedShort5551));
             Add(Format.B5G5R5A1Unorm,       new FormatInfo(4, true,  false, All.Rgb5A1,            PixelFormat.Bgra,           PixelType.UnsignedShort5551));
             Add(Format.A1B5G5R5Unorm,       new FormatInfo(4, true,  false, All.Rgb5A1,            PixelFormat.Bgra,           PixelType.UnsignedShort1555Reversed));
-            Add(Format.B8G8R8X8Unorm,       new FormatInfo(4, true,  false, All.Rgba8,             PixelFormat.Bgra,           PixelType.UnsignedByte));
-            Add(Format.B8G8R8A8Unorm,       new FormatInfo(4, true,  false, All.Rgba8,             PixelFormat.Bgra,           PixelType.UnsignedByte));
-            Add(Format.B8G8R8X8Srgb,        new FormatInfo(4, false, false, All.Srgb8,             PixelFormat.BgraInteger,    PixelType.UnsignedByte));
-            Add(Format.B8G8R8A8Srgb,        new FormatInfo(4, false, false, All.Srgb8Alpha8,       PixelFormat.BgraInteger,    PixelType.UnsignedByte));
+            Add(Format.B8G8R8X8Unorm,       new FormatInfo(4, true,  false, All.Rgba8,             PixelFormat.Rgba,           PixelType.UnsignedByte));
+            Add(Format.B8G8R8A8Unorm,       new FormatInfo(4, true,  false, All.Rgba8,             PixelFormat.Rgba,           PixelType.UnsignedByte));
+            Add(Format.B8G8R8X8Srgb,        new FormatInfo(4, false, false, All.Srgb8,             PixelFormat.Rgba,           PixelType.UnsignedByte));
+            Add(Format.B8G8R8A8Srgb,        new FormatInfo(4, false, false, All.Srgb8Alpha8,       PixelFormat.Rgba,           PixelType.UnsignedByte));
         }
 
         private static void Add(Format format, FormatInfo info)
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs b/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs
index dfb81642c5..5f786decc7 100644
--- a/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs
+++ b/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs
@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
     {
         public int Handle { get; protected set; }
 
-        protected TextureCreateInfo Info { get; }
+        public TextureCreateInfo Info { get; }
 
         public int Width { get; }
         public int Height { get; }
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
index e89d5614ca..edfbec5f82 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;
+            }
         }
     }
 }
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
index 02353ffaa8..2d50eba5e1 100644
--- a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
+++ b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
@@ -72,6 +72,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
                 (int)Info.SwizzleA.Convert()
             };
 
+            if (Info.Format.IsBgra8())
+            {
+                // Swap B <-> R for BGRA formats, as OpenGL has no support for them
+                // and we need to manually swap the components on read/write on the GPU.
+                int temp = swizzleRgba[0];
+                swizzleRgba[0] = swizzleRgba[2];
+                swizzleRgba[2] = temp;
+            }
+
             GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
 
             int maxLevel = Info.Levels - 1;
@@ -189,7 +198,12 @@ namespace Ryujinx.Graphics.OpenGL.Image
             return data;
         }
 
-        private void WriteTo(IntPtr ptr)
+        public void WriteToPbo(int offset, bool forceBgra)
+        {
+            WriteTo(IntPtr.Zero + offset, forceBgra);
+        }
+
+        private void WriteTo(IntPtr data, bool forceBgra = false)
         {
             TextureTarget target = Target.Convert();
 
@@ -197,6 +211,14 @@ namespace Ryujinx.Graphics.OpenGL.Image
 
             FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
 
+            PixelFormat pixelFormat = format.PixelFormat;
+            PixelType   pixelType   = format.PixelType;
+
+            if (forceBgra)
+            {
+                pixelFormat = PixelFormat.Bgra;
+            }
+
             int faces = 1;
 
             if (target == TextureTarget.TextureCubeMap)
@@ -214,20 +236,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
 
                     if (format.IsCompressed)
                     {
-                        GL.GetCompressedTexImage(target + face, level, ptr + faceOffset);
+                        GL.GetCompressedTexImage(target + face, level, data + faceOffset);
                     }
                     else
                     {
-                        GL.GetTexImage(
-                            target + face,
-                            level,
-                            format.PixelFormat,
-                            format.PixelType,
-                            ptr + faceOffset);
+                        GL.GetTexImage(target + face, level, pixelFormat, pixelType, data + faceOffset);
                     }
                 }
 
-                ptr += Info.GetMipSize(level);
+                data += Info.GetMipSize(level);
             }
         }
 
@@ -237,12 +254,17 @@ namespace Ryujinx.Graphics.OpenGL.Image
             {
                 fixed (byte* ptr = data)
                 {
-                    SetData((IntPtr)ptr, data.Length);
+                    ReadFrom((IntPtr)ptr, data.Length);
                 }
             }
         }
 
-        private void SetData(IntPtr data, int size)
+        public void ReadFromPbo(int offset, int size)
+        {
+            ReadFrom(IntPtr.Zero + offset, size);
+        }
+
+        private void ReadFrom(IntPtr data, int size)
         {
             TextureTarget target = Target.Convert();
 
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs
index 2016d85246..09ba9be0b1 100644
--- a/Ryujinx.Graphics.OpenGL/Pipeline.cs
+++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs
@@ -31,6 +31,7 @@ namespace Ryujinx.Graphics.OpenGL
         private int _boundDrawFramebuffer;
         private int _boundReadFramebuffer;
 
+        private int[] _fpIsBgra = new int[8];
         private float[] _fpRenderScale = new float[33];
         private float[] _cpRenderScale = new float[32];
 
@@ -722,12 +723,12 @@ namespace Ryujinx.Graphics.OpenGL
                 GL.Disable(EnableCap.ProgramPointSize);
             }
 
-            GL.PointParameter(origin == Origin.LowerLeft 
-                ? PointSpriteCoordOriginParameter.LowerLeft 
+            GL.PointParameter(origin == Origin.LowerLeft
+                ? PointSpriteCoordOriginParameter.LowerLeft
                 : PointSpriteCoordOriginParameter.UpperLeft);
 
             // Games seem to set point size to 0 which generates a GL_INVALID_VALUE
-            // From the spec, GL_INVALID_VALUE is generated if size is less than or equal to 0. 
+            // From the spec, GL_INVALID_VALUE is generated if size is less than or equal to 0.
             GL.PointSize(Math.Max(float.Epsilon, size));
         }
 
@@ -765,6 +766,7 @@ namespace Ryujinx.Graphics.OpenGL
                 _program.Bind();
             }
 
+            UpdateFpIsBgra();
             SetRenderTargetScale(_fpRenderScale[0]);
         }
 
@@ -814,12 +816,15 @@ namespace Ryujinx.Graphics.OpenGL
                 TextureView color = (TextureView)colors[index];
 
                 _framebuffer.AttachColor(index, color);
+
+                _fpIsBgra[index] = color != null && color.Format.IsBgra8() ? 1 : 0;
             }
 
+            UpdateFpIsBgra();
+
             TextureView depthStencilView = (TextureView)depthStencil;
 
             _framebuffer.AttachDepthStencil(depthStencilView);
-
             _framebuffer.SetDrawBuffers(colors.Length);
 
             _hasDepthBuffer = depthStencil != null && depthStencilView.Format != Format.S8Uint;
@@ -938,7 +943,9 @@ namespace Ryujinx.Graphics.OpenGL
 
                                 if (activeTarget != null && activeTarget.Width / (float)texture.Width == activeTarget.Height / (float)texture.Height)
                                 {
-                                    // If the texture's size is a multiple of the sampler size, enable interpolation using gl_FragCoord. (helps "invent" new integer values between scaled pixels)
+                                    // If the texture's size is a multiple of the sampler size,
+                                    // enable interpolation using gl_FragCoord.
+                                    // (helps "invent" new integer values between scaled pixels)
                                     interpolate = true;
                                 }
                             }
@@ -1112,6 +1119,14 @@ namespace Ryujinx.Graphics.OpenGL
             return (_boundDrawFramebuffer, _boundReadFramebuffer);
         }
 
+        private void UpdateFpIsBgra()
+        {
+            if (_program != null)
+            {
+                GL.Uniform1(_program.FragmentIsBgraUniform, 8, _fpIsBgra);
+            }
+        }
+
         private void UpdateDepthTest()
         {
             // Enabling depth operations is only valid when we have
@@ -1137,6 +1152,29 @@ namespace Ryujinx.Graphics.OpenGL
             }
         }
 
+        public void UpdateRenderScale(ShaderStage stage, int textureCount)
+        {
+            if (_program != null)
+            {
+                switch (stage)
+                {
+                    case ShaderStage.Fragment:
+                        if (_program.FragmentRenderScaleUniform != -1)
+                        {
+                            GL.Uniform1(_program.FragmentRenderScaleUniform, textureCount + 1, _fpRenderScale);
+                        }
+                        break;
+
+                    case ShaderStage.Compute:
+                        if (_program.ComputeRenderScaleUniform != -1)
+                        {
+                            GL.Uniform1(_program.ComputeRenderScaleUniform, textureCount, _cpRenderScale);
+                        }
+                        break;
+                }
+            }
+        }
+
         private void PrepareForDispatch()
         {
             if (_unit0Texture != null)
@@ -1230,28 +1268,5 @@ namespace Ryujinx.Graphics.OpenGL
             _framebuffer?.Dispose();
             _vertexArray?.Dispose();
         }
-
-        public void UpdateRenderScale(ShaderStage stage, int textureCount)
-        {
-            if (_program != null)
-            {
-                switch (stage)
-                {
-                    case ShaderStage.Fragment:
-                        if (_program.FragmentRenderScaleUniform != -1)
-                        {
-                            GL.Uniform1(_program.FragmentRenderScaleUniform, textureCount + 1, _fpRenderScale);
-                        }
-                        break;
-
-                    case ShaderStage.Compute:
-                        if (_program.ComputeRenderScaleUniform != -1)
-                        {
-                            GL.Uniform1(_program.ComputeRenderScaleUniform, textureCount, _cpRenderScale);
-                        }
-                        break;
-                }
-            }
-        }
     }
 }
diff --git a/Ryujinx.Graphics.OpenGL/Program.cs b/Ryujinx.Graphics.OpenGL/Program.cs
index a0f8eb0159..06f05f67c5 100644
--- a/Ryujinx.Graphics.OpenGL/Program.cs
+++ b/Ryujinx.Graphics.OpenGL/Program.cs
@@ -25,6 +25,7 @@ namespace Ryujinx.Graphics.OpenGL
 
         public int Handle { get; private set; }
 
+        public int FragmentIsBgraUniform { get; }
         public int FragmentRenderScaleUniform { get; }
         public int ComputeRenderScaleUniform { get; }
 
@@ -218,6 +219,7 @@ namespace Ryujinx.Graphics.OpenGL
                 }
             }
 
+            FragmentIsBgraUniform = GL.GetUniformLocation(Handle, "is_bgra");
             FragmentRenderScaleUniform = GL.GetUniformLocation(Handle, "fp_renderScale");
             ComputeRenderScaleUniform = GL.GetUniformLocation(Handle, "cp_renderScale");
         }
diff --git a/Ryujinx.Graphics.OpenGL/Window.cs b/Ryujinx.Graphics.OpenGL/Window.cs
index b7dc378431..a2f4e4ce9a 100644
--- a/Ryujinx.Graphics.OpenGL/Window.cs
+++ b/Ryujinx.Graphics.OpenGL/Window.cs
@@ -51,10 +51,12 @@ namespace Ryujinx.Graphics.OpenGL
             GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
             GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
 
+            TextureView viewConverted = view.Format.IsBgra8() ? _renderer.TextureCopy.BgraSwap(view) : view;
+
             GL.FramebufferTexture(
                 FramebufferTarget.ReadFramebuffer,
                 FramebufferAttachment.ColorAttachment0,
-                view.Handle,
+                viewConverted.Handle,
                 0);
 
             GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
@@ -138,6 +140,11 @@ namespace Ryujinx.Graphics.OpenGL
 
             ((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
             ((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
+
+            if (viewConverted != view)
+            {
+                viewConverted.Dispose();
+            }
         }
 
         private int GetCopyFramebufferHandleLazy()
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index efd30143ba..40e277e067 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -139,6 +139,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
 
             if (context.Config.Stage == ShaderStage.Fragment || context.Config.Stage == ShaderStage.Compute)
             {
+                if (context.Config.Stage == ShaderStage.Fragment)
+                {
+                    context.AppendLine($"uniform bool {DefaultNames.IsBgraName}[8];");
+                    context.AppendLine();
+                }
+
                 if (DeclareRenderScale(context))
                 {
                     context.AppendLine();
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs
index 4da38b2de5..d1cf4636bc 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs
@@ -23,5 +23,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
         public const string SharedMemoryName = "shared_mem";
 
         public const string UndefinedName = "undef";
+
+        public const string IsBgraName = "is_bgra";
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
index 8801fc1113..4ae9a00ac7 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
@@ -64,6 +64,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
             { AttributeConsts.GtMask,              new BuiltInAttribute("unpackUint2x32(gl_SubGroupGtMaskARB).x", VariableType.U32) },
             { AttributeConsts.LeMask,              new BuiltInAttribute("unpackUint2x32(gl_SubGroupLeMaskARB).x", VariableType.U32) },
             { AttributeConsts.LtMask,              new BuiltInAttribute("unpackUint2x32(gl_SubGroupLtMaskARB).x", VariableType.U32) },
+
+            // Support uniforms.
+            { AttributeConsts.FragmentOutputIsBgraBase + 0,  new BuiltInAttribute($"{DefaultNames.IsBgraName}[0]",  VariableType.Bool) },
+            { AttributeConsts.FragmentOutputIsBgraBase + 4,  new BuiltInAttribute($"{DefaultNames.IsBgraName}[1]",  VariableType.Bool) },
+            { AttributeConsts.FragmentOutputIsBgraBase + 8,  new BuiltInAttribute($"{DefaultNames.IsBgraName}[2]",  VariableType.Bool) },
+            { AttributeConsts.FragmentOutputIsBgraBase + 12, new BuiltInAttribute($"{DefaultNames.IsBgraName}[3]",  VariableType.Bool) },
+            { AttributeConsts.FragmentOutputIsBgraBase + 16, new BuiltInAttribute($"{DefaultNames.IsBgraName}[4]",  VariableType.Bool) },
+            { AttributeConsts.FragmentOutputIsBgraBase + 20, new BuiltInAttribute($"{DefaultNames.IsBgraName}[5]",  VariableType.Bool) },
+            { AttributeConsts.FragmentOutputIsBgraBase + 24, new BuiltInAttribute($"{DefaultNames.IsBgraName}[6]",  VariableType.Bool) },
+            { AttributeConsts.FragmentOutputIsBgraBase + 28, new BuiltInAttribute($"{DefaultNames.IsBgraName}[7]",  VariableType.Bool) }
         };
 
         private Dictionary<AstOperand, string> _locals;
@@ -149,8 +159,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
 
             char swzMask = GetSwizzleMask((value >> 2) & 3);
 
-            if (value >= AttributeConsts.UserAttributeBase &&
-                value <  AttributeConsts.UserAttributeEnd)
+            if (value >= AttributeConsts.UserAttributeBase && value < AttributeConsts.UserAttributeEnd)
             {
                 value -= AttributeConsts.UserAttributeBase;
 
@@ -169,8 +178,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
             }
             else
             {
-                if (value >= AttributeConsts.FragmentOutputColorBase &&
-                    value <  AttributeConsts.FragmentOutputColorEnd)
+                if (value >= AttributeConsts.FragmentOutputColorBase && value < AttributeConsts.FragmentOutputColorEnd)
                 {
                     value -= AttributeConsts.FragmentOutputColorBase;
 
diff --git a/Ryujinx.Graphics.Shader/Translation/AttributeConsts.cs b/Ryujinx.Graphics.Shader/Translation/AttributeConsts.cs
index 8ff37429ae..c194b5c2e4 100644
--- a/Ryujinx.Graphics.Shader/Translation/AttributeConsts.cs
+++ b/Ryujinx.Graphics.Shader/Translation/AttributeConsts.cs
@@ -35,6 +35,9 @@ namespace Ryujinx.Graphics.Shader.Translation
         public const int FragmentOutputColorBase = 0x1000010;
         public const int FragmentOutputColorEnd  = FragmentOutputColorBase + 8 * 16;
 
+        public const int FragmentOutputIsBgraBase = 0x1000100;
+        public const int FragmentOutputIsBgraEnd  = FragmentOutputIsBgraBase + 8 * 4;
+
         public const int ThreadIdX = 0x2000000;
         public const int ThreadIdY = 0x2000004;
         public const int ThreadIdZ = 0x2000008;
diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
index 39532a64f6..9b26fa4a67 100644
--- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
@@ -115,22 +115,46 @@ namespace Ryujinx.Graphics.Shader.Translation
 
                 int regIndex = 0;
 
-                for (int attachment = 0; attachment < 8; attachment++)
+                for (int rtIndex = 0; rtIndex < 8; rtIndex++)
                 {
-                    OmapTarget target = Config.OmapTargets[attachment];
+                    OmapTarget target = Config.OmapTargets[rtIndex];
 
                     for (int component = 0; component < 4; component++)
                     {
-                        if (target.ComponentEnabled(component))
+                        if (!target.ComponentEnabled(component))
                         {
-                            Operand dest = Attribute(AttributeConsts.FragmentOutputColorBase + attachment * 16 + component * 4);
-
-                            Operand src = Register(regIndex, RegisterType.Gpr);
-
-                            this.Copy(dest, src);
-
-                            regIndex++;
+                            continue;
                         }
+
+                        int fragmentOutputColorAttr = AttributeConsts.FragmentOutputColorBase + rtIndex * 16;
+
+                        Operand src = Register(regIndex, RegisterType.Gpr);
+
+                        // Perform B <-> R swap if needed, for BGRA formats (not supported on OpenGL).
+                        if (component == 0 || component == 2)
+                        {
+                            Operand isBgra = Attribute(AttributeConsts.FragmentOutputIsBgraBase + rtIndex * 4);
+
+                            Operand lblIsBgra = Label();
+                            Operand lblEnd    = Label();
+
+                            this.BranchIfTrue(lblIsBgra, isBgra);
+
+                            this.Copy(Attribute(fragmentOutputColorAttr + component * 4), src);
+                            this.Branch(lblEnd);
+
+                            MarkLabel(lblIsBgra);
+
+                            this.Copy(Attribute(fragmentOutputColorAttr + (2 - component) * 4), src);
+
+                            MarkLabel(lblEnd);
+                        }
+                        else
+                        {
+                            this.Copy(Attribute(fragmentOutputColorAttr + component * 4), src);
+                        }
+
+                        regIndex++;
                     }
                 }
             }
diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
index e1eb55ade7..dbb05c7720 100644
--- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
+++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
@@ -247,7 +247,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
         }
 
         private void PostFrameBuffer(Layer layer, BufferItem item)
-        { 
+        {
             int frameBufferWidth  = item.GraphicBuffer.Object.Width;
             int frameBufferHeight = item.GraphicBuffer.Object.Height;