示例#1
0
        /// <summary>
        /// Untile surface. The input dimensions must be in terms of blocks.
        /// </summary>
        /// <param name="width">Width of the surface in blocks</param>
        /// <param name="height">Height of the surface in blocks</param>
        /// <param name="rowPitch">Size in bytes of a row of pixels in the destination image</param>
        /// <param name="point">Offset in the surface</param>
        /// <param name="source">Source data</param>
        /// <param name="texelPitch">Size in bytes of a block</param>
        /// <param name="rect">Image rectangle to untile</param>
        /// <returns></returns>
        private static byte[] UntileSurface(uint width, uint height, uint rowPitch, XGPOINT point, byte[] source, uint texelPitch, D3DBOX rect)
        {
            uint nBlocksWidth  = rect.Right - rect.Left;
            uint nBlocksHeight = rect.Bottom - rect.Top;

            uint alignedWidth  = (width + 31) & ~31u;
            uint alignedHeight = (height + 31) & ~31u;

            uint totalSize = AlignToPage(alignedWidth * alignedHeight); // may not be necessary on PC

            byte[] result = new byte[totalSize];

            uint v12    = 16 / texelPitch;
            uint logBpp = XGLog2LE16(texelPitch);                                 // log bytes per pixel
            uint v14    = (~(v12 - 1u) & (rect.Left + v12)) - rect.Left;          //  v12 - (rect.Left) % v12
            uint v42    = (~(v12 - 1u) & (rect.Left + nBlocksWidth)) - rect.Left; // nBlocksWidth - (rect.Left + nBlocksWidth) % v12


            //int x = XGAddress2DTiledX(offset, xChunks, texPitch);
            //int y = XGAddress2DTiledY(offset, xChunks, texPitch);
            //int sourceIndex = ((i * xChunks) * texPitch) + (j * texPitch);
            //int destinationIndex = ((y * xChunks) * texPitch) + (x * texPitch);

            for (uint yBlockIndex = 0; yBlockIndex < nBlocksHeight; yBlockIndex++)
            {
                uint v38          = alignedWidth >> 5;
                uint _y           = yBlockIndex + rect.Top;
                uint v47          = v38 * (_y >> 5);
                uint v44          = (_y >> 4) & 1;
                uint yBlockOffset = (uint)point.Y;
                uint v17          = (_y >> 3) & 1;
                uint v46          = 16 * (_y & 1);
                uint v45          = 2 * v17;
                uint v19          = rect.Left;
                uint v18          = 4 * (_y & 6);
                uint v52          = v17 << (int)(logBpp + 6);
                uint heightOffset = rowPitch * (yBlockIndex + yBlockOffset);

                {
                    uint v30   = rect.Left;
                    uint v31   = (v44 + 2 * ((v45 + (byte)(v19 >> 3)) & 3));
                    uint micro = (v18 + (v30 & 7)) << (int)(logBpp + 6);
                    uint v32   = v46 + v52 + ((micro >> 6) & 0xF) + 2 * (((micro >> 6) & ~0xFu) + (((v47 + (v19 >> 5)) << (int)(logBpp + 6)) & 0x1FFFFFFF));
                    uint v28   = ((v32 >> 6) & 7) + 8 * (v31 & 1);

                    var v37a = v14;
                    if (v37a > nBlocksWidth)
                    {
                        v37a = nBlocksWidth;
                    }

                    uint sourceOffset      = 8 * ((v32 & ~0x1FFu) + 4 * ((v31 & ~1u) + 8 * v28)) + (v32 & 0x3F);
                    uint destinationOffset = heightOffset + ((uint)point.X << (int)logBpp);
                    uint blockSize         = v37a;

                    Array.Copy(source, sourceOffset, result, destinationOffset, blockSize);
                }

                uint x   = v14;
                uint v48 = v14;

                while (x < v42)
                {
                    uint v30 = x + rect.Left;
                    uint v31 = v44 + 2 * ((v45 + (byte)(v30 >> 3)) & 3);
                    uint v25 = (v18 + (v30 & 7)) << (int)(logBpp + 6);
                    uint v32 = v46 + v52 + ((v25 >> 6) & 0xF) + 2 * (((v25 >> 6) & ~0xFu) + (((v47 + (v30 >> 5)) << (int)(logBpp + 6)) & 0x1FFFFFFF));
                    uint v28 = ((v32 >> 6) & 7) + 8 * (v31 & 1);

                    uint sourceOffset      = 8 * ((v32 & ~0x1FFu) + 4 * ((v31 & ~1u) + 8 * v28)) + (v32 & 0x3F);
                    uint destinationOffset = heightOffset + ((v48 + (uint)point.X) << (int)logBpp);
                    uint blockSize         = v12 << (int)logBpp;

                    Array.Copy(source, sourceOffset, result, destinationOffset, blockSize);

                    x += v12;
                }

                if (x < nBlocksWidth)
                {
                    uint v30 = x + rect.Left;
                    uint v31 = v44 + 2 * ((v45 + (byte)(v30 >> 3)) & 3);
                    uint v25 = (v18 + (v30 & 7)) << (int)(logBpp + 6);
                    uint v32 = v46 + v52 + ((v25 >> 6) & 0xF) + 2 * (((v25 >> 6) & ~0xFu) + (((v47 + (v30 >> 5)) << (int)(logBpp + 6)) & 0x1FFFFFFF));
                    uint v28 = ((v32 >> 6) & 7) + 8 * (v31 & 1);

                    uint sourceOffset      = 8 * ((v32 & ~0x1FFu) + 4 * ((v31 & ~1u) + 8 * v28)) + (v32 & 0x3F);
                    uint destinationOffset = heightOffset + ((v48 + (uint)point.X) << (int)logBpp);
                    uint blockSize         = (nBlocksWidth - v48) << (int)logBpp;

                    Array.Copy(source, sourceOffset, result, destinationOffset, blockSize);
                }
            }

            return(result);
        }
示例#2
0
        public static byte[] XGUntileTextureLevel(uint width, uint height, uint level, TextureFormat format, XGTILE flags, uint rowPitch, XGPOINT point, byte[] source, D3DBOX box)
        {
            uint width_as_blocks;
            uint height_as_blocks;
            uint texelPitch;

            uint blockWidth  = 0;
            uint blockHeight = 0;


            XGGetBlockDimensions(format, out blockWidth, out blockHeight);
            int blockLogWidth  = (int)Log2Floor((int)blockWidth);
            int blockLogHeight = (int)Log2Floor((int)blockHeight);
            var bitsPerPixel   = XGBitsPerPixelFromGpuFormat(format);

            texelPitch = (bitsPerPixel << (blockLogWidth + blockLogHeight)) >> 3; // also bytes per block


            int borderSize = flags.HasFlag(XGTILE.XGTILE_BORDER) ? 2 : 0;
            int hasBorder  = flags.HasFlag(XGTILE.XGTILE_BORDER) ? 1 : 0;

            if (level > 0)
            {
                int nextPowerOfTwoWidth  = 1 << (hasBorder - (int)Log2Ceiling((int)(width - borderSize - 1))) >> (int)level;
                int nextPowerOfTwoHeight = 1 << (hasBorder - (int)Log2Ceiling((int)(height - borderSize - 1))) >> (int)level;

                if (nextPowerOfTwoWidth <= 1)
                {
                    nextPowerOfTwoWidth = 1;
                }
                if (nextPowerOfTwoHeight <= 1)
                {
                    nextPowerOfTwoHeight = 1;
                }

                width_as_blocks  = (uint)(nextPowerOfTwoWidth + blockWidth - 1) >> blockLogWidth;
                height_as_blocks = (uint)(nextPowerOfTwoHeight + blockHeight - 1) >> blockLogHeight;
            }
            else
            {
                width_as_blocks  = (width + blockWidth - 1) >> blockLogWidth;
                height_as_blocks = (height + blockHeight - 1) >> blockLogHeight;
            }

            // update point to be in terms of the block width and height
            if (point != null)
            {
                point.X >>= blockLogWidth;
                point.Y >>= blockLogWidth;
            }
            else
            {
                point   = new XGPOINT();
                point.X = 0;
                point.Y = 0;
            }

            // update box bounds to be in terms of the block width and height
            if (box != null)
            {
                box.Left >>= blockLogWidth;
                box.Right  = (box.Right + blockWidth - 1) >> blockLogWidth;
                box.Top  >>= blockLogHeight;
                box.Bottom = (box.Bottom + blockHeight - 1) >> blockLogHeight;
            }
            else
            {
                box      = new D3DBOX();
                box.Left = 0;
                box.Top  = 0;

                var tempWidth = (width - borderSize) >> (int)level;
                if (tempWidth <= 1)
                {
                    tempWidth = 1;
                }
                box.Right = (uint)(tempWidth + blockWidth - 1) >> blockLogWidth;

                var tempHeight = (height - borderSize) >> (int)level;
                if (tempHeight <= 1)
                {
                    tempHeight = 1;
                }
                box.Bottom = (uint)(tempHeight + blockHeight - 1) >> blockLogHeight;
            }

            if (!flags.HasFlag(XGTILE.XGTILE_NONPACKED))
            {
                XGPOINT offset = new XGPOINT();
                // need to understand the return value and modify the byte[]
                var offsetInByteArray = GetMipTailLevelOffsetCoords(width, height, 1, level, format, true, flags.HasFlag(XGTILE.XGTILE_BORDER), offset);

                box.Top    += (uint)offset.Y;
                box.Bottom += (uint)offset.Y;
                box.Left   += (uint)offset.X;
                box.Right  += (uint)offset.X;
            }

            return(UntileSurface(width_as_blocks, height_as_blocks, rowPitch, point, source, texelPitch, box));
        }