Ryujinx/Ryujinx.Graphics.OpenGL/TextureCopyUnscaled.cs
2020-01-09 02:13:00 +01:00

86 lines
2.8 KiB
C#

using Ryujinx.Common;
using Ryujinx.Graphics.GAL.Texture;
using OpenTK.Graphics.OpenGL;
using System;
namespace Ryujinx.Graphics.OpenGL
{
static class TextureCopyUnscaled
{
public static void Copy(TextureView src, TextureView dst, int dstLayer, int dstLevel)
{
int srcWidth = src.Width;
int srcHeight = src.Height;
int srcDepth = src.DepthOrLayers;
int srcLevels = src.Levels;
srcWidth = Math.Max(1, srcWidth >> dstLevel);
srcHeight = Math.Max(1, srcHeight >> dstLevel);
if (src.Target == Target.Texture3D)
{
srcDepth = Math.Max(1, srcDepth >> dstLevel);
}
int dstWidth = dst.Width;
int dstHeight = dst.Height;
int dstDepth = dst.DepthOrLayers;
int dstLevels = dst.Levels;
// When copying from a compressed to a non-compressed format,
// the non-compressed texture will have the size of the texture
// in blocks (not in texels), so we must adjust that size to
// match the size in texels of the compressed texture.
if (!src.IsCompressed && dst.IsCompressed)
{
dstWidth = BitUtils.DivRoundUp(dstWidth, dst.BlockWidth);
dstHeight = BitUtils.DivRoundUp(dstHeight, dst.BlockHeight);
}
else if (src.IsCompressed && !dst.IsCompressed)
{
dstWidth *= dst.BlockWidth;
dstHeight *= dst.BlockHeight;
}
int width = Math.Min(srcWidth, dstWidth);
int height = Math.Min(srcHeight, dstHeight);
int depth = Math.Min(srcDepth, dstDepth);
int levels = Math.Min(srcLevels, dstLevels);
for (int level = 0; level < levels; level++)
{
// Stop copy if we are already out of the levels range.
if (level >= src.Levels || dstLevel + level >= dst.Levels)
{
break;
}
GL.CopyImageSubData(
src.Handle,
src.Target.ConvertToImageTarget(),
level,
0,
0,
0,
dst.Handle,
dst.Target.ConvertToImageTarget(),
dstLevel + level,
0,
0,
dstLayer,
width,
height,
depth);
width = Math.Max(1, width >> 1);
height = Math.Max(1, height >> 1);
if (src.Target == Target.Texture3D)
{
depth = Math.Max(1, depth >> 1);
}
}
}
}
}