aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2020-11-20 20:14:45 +0000
committerGitHub <noreply@github.com>2020-11-20 17:14:45 -0300
commit9493cdfe553d77d8f37927ef2acf87cfbab1c467 (patch)
tree9c5e5b588c1fa9372274d3d780b4cbb041bf24c5 /Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
parentcf7044e37bc628f25525941d25b830594b833428 (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.cs103
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)