Example #1
0
        public override byte[] GetImageData(int ArrayLevel = 0, int MipLevel = 0)
        {
            if (!IsSwizzled)
            {
                return(ImageData);
            }

            int  target    = 1;
            uint bpp       = GetBytesPerPixel(Format);
            uint blkWidth  = GetBlockWidth(Format);
            uint blkHeight = GetBlockHeight(Format);
            uint blkDepth  = GetBlockDepth(Format);

            uint blockHeight     = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(Height, blkHeight));
            uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;

            uint Pitch         = 0;
            uint DataAlignment = 512;
            uint TileMode      = 0;

            int linesPerBlockHeight = (1 << (int)BlockHeightLog2) * 8;

            uint ArrayCount = (uint)mipSizes.Count;

            uint ArrayOffset = 0;

            for (int arrayLevel = 0; arrayLevel < ArrayCount; arrayLevel++)
            {
                uint SurfaceSize      = 0;
                int  blockHeightShift = 0;

                List <uint> MipOffsets = new List <uint>();

                for (int mipLevel = 0; mipLevel < mipSizes[arrayLevel].Length; mipLevel++)
                {
                    uint width  = (uint)Math.Max(1, Width >> mipLevel);
                    uint height = (uint)Math.Max(1, Height >> mipLevel);
                    uint depth  = (uint)Math.Max(1, Depth >> mipLevel);

                    uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;

                    if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
                    {
                        blockHeightShift += 1;
                    }


                    uint width__  = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth);
                    uint height__ = TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight);

                    //Calculate the mip size instead
                    byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, DataAlignment) - SurfaceSize)];
                    SurfaceSize += (uint)AlignedData.Length;
                    MipOffsets.Add(SurfaceSize);

                    //Get the first mip offset and current one and the total image size
                    int msize = (int)((MipOffsets[0] + ImageData.Length - MipOffsets[mipLevel]) / ArrayCount);

                    byte[] data_ = Utils.SubArray(ImageData, ArrayOffset + MipOffsets[mipLevel], (uint)msize);

                    try
                    {
                        Pitch        = TegraX1Swizzle.round_up(width__ * bpp, 64);
                        SurfaceSize += Pitch * TegraX1Swizzle.round_up(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);

                        Console.WriteLine($"{width} {height} {blkWidth} {blkHeight} {target} {bpp} {TileMode} {(int)Math.Max(0, BlockHeightLog2 - blockHeightShift)} {data_.Length}");
                        byte[] result = TegraX1Swizzle.deswizzle(width, height, depth, blkWidth, blkHeight, blkDepth, target, bpp, TileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), data_);
                        //Create a copy and use that to remove uneeded data
                        byte[] result_ = new byte[size];
                        Array.Copy(result, 0, result_, 0, size);
                        result = null;

                        if (ArrayLevel == arrayLevel && MipLevel == mipLevel)
                        {
                            return(result_);
                        }
                    }
                    catch (Exception e)
                    {
                        System.Windows.Forms.MessageBox.Show($"Failed to swizzle texture {Text}!");
                        Console.WriteLine(e);

                        return(new byte[0]);
                    }
                }

                ArrayOffset += (uint)(ImageData.Length / ArrayCount);
            }
            return(new byte[0]);
        }
        public static List <byte[]> SwizzleSurfaceMipMaps(Texture tex, byte[] data, TileMode TileMode)
        {
            int  blockHeightShift    = 0;
            int  target              = 1;
            uint Pitch               = 0;
            uint SurfaceSize         = 0;
            uint blockHeight         = 0;
            uint blk_dim             = Formats.blk_dims((uint)((int)tex.Format >> 8));
            uint blkWidth            = blk_dim >> 4;
            uint blkHeight           = blk_dim & 0xF;
            uint linesPerBlockHeight = 0;

            uint bpp = Formats.bpps((uint)((int)tex.Format >> 8));

            if ((int)TileMode == 1)
            {
                blockHeight         = 1;
                tex.BlockHeightLog2 = 0;
                tex.Alignment       = 1;

                linesPerBlockHeight   = 1;
                tex.ReadTextureLayout = 0;
            }
            else
            {
                blockHeight         = TegraX1Swizzle.GetBlockHeight(DIV_ROUND_UP(tex.Height, blkHeight));
                tex.BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
                Console.WriteLine("BlockHeightLog2 " + tex.BlockHeightLog2);
                Console.WriteLine("blockHeight " + blockHeight);
                tex.Alignment         = 512;
                tex.ReadTextureLayout = 1;

                linesPerBlockHeight = blockHeight * 8;
            }

            List <byte[]> mipmaps = new List <byte[]>();

            for (int mipLevel = 0; mipLevel < tex.MipCount; mipLevel++)
            {
                var  result = GetCurrentMipSize(tex.Width, tex.Height, blkWidth, blkHeight, bpp, mipLevel);
                uint offset = result.Item1;
                uint size   = result.Item2;

                byte[] data_ = SubArray(data, offset, size);

                uint width_  = Math.Max(1, tex.Width >> mipLevel);
                uint height_ = Math.Max(1, tex.Height >> mipLevel);

                uint width__  = DIV_ROUND_UP(width_, blkWidth);
                uint height__ = DIV_ROUND_UP(height_, blkHeight);


                byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, (uint)tex.Alignment) - SurfaceSize)];
                SurfaceSize += (uint)AlignedData.Length;

                Console.WriteLine("SurfaceSize Aligned " + AlignedData);

                Console.WriteLine("MipOffsets " + SurfaceSize);

                tex.MipOffsets[mipLevel] = SurfaceSize;
                if (tex.TileMode == TileMode.LinearAligned)
                {
                    Pitch = width__ * bpp;

                    Console.WriteLine("Pitch 1 " + Pitch);

                    if (target == 1)
                    {
                        Pitch = TegraX1Swizzle.round_up(width__ * bpp, 32);
                        Console.WriteLine("Pitch 2 " + Pitch);
                    }

                    SurfaceSize += Pitch * height__;
                }
                else
                {
                    if (TegraX1Swizzle.pow2_round_up(height__) < linesPerBlockHeight)
                    {
                        blockHeightShift += 1;
                    }

                    Pitch = TegraX1Swizzle.round_up(width__ * bpp, 64);

                    Console.WriteLine("Pitch 1 " + Pitch);
                    Console.WriteLine("blockHeightShift " + blockHeightShift);

                    SurfaceSize += Pitch * TegraX1Swizzle.round_up(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);

                    Console.WriteLine("SurfaceSize " + SurfaceSize);

                    byte[] SwizzledData = TegraX1Swizzle.swizzle(width_, height_, blkWidth, blkHeight, target, bpp, (uint)tex.TileMode, (int)Math.Max(0, tex.BlockHeightLog2 - blockHeightShift), data_);

                    mipmaps.Add(AlignedData.Concat(SwizzledData).ToArray());
                }
            }
            tex.ImageSize = SurfaceSize;

            return(mipmaps);
        }
Example #3
0
        private List <uint[]> GenerateMipSizes(uint SurfaceCount = 1)
        {
            List <uint[]> MipMapSizes = new List <uint[]>();

            uint bpp       = GetBytesPerPixel(Format);
            uint blkWidth  = GetBlockWidth(Format);
            uint blkHeight = GetBlockHeight(Format);
            uint blkDepth  = GetBlockDepth(Format);

            uint blockHeight     = TegraX1Swizzle.GetBlockHeight(TegraX1Swizzle.DIV_ROUND_UP(Height, blkHeight));
            uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;

            uint Pitch         = 0;
            uint DataAlignment = 512;

            int linesPerBlockHeight = (1 << (int)BlockHeightLog2) * 8;

            uint ArrayCount = (uint)mipSizes.Count;

            uint ArrayOffset = 0;

            for (int arrayLevel = 0; arrayLevel < ArrayCount; arrayLevel++)
            {
                uint SurfaceSize      = 0;
                int  blockHeightShift = 0;

                uint[] MipOffsets = new uint[MipCount];

                for (int mipLevel = 0; mipLevel < MipCount; mipLevel++)
                {
                    uint width  = (uint)Math.Max(1, Width >> mipLevel);
                    uint height = (uint)Math.Max(1, Height >> mipLevel);
                    uint depth  = (uint)Math.Max(1, Depth >> mipLevel);

                    uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;

                    if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
                    {
                        blockHeightShift += 1;
                    }

                    uint width__  = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth);
                    uint height__ = TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight);

                    //Calculate the mip size instead
                    byte[] AlignedData = new byte[(TegraX1Swizzle.round_up(SurfaceSize, DataAlignment) - SurfaceSize)];
                    SurfaceSize         += (uint)AlignedData.Length;
                    MipOffsets[mipLevel] = (SurfaceSize);

                    //Get the first mip offset and current one and the total image size
                    int msize = (int)((MipOffsets[0] + ImageData.Length - MipOffsets[mipLevel]) / ArrayCount);

                    Pitch        = TegraX1Swizzle.round_up(width__ * bpp, 64);
                    SurfaceSize += Pitch * TegraX1Swizzle.round_up(height__, Math.Max(1, blockHeight >> blockHeightShift) * 8);
                }
                ArrayOffset += (uint)(ImageData.Length / ArrayCount);

                MipMapSizes.Add(MipOffsets);
            }

            return(MipMapSizes);
        }