Пример #1
0
        public static BitmapTextureInteropDefinition CreateBitmapTextureInteropDefinition(DDSHeader header)
        {
            var result = new BitmapTextureInteropDefinition
            {
                Width       = (short)header.Width,
                Height      = (short)header.Height,
                Depth       = (byte)Math.Max(1, header.Depth),
                MipmapCount = (byte)Math.Max(1, header.MipMapCount),
                HighResInSecondaryResource = 0,
            };

            result.BitmapType = BitmapDdsFormatDetection.DetectType(header);
            result.Format     = BitmapDdsFormatDetection.DetectFormat(header);
            result.D3DFormat  = (int)header.PixelFormat.FourCC;

            result.Curve = BitmapImageCurve.xRGB; // find a way to properly determine that

            if (IsCompressedFormat(result.Format))
            {
                result.Flags |= BitmapFlags.Compressed;
            }

            if (IsPowerOfTwo(header.Width) && IsPowerOfTwo(header.Height))
            {
                result.Flags |= BitmapFlags.PowerOfTwoDimensions;
            }

            return(result);
        }
Пример #2
0
 public XboxBitmap(BitmapTextureInteropDefinition definition, Bitmap.Image image) : base(definition, image)
 {
     UpdateFormat(image.Format);
     MultipleOfBlockDimension = Width % BlockDimension == 0 && Height % BlockDimension == 0;
     NotExact = Width != VirtualWidth || Height != VirtualHeight;
     InTile   = Width <= MinimalBitmapSize / 2 && Height <= MinimalBitmapSize / 2;
     Offset   = 0;
 }
Пример #3
0
 public BaseBitmap(BitmapTextureInteropDefinition definition, Bitmap.Image image)
 {
     Height       = definition.Height;
     Width        = definition.Width;
     Depth        = definition.Depth;
     MipMapCount  = definition.MipmapCount != 0 ? definition.MipmapCount - 1 : 0;
     Type         = definition.BitmapType;
     Flags        = image.Flags;
     Curve        = image.Curve;
     MipMapOffset = image.MipMapOffset;
     UpdateFormat(image.Format);
 }
Пример #4
0
        public static BitmapTextureInteropDefinition CreateBitmapTextureInteropDefinition(BaseBitmap bitmap)
        {
            var result = new BitmapTextureInteropDefinition
            {
                Width       = (short)bitmap.Width,
                Height      = (short)bitmap.Height,
                Depth       = (byte)bitmap.Depth,
                MipmapCount = (byte)(bitmap.MipMapCount + 1),
                HighResInSecondaryResource = 0,
            };

            result.BitmapType = bitmap.Type;
            result.Format     = bitmap.Format;

            switch (result.Format)
            {
            case BitmapFormat.Dxt1:
                result.D3DFormat = (int)D3DFormat.D3DFMT_DXT1;
                result.Flags    |= BitmapFlags.Compressed;
                break;

            case BitmapFormat.Dxt3:
                result.D3DFormat = (int)D3DFormat.D3DFMT_DXT3;
                result.Flags    |= BitmapFlags.Compressed;
                break;

            case BitmapFormat.Dxt5:
                result.D3DFormat = (int)D3DFormat.D3DFMT_DXT5;
                result.Flags    |= BitmapFlags.Compressed;
                break;

            case BitmapFormat.Dxn:
                result.D3DFormat = (int)D3DFormat.D3DFMT_ATI2;
                result.Flags    |= BitmapFlags.Compressed;
                break;

            default:
                result.D3DFormat = (int)D3DFormat.D3DFMT_UNKNOWN;
                break;
            }

            result.Curve = bitmap.Curve;

            if (IsPowerOfTwo(bitmap.Width) && IsPowerOfTwo(bitmap.Height))
            {
                result.Flags |= BitmapFlags.PowerOfTwoDimensions;
            }

            return(result);
        }
Пример #5
0
        public static Bitmap.Image CreateBitmapImageFromResourceDefinition(BitmapTextureInteropDefinition definition)
        {
            var result = new Bitmap.Image()
            {
                Signature   = "mtib",
                Width       = definition.Width,
                Height      = definition.Height,
                Depth       = (sbyte)definition.Depth,
                Format      = definition.Format,
                Type        = definition.BitmapType,
                MipmapCount = (sbyte)(definition.MipmapCount != 0 ? definition.MipmapCount - 1 : 0),
                Flags       = definition.Flags,
                Curve       = definition.Curve
            };

            return(result);
        }
Пример #6
0
        public static uint GetXboxBitmapD3DTextureType(BitmapTextureInteropDefinition bitmapResource)
        {
            switch (bitmapResource.BitmapType)
            {
            case BitmapType.Texture2D:
            case BitmapType.Array:
                return(1);

            case BitmapType.Texture3D:
                return(2);

            case BitmapType.CubeMap:
                return(3);

            default:
                throw new NotSupportedException();
            }
        }
Пример #7
0
        private static BaseBitmap ConvertGen3Bitmap(byte[] primaryData, byte[] secondaryData, BitmapTextureInteropDefinition definition, Bitmap bitmap, int imageIndex, bool isPaired, int pairIndex, BitmapTextureInteropDefinition otherDefinition, bool forDDS)
        {
            if (primaryData == null && secondaryData == null)
            {
                return(null);
            }

            using (var result = new MemoryStream())
            {
                int mipLevelCount = definition.MipmapCount;
                int layerCount    = definition.BitmapType == BitmapType.CubeMap ? 6 : definition.Depth;

                if (definition.BitmapType == BitmapType.Array && mipLevelCount > 1)
                {
                    mipLevelCount          = 1;
                    definition.MipmapCount = 1;
                }

                if (!forDDS)
                {
                    // order for d3d9, all faces first, then mipmaps
                    for (int mipLevel = 0; mipLevel < mipLevelCount; mipLevel++)
                    {
                        for (int layerIndex = 0; layerIndex < layerCount; layerIndex++)
                        {
                            if (definition.BitmapType == BitmapType.CubeMap) // swap cubemap faces
                            {
                                if (layerIndex == 2)
                                {
                                    layerIndex = 3;
                                }
                                else if (layerIndex == 3)
                                {
                                    layerIndex = 2;
                                }
                            }

                            ConvertGen3BitmapData(result, primaryData, secondaryData, definition, bitmap, imageIndex, mipLevel, layerIndex, isPaired, pairIndex, otherDefinition);

                            if (definition.BitmapType == BitmapType.CubeMap)
                            {
                                if (layerIndex == 3)
                                {
                                    layerIndex = 2;
                                }
                                else if (layerIndex == 2)
                                {
                                    layerIndex = 3;
                                }
                            }
                        }
                    }
                }
                else
                {
                    for (int layerIndex = 0; layerIndex < layerCount; layerIndex++)
                    {
                        if (definition.BitmapType == BitmapType.CubeMap) // swap cubemap faces
                        {
                            if (layerIndex == 2)
                            {
                                layerIndex = 3;
                            }
                            else if (layerIndex == 3)
                            {
                                layerIndex = 2;
                            }
                        }

                        for (int mipLevel = 0; mipLevel < mipLevelCount; mipLevel++)
                        {
                            ConvertGen3BitmapData(result, primaryData, secondaryData, definition, bitmap, imageIndex, mipLevel, layerIndex, isPaired, pairIndex, otherDefinition);
                        }

                        if (definition.BitmapType == BitmapType.CubeMap)
                        {
                            if (layerIndex == 3)
                            {
                                layerIndex = 2;
                            }
                            else if (layerIndex == 2)
                            {
                                layerIndex = 3;
                            }
                        }
                    }
                }

                var resultData = result.ToArray();

                BaseBitmap resultBitmap = new BaseBitmap(bitmap.Images[imageIndex]);


                var newFormat = BitmapUtils.GetEquivalentBitmapFormat(bitmap.Images[imageIndex].Format);
                resultBitmap.UpdateFormat(newFormat);

                if (BitmapUtils.RequiresDecompression(resultBitmap.Format, (uint)resultBitmap.Width, (uint)resultBitmap.Height))
                {
                    resultBitmap.Format = BitmapFormat.A8R8G8B8;
                }

                if (!BitmapUtils.IsCompressedFormat(resultBitmap.Format))
                {
                    resultBitmap.Flags &= ~BitmapFlags.Compressed;
                }
                else
                {
                    resultBitmap.Flags |= BitmapFlags.Compressed;
                }

                //
                // Update resource definition/image, truncate DXN to level 4x4
                //

                resultBitmap.Data = resultData;

                if (resultBitmap.Format == BitmapFormat.Dxn) // wouldn't be required if d3d9 supported non power of two DXN and with mips less than 8x8
                {
                    GenerateCompressedMipMaps(resultBitmap);
                }


                if (resultBitmap.Type == BitmapType.Array) // for HO, arrays use the index of Texture3D
                {
                    resultBitmap.Type = BitmapType.Texture3D;
                }

                return(resultBitmap);
            }
        }
Пример #8
0
        private static void ConvertGen3BitmapData(Stream resultStream, byte[] primaryData, byte[] secondaryData, BitmapTextureInteropDefinition definition, Bitmap bitmap, int imageIndex, int level, int layerIndex, bool isPaired, int pairIndex, BitmapTextureInteropDefinition otherDefinition)
        {
            byte[] data;
            uint   levelOffset;

            var d3dFormat = definition.D3DFormat;
            var isTiled   = Direct3D.D3D9x.D3D.IsTiled(d3dFormat);

            uint blockWidth;
            uint blockHeight;

            uint alignedWidth  = (uint)definition.Width >> level;
            uint alignedHeight = (uint)definition.Height >> level;

            if (alignedWidth < 1)
            {
                alignedWidth = 1;
            }
            if (alignedHeight < 1)
            {
                alignedHeight = 1;
            }

            uint alignedDepth = definition.Depth;
            var  gpuFormat    = XboxGraphics.XGGetGpuFormat(d3dFormat);
            uint bitsPerPixel = XboxGraphics.XGBitsPerPixelFromGpuFormat(gpuFormat);

            XboxGraphics.XGGetBlockDimensions(gpuFormat, out blockWidth, out blockHeight);
            XboxGraphics.XGPOINT point = new XboxGraphics.XGPOINT();
            if (definition.MipmapCount > 1)
            {
                XboxGraphics.GetMipTailLevelOffsetCoords((uint)definition.Width, (uint)definition.Height, definition.Depth, (uint)level, gpuFormat, false, false, point);
            }

            var textureType = BitmapUtils.GetXboxBitmapD3DTextureType(definition);

            Direct3D.D3D9x.D3D.AlignTextureDimensions(ref alignedWidth, ref alignedHeight, ref alignedDepth, bitsPerPixel, gpuFormat, textureType, isTiled);

            if (level > 0)
            {
                // align to next power of two
                if (!Direct3D.D3D9x.D3D.IsPowerOfTwo((int)alignedWidth))
                {
                    alignedWidth = Direct3D.D3D9x.D3D.Log2Ceiling((int)alignedWidth);
                    if (alignedWidth < 0)
                    {
                        alignedWidth = 0;
                    }
                    alignedWidth = 1u << (int)alignedWidth;
                }

                if (!Direct3D.D3D9x.D3D.IsPowerOfTwo((int)alignedHeight))
                {
                    alignedHeight = Direct3D.D3D9x.D3D.Log2Ceiling((int)alignedHeight);
                    if (alignedHeight < 0)
                    {
                        alignedHeight = 0;
                    }
                    alignedHeight = 1u << (int)alignedHeight;
                }
            }

            // hacks when the point is outside of the first aligned texture, compute how many tiles you need and extract them (non-square only)
            if (point.X >= 32)
            {
                alignedWidth *= (uint)(1 + point.X / 32);
            }
            if (point.Y >= 32)
            {
                alignedHeight *= (uint)(1 + point.Y / 32);
            }

            uint texelPitch = blockWidth * blockHeight * bitsPerPixel / 8;
            uint size       = alignedWidth * alignedHeight * bitsPerPixel / 8;

            // documentation says that each packed mip level should be aligned to 4KB, required to make untiling work smoothly
            size = (uint)((size + 0xFFF) & ~0xFFF);

            int tileOffset = 0;

            if (!isPaired)
            {
                bool useHighResBuffer = definition.HighResInSecondaryResource > 0;
                if ((level == 0 && useHighResBuffer) || primaryData == null)
                {
                    levelOffset = BitmapUtils.GetXboxBitmapLevelOffset(definition, layerIndex, level);
                    uint alignedSecondaryLength = (uint)((secondaryData.Length + 0x3FFF) & ~0x3FFF);
                    data = new byte[alignedSecondaryLength];
                    Array.Copy(secondaryData, 0, data, 0, secondaryData.Length);
                }
                else
                {
                    levelOffset = BitmapUtils.GetXboxBitmapLevelOffset(definition, layerIndex, level, useHighResBuffer);
                    uint alignedPrimaryLength = (uint)((primaryData.Length + 0x3FFF) & ~0x3FFF);
                    data = new byte[alignedPrimaryLength];
                    Array.Copy(primaryData, 0, data, 0, primaryData.Length);
                }
            }
            else
            {
                bool useHighResBuffer = definition.HighResInSecondaryResource > 0;
                var  bitmap1          = pairIndex == 0 ? definition : otherDefinition;
                var  bitmap2          = pairIndex == 0 ? otherDefinition : definition;

                if (level == 0 && useHighResBuffer)
                {
                    levelOffset = BitmapUtils.GetXboxInterleavedBitmapOffset(bitmap1, bitmap2, layerIndex, level, pairIndex);
                    uint alignedSecondaryLength = (uint)((secondaryData.Length + 0x3FFF) & ~0x3FFF);
                    data = new byte[alignedSecondaryLength];
                    Array.Copy(secondaryData, 0, data, 0, secondaryData.Length);
                }
                else
                {
                    levelOffset = BitmapUtils.GetXboxInterleavedBitmapOffset(bitmap1, bitmap2, layerIndex, level, pairIndex, useHighResBuffer);
                    uint alignedPrimaryLength = (uint)((primaryData.Length + 0x3FFF) & ~0x3FFF);
                    data = new byte[alignedPrimaryLength];
                    Array.Copy(primaryData, 0, data, 0, primaryData.Length);
                }
            }

            tileOffset += (int)levelOffset;

            byte[] tempResult = new byte[size];

            // check if data has enough memory for the requested, size, sometimes it does not (truncated to save memory)
            uint copySize = size;

            if (size + tileOffset >= data.Length)
            {
                copySize = (uint)(data.Length - tileOffset);
            }

            Array.Copy(data, tileOffset, tempResult, 0, copySize);
            data = tempResult;

            uint nBlockWidth;
            uint nBlockHeight;

            if (isTiled)
            {
                //
                // Untile texture
                //

                byte[] result = new byte[size];

                nBlockWidth  = alignedWidth / blockWidth;
                nBlockHeight = alignedHeight / blockHeight;
                for (int i = 0; i < nBlockHeight; i++)
                {
                    for (int j = 0; j < nBlockWidth; j++)
                    {
                        int  destinationIndex  = (int)(i * nBlockWidth + j);                                                     // offset in terms block
                        int  destinationOffset = (int)(destinationIndex * texelPitch);
                        uint tiledIndex        = XboxGraphics.XGAddress2DTiledOffset((uint)j, (uint)i, nBlockWidth, texelPitch); // returns offset in terms of block
                        uint tiledOffset       = tiledIndex * texelPitch;
                        Array.Copy(data, tiledOffset, result, destinationOffset, texelPitch);
                    }
                }
                data = result;
            }

            // find level size aligned to block size

            int levelWidth  = definition.Width >> level;
            int levelHeight = definition.Height >> level;

            if (levelWidth < 1)
            {
                levelWidth = 1;
            }
            if (levelHeight < 1)
            {
                levelHeight = 1;
            }

            if (levelWidth % blockWidth != 0)
            {
                levelWidth = (int)(levelWidth + blockWidth - levelWidth % blockWidth);
            }

            if (levelHeight % blockHeight != 0)
            {
                levelHeight = (int)(levelHeight + blockHeight - levelHeight % blockHeight);
            }

            byte[] finalData = new byte[levelWidth * levelHeight * bitsPerPixel >> 3];

            nBlockWidth  = (uint)(levelWidth / blockWidth);
            nBlockHeight = (uint)(levelHeight / blockHeight);

            uint sliceBlockWidth = alignedWidth / blockWidth;

            // skip these loops if the bitmap is already the proper format
            if (point.X != 0 || point.Y != 0 || finalData.Length != data.Length)
            {
                for (int i = 0; i < nBlockHeight; i++)
                {
                    for (int j = 0; j < nBlockWidth; j++)
                    {
                        uint offset     = (uint)(((i + point.Y) * sliceBlockWidth) + j + point.X) * texelPitch;
                        uint destOffset = (uint)((i * nBlockWidth) + j) * texelPitch;
                        Array.Copy(data, offset, finalData, destOffset, texelPitch);
                    }
                }
            }
            else
            {
                Array.Copy(data, 0, finalData, 0, data.Length);
            }

            XboxGraphics.XGEndianSwapSurface(d3dFormat, finalData);

            uint actualWidth  = (uint)definition.Width >> level;
            uint actualHeight = (uint)definition.Height >> level;

            if (actualWidth < 1)
            {
                actualWidth = 1;
            }
            if (actualHeight < 1)
            {
                actualHeight = 1;
            }
            bool requireDecompression = BitmapUtils.RequiresDecompression(BitmapUtils.GetEquivalentBitmapFormat(bitmap.Images[imageIndex].Format), (uint)definition.Width, (uint)definition.Height);

            finalData = BitmapUtils.ConvertXboxFormats(finalData, actualWidth, actualHeight, bitmap.Images[imageIndex].Format, requireDecompression);

            resultStream.Write(finalData, 0, finalData.Length);
        }
Пример #9
0
 public DDSHeader(BitmapTextureInteropDefinition definition)
 {
     CreateHeaderFromType(definition.Height, definition.Width, definition.Depth, definition.MipmapCount, definition.Format, definition.BitmapType);
 }
Пример #10
0
        public static uint GetXboxBitmapLevelOffset(BitmapTextureInteropDefinition bitmapResource, int ArrayIndex, int Level, bool hasHighResData = false)
        {
            uint blockWidth, blockHeight;
            uint layerSize;
            uint offset = 0;
            uint levelSizeBytes;

            uint unknownType  = GetXboxBitmapD3DTextureType(bitmapResource);
            var  format       = XboxGraphics.XGGetGpuFormat(bitmapResource.D3DFormat);
            uint bitsPerPixel = XboxGraphics.XGBitsPerPixelFromGpuFormat(format);
            bool isTiled      = Direct3D.D3D9x.D3D.IsTiled(bitmapResource.D3DFormat);

            XboxGraphics.XGGetBlockDimensions(format, out blockWidth, out blockHeight);

            int levels = bitmapResource.MipmapCount == 0 ? Direct3D.D3D9x.D3D.GetMaxMipLevels(bitmapResource.Width, bitmapResource.Height, bitmapResource.Depth, 0) : bitmapResource.MipmapCount;

            bool isPacked = levels > 1;

            uint width  = (uint)bitmapResource.Width;
            uint height = (uint)bitmapResource.Height;
            uint depth  = (uint)bitmapResource.Depth;

            uint levelWidth  = width;
            uint levelHeight = height;
            uint levelDepth  = depth;

            if (Level > 0 || (isPacked && (levelWidth <= 16 || levelHeight <= 16)))
            {
                uint arrayStride = 1;
                if (bitmapResource.BitmapType == BitmapType.CubeMap || bitmapResource.BitmapType == BitmapType.Array)
                {
                    int  arrayFactor = bitmapResource.BitmapType == BitmapType.Array ? 2 : 0;
                    uint actualDepth = (uint)(bitmapResource.BitmapType == BitmapType.CubeMap ? 6 : bitmapResource.Depth);
                    arrayStride = Direct3D.D3D9x.D3D.NextMultipleOf(actualDepth, 1u << arrayFactor);
                }

                uint alignedWidth  = 0;
                uint alignedHeight = 0;
                uint alignedDepth  = 0;

                for (int i = 0; i < Level; i++)
                {
                    levelWidth  = width >> i;
                    levelHeight = height >> i;

                    if (levelWidth < 1)
                    {
                        levelWidth = 1;
                    }
                    if (levelHeight < 1)
                    {
                        levelHeight = 1;
                    }

                    alignedDepth  = levelDepth;
                    alignedWidth  = levelWidth;
                    alignedHeight = levelHeight;

                    Direct3D.D3D9x.D3D.AlignTextureDimensions(ref alignedWidth, ref alignedHeight, ref alignedDepth, bitsPerPixel, format, unknownType, isTiled);

                    // if not first mip level, align to next power of two
                    if (i > 0)
                    {
                        if (!Direct3D.D3D9x.D3D.IsPowerOfTwo((int)alignedWidth))
                        {
                            alignedWidth = Direct3D.D3D9x.D3D.Log2Ceiling((int)alignedWidth);
                            if (alignedWidth < 0)
                            {
                                alignedWidth = 0;
                            }
                            alignedWidth = 1u << (int)alignedWidth;
                        }

                        if (!Direct3D.D3D9x.D3D.IsPowerOfTwo((int)alignedHeight))
                        {
                            alignedHeight = Direct3D.D3D9x.D3D.Log2Ceiling((int)alignedHeight);
                            if (alignedHeight < 0)
                            {
                                alignedHeight = 0;
                            }
                            alignedHeight = 1u << (int)alignedHeight;
                        }
                    }

                    layerSize = (bitsPerPixel * alignedWidth * alignedHeight) / 8;

                    // if the bitmap uses the high resolution buffer, the first level is stored there so no need to add it to the running offset
                    if (hasHighResData && i == 0)
                    {
                        if (Level == 1)
                        {
                            levelWidth  = width >> 1;
                            levelHeight = height >> 1;

                            if (levelWidth < 1)
                            {
                                levelWidth = 1;
                            }
                            if (levelHeight < 1)
                            {
                                levelHeight = 1;
                            }

                            alignedDepth  = levelDepth;
                            alignedWidth  = levelWidth;
                            alignedHeight = levelHeight;

                            Direct3D.D3D9x.D3D.AlignTextureDimensions(ref alignedWidth, ref alignedHeight, ref alignedDepth, bitsPerPixel, format, unknownType, isTiled);
                        }
                        continue;
                    }


                    if ((levelWidth <= 16 || levelHeight <= 16) && isPacked)
                    {
                        break;
                    }
                    else
                    {
                        if (unknownType == 2)
                        {
                            levelSizeBytes = Direct3D.D3D9x.D3D.NextMultipleOf(alignedDepth * layerSize, 0x1000);
                        }
                        else
                        {
                            levelSizeBytes = alignedDepth * Direct3D.D3D9x.D3D.NextMultipleOf(layerSize, 0x1000);
                        }

                        offset += arrayStride * levelSizeBytes;
                    }
                }
                // when array index is > 0, we need to add an offset into the right array layer, outside of the loop since the loop computes the offset for all layers
                if (ArrayIndex > 0)
                {
                    alignedDepth  = depth;
                    alignedWidth  = width >> Level;
                    alignedHeight = height >> Level;

                    if (alignedWidth < 1)
                    {
                        alignedWidth = 1;
                    }
                    if (alignedHeight < 1)
                    {
                        alignedHeight = 1;
                    }

                    Direct3D.D3D9x.D3D.AlignTextureDimensions(ref alignedWidth, ref alignedHeight, ref alignedDepth, bitsPerPixel, format, unknownType, isTiled);

                    // if not first mip level, align to next power of two
                    if (Level > 0)
                    {
                        if (!Direct3D.D3D9x.D3D.IsPowerOfTwo((int)alignedWidth))
                        {
                            alignedWidth = Direct3D.D3D9x.D3D.Log2Ceiling((int)alignedWidth);
                            if (alignedWidth < 0)
                            {
                                alignedWidth = 0;
                            }
                            alignedWidth = 1u << (int)alignedWidth;
                        }

                        if (!Direct3D.D3D9x.D3D.IsPowerOfTwo((int)alignedHeight))
                        {
                            alignedHeight = Direct3D.D3D9x.D3D.Log2Ceiling((int)alignedHeight);
                            if (alignedHeight < 0)
                            {
                                alignedHeight = 0;
                            }
                            alignedHeight = 1u << (int)alignedHeight;
                        }
                    }

                    uint size          = alignedWidth * alignedHeight * bitsPerPixel / 8;
                    uint nextLevelSize = Direct3D.D3D9x.D3D.NextMultipleOf(size, 0x1000);
                    offset += (uint)(ArrayIndex * nextLevelSize);
                }
            }
            else
            {
                levelWidth  = width;
                levelHeight = height;
                levelDepth  = depth;

                Direct3D.D3D9x.D3D.AlignTextureDimensions(
                    ref levelWidth, ref levelHeight, ref levelDepth, bitsPerPixel, format, unknownType, isTiled);

                if (!isTiled &&
                    !(bitmapResource.BitmapType == BitmapType.Array) &&
                    !(isPacked) &&
                    unknownType == 1 &&
                    bitmapResource.MipmapCount < 1)
                {
                    levelHeight = Direct3D.D3D9x.D3D.NextMultipleOf(height, blockHeight);
                }

                layerSize = (bitsPerPixel * levelWidth * levelHeight) >> 3;

                levelSizeBytes = Direct3D.D3D9x.D3D.NextMultipleOf(layerSize, 0x1000);
                offset        += levelSizeBytes * (uint)ArrayIndex;
            }

            return(offset);
        }
Пример #11
0
        public static uint GetXboxInterleavedBitmapOffset(BitmapTextureInteropDefinition bitmap1, BitmapTextureInteropDefinition bitmap2, int arrayIndex, int level, int currentBitmapIndex, bool hasHighResData = false)
        {
            /*
             * Block size, bits per pixel, tiling and formats are the same, also texture must be square.
             */

            uint offset = 0;

            var  format       = XboxGraphics.XGGetGpuFormat(bitmap1.D3DFormat);
            uint bitsPerPixel = XboxGraphics.XGBitsPerPixelFromGpuFormat(format);
            bool isTiled      = Direct3D.D3D9x.D3D.IsTiled(bitmap1.D3DFormat);

            XboxGraphics.XGGetBlockDimensions(format, out uint blockWidth, out blockWidth);
            BitmapTextureInteropDefinition currentBitmap = currentBitmapIndex == 0 ? bitmap1 : bitmap2;
            BitmapTextureInteropDefinition otherBitmap   = currentBitmapIndex == 0 ? bitmap2 : bitmap1;

            uint dimension      = (uint)currentBitmap.Width;
            uint depth          = (uint)currentBitmap.Depth;
            uint levelDimension = dimension;
            uint levelDepth     = depth;
            uint tileSize       = (blockWidth * blockWidth * 32 * 32 * bitsPerPixel) >> 3;

            uint arrayStride = 1;

            if (currentBitmap.BitmapType == BitmapType.CubeMap || currentBitmap.BitmapType == BitmapType.Array)
            {
                int  arrayFactor = currentBitmap.BitmapType == BitmapType.Array ? 2 : 0;
                uint actualDepth = (uint)(currentBitmap.BitmapType == BitmapType.CubeMap ? 6 : currentBitmap.Depth);
                arrayStride = Direct3D.D3D9x.D3D.NextMultipleOf(actualDepth, 1u << arrayFactor);
            }

            // assume power of two for now

            bool useInterleavedOffset;

            if (currentBitmap.Width == otherBitmap.Width)
            {
                useInterleavedOffset = currentBitmapIndex != 0;
            }
            else
            {
                useInterleavedOffset = currentBitmap.Width < otherBitmap.Width;
            }

            if (useInterleavedOffset)
            {
                if ((levelDimension >> level) <= 64)
                {
                    offset += tileSize / 2;
                }
            }

            if (bitmap1.Width > bitmap2.Width)
            {
                if (useInterleavedOffset)
                {
                    // compute used data from the other image
                    if (currentBitmap.HighResInSecondaryResource > 0)
                    {
                        if (level == 0)
                        {
                            offset += (uint)(arrayStride * otherBitmap.Width * otherBitmap.Width * bitsPerPixel) / 8;
                        }
                    }

                    if (currentBitmap.Width >> level <= 64)
                    {
                        // compute first level that can fit mips
                        int  lowerBound  = currentBitmap.Width > 16 ? 64 : 16;
                        int  targetLevel = 0;
                        uint tempWidth   = (uint)bitmap1.Width;
                        do
                        {
                            targetLevel++;
                            tempWidth >>= 1;
                            if (tempWidth < 1)
                            {
                                tempWidth = 1;
                            }
                        }while (tempWidth > lowerBound && targetLevel <= bitmap1.MipmapCount);

                        if (targetLevel > 0)
                        {
                            offset += GetXboxBitmapLevelOffset(bitmap1, 0, targetLevel, bitmap1.HighResInSecondaryResource > 0);
                        }
                    }
                    else
                    {
                        if (bitmap2.Width >> level <= 64)
                        {
                            // compute first level that can fit mips
                            int  targetLevel = 0;
                            uint tempWidth   = (uint)bitmap1.Width;
                            do
                            {
                                targetLevel++;
                                tempWidth >>= 1;
                                if (tempWidth < 1)
                                {
                                    tempWidth = 1;
                                }
                            }while (tempWidth > (bitmap2.Width >> level) && targetLevel <= bitmap1.MipmapCount);

                            if (targetLevel > 0)
                            {
                                offset += GetXboxBitmapLevelOffset(bitmap1, 0, targetLevel, bitmap1.HighResInSecondaryResource > 0);
                            }
                        }
                    }
                }
                else
                {
                    offset = 0;
                }
            }
            else if (bitmap1.Width == bitmap2.Width)
            {
                if (bitmap1.Width > 64 && level == 0 && useInterleavedOffset)
                {
                    offset += arrayStride * tileSize;
                }

                if (bitmap1.Width > 128)
                {
                    throw new Exception("FIX ME");
                }
            }
            else
            {
                if (useInterleavedOffset)
                {
                    // compute used data from the other image
                    if (currentBitmap.HighResInSecondaryResource > 0)
                    {
                        if (level == 0)
                        {
                            offset += (uint)(arrayStride * otherBitmap.Width * otherBitmap.Width * bitsPerPixel) / 8;
                        }
                    }

                    if (currentBitmap.Width >> level <= 64)
                    {
                        // compute first level that can fit mips
                        int  lowerBound  = currentBitmap.Width > 16 ? 64 : 16;
                        int  targetLevel = 0;
                        uint tempWidth   = (uint)bitmap2.Width;
                        do
                        {
                            targetLevel++;
                            tempWidth >>= 1;
                            if (tempWidth < 1)
                            {
                                tempWidth = 1;
                            }
                        }while (tempWidth > lowerBound && targetLevel <= bitmap2.MipmapCount);

                        if (targetLevel > 0)
                        {
                            offset += GetXboxBitmapLevelOffset(bitmap2, 0, targetLevel, bitmap2.HighResInSecondaryResource > 0);
                        }
                    }
                    else
                    {
                        if (bitmap1.Width >> level <= 64)
                        {
                            // compute first level that can fit mips
                            int  targetLevel = 0;
                            uint tempWidth   = (uint)bitmap2.Width;
                            do
                            {
                                targetLevel++;
                                tempWidth >>= 1;
                                if (tempWidth < 1)
                                {
                                    tempWidth = 1;
                                }
                            }while (tempWidth > (bitmap1.Width >> level) && targetLevel <= bitmap2.MipmapCount);

                            if (targetLevel > 0)
                            {
                                offset += GetXboxBitmapLevelOffset(bitmap2, 0, targetLevel, bitmap2.HighResInSecondaryResource > 0);
                            }
                        }
                    }
                }
                else
                {
                    offset = 0;
                }
            }

            offset += GetXboxBitmapLevelOffset(currentBitmap, arrayIndex, level, hasHighResData);

            return(offset);
        }