diff options
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Image')
| -rw-r--r-- | Ryujinx.Graphics.OpenGL/Image/TextureBase.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs | 65 | ||||
| -rw-r--r-- | Ryujinx.Graphics.OpenGL/Image/TextureView.cs | 44 |
3 files changed, 98 insertions, 13 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs b/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs index dfb81642..5f786dec 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 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; + } } } } diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs index 02353ffa..2d50eba5 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(); |
