diff options
author | riperiperi <rhy3756547@hotmail.com> | 2020-11-20 20:14:45 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-20 17:14:45 -0300 |
commit | 9493cdfe553d77d8f37927ef2acf87cfbab1c467 (patch) | |
tree | 9c5e5b588c1fa9372274d3d780b4cbb041bf24c5 /Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs | |
parent | cf7044e37bc628f25525941d25b830594b833428 (diff) |
Allow copy destination to have a different scale from source (#1711)
* Allow copy destination to have a different scale from source
Will result in more scaled copy destinations, but allows scaling in some games that copy textures to the output framebuffer.
* Support copying multiple levels/layers
Uses glFramebufferTextureLayer to copy multiple layers, copies levels individually (and scales the regions).
Remove CopyArrayScaled, since the backend copy handles it now.
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs')
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs | 103 |
1 files changed, 70 insertions, 33 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs index 74832dd8..20a3b914 100644 --- a/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs @@ -34,37 +34,60 @@ namespace Ryujinx.Graphics.OpenGL.Image GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy()); GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy()); - Attach(FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle); - Attach(FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle); + int levels = Math.Min(src.Info.Levels, dst.Info.Levels); + int layers = Math.Min(src.Info.GetLayers(), dst.Info.GetLayers()); - ClearBufferMask mask = GetMask(src.Format); - - if ((mask & (ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit)) != 0 || src.Format.IsInteger()) + for (int level = 0; level < levels; level++) { - linearFilter = false; - } - - BlitFramebufferFilter filter = linearFilter - ? BlitFramebufferFilter.Linear - : BlitFramebufferFilter.Nearest; - - GL.ReadBuffer(ReadBufferMode.ColorAttachment0); - GL.DrawBuffer(DrawBufferMode.ColorAttachment0); - - GL.Disable(EnableCap.RasterizerDiscard); - GL.Disable(IndexedEnableCap.ScissorTest, 0); + for (int layer = 0; layer < layers; layer++) + { + if (layers > 1) + { + Attach(FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, level, layer); + Attach(FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, level, layer); + } + else + { + Attach(FramebufferTarget.ReadFramebuffer, src.Format, srcConverted.Handle, level); + Attach(FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle, level); + } + + ClearBufferMask mask = GetMask(src.Format); + + if ((mask & (ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit)) != 0 || src.Format.IsInteger()) + { + linearFilter = false; + } + + BlitFramebufferFilter filter = linearFilter + ? BlitFramebufferFilter.Linear + : BlitFramebufferFilter.Nearest; + + GL.ReadBuffer(ReadBufferMode.ColorAttachment0); + GL.DrawBuffer(DrawBufferMode.ColorAttachment0); + + GL.Disable(EnableCap.RasterizerDiscard); + GL.Disable(IndexedEnableCap.ScissorTest, 0); + + GL.BlitFramebuffer( + srcRegion.X1, + srcRegion.Y1, + srcRegion.X2, + srcRegion.Y2, + dstRegion.X1, + dstRegion.Y1, + dstRegion.X2, + dstRegion.Y2, + mask, + filter); + } - GL.BlitFramebuffer( - srcRegion.X1, - srcRegion.Y1, - srcRegion.X2, - srcRegion.Y2, - dstRegion.X1, - dstRegion.Y1, - dstRegion.X2, - dstRegion.Y2, - mask, - filter); + if (level < levels - 1) + { + srcRegion = srcRegion.Reduce(1); + dstRegion = dstRegion.Reduce(1); + } + } Attach(FramebufferTarget.ReadFramebuffer, src.Format, 0); Attach(FramebufferTarget.DrawFramebuffer, dst.Format, 0); @@ -191,26 +214,40 @@ namespace Ryujinx.Graphics.OpenGL.Image } } - private static void Attach(FramebufferTarget target, Format format, int handle) + private static FramebufferAttachment AttachmentForFormat(Format format) { if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint) { - GL.FramebufferTexture(target, FramebufferAttachment.DepthStencilAttachment, handle, 0); + return FramebufferAttachment.DepthStencilAttachment; } else if (IsDepthOnly(format)) { - GL.FramebufferTexture(target, FramebufferAttachment.DepthAttachment, handle, 0); + return FramebufferAttachment.DepthAttachment; } else if (format == Format.S8Uint) { - GL.FramebufferTexture(target, FramebufferAttachment.StencilAttachment, handle, 0); + return FramebufferAttachment.StencilAttachment; } else { - GL.FramebufferTexture(target, FramebufferAttachment.ColorAttachment0, handle, 0); + return FramebufferAttachment.ColorAttachment0; } } + private static void Attach(FramebufferTarget target, Format format, int handle, int level = 0) + { + FramebufferAttachment attachment = AttachmentForFormat(format); + + GL.FramebufferTexture(target, attachment, handle, level); + } + + private static void Attach(FramebufferTarget target, Format format, int handle, int level, int layer) + { + FramebufferAttachment attachment = AttachmentForFormat(format); + + GL.FramebufferTextureLayer(target, attachment, handle, level, layer); + } + private static ClearBufferMask GetMask(Format format) { if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint) |