示例#1
0
        private KTXError ReadHeader(byte[] headerChunk, out KTXHeader header)
        {
            KTXError errorCode = KTXError.Success;

            header = new KTXHeader();
            header.Populate(headerChunk);
            if (header.Instructions.Result != KTXError.Success)
            {
                return(header.Instructions.Result);
            }
            header.KeyValueData = new byte[header.BytesOfKeyValueData];
            if (header.KeyValueData == null)
            {
                return(KTXError.OutOfMemory);
            }
            return(errorCode);
        }
示例#2
0
        public bool ExtractUInt32(Stream stream, out UInt32 result)
        {
            const int UINT32_NO_OF_BYTES = 4;

            byte[] chunk     = new byte[UINT32_NO_OF_BYTES];
            int    bytesRead = stream.Read(chunk, 0, UINT32_NO_OF_BYTES);

            if (bytesRead != UINT32_NO_OF_BYTES)
            {
                result = 0;
                return(false);
            }
            if (Endianness == KTX_ENDIAN_REF_REV)
            {
                KTXHeader.SwapEndian32(chunk, UINT32_NO_OF_BYTES);
            }
            result = BitConverter.ToUInt32(chunk, 0);
            return(true);
        }
示例#3
0
        static KeyValueArrayData[] GenerateKeyValueArray(KTXHeader destHeader)
        {
            var output = new List <KeyValueArrayData> ();

            int offset = 0;

            do
            {
                var keyValue         = new KeyValueArrayData();
                var keyValueByteSize = destHeader.GetEndian32(destHeader.KeyValueData, ref offset);
                keyValue.Id      = destHeader.GetEndian64(destHeader.KeyValueData, ref offset);
                keyValue.Offsets = new ulong[destHeader.NumberOfMipmapLevels];
                for (int j = 0; j < keyValue.Offsets.Length; ++j)
                {
                    keyValue.Offsets [j] = destHeader.GetEndian64(destHeader.KeyValueData, ref offset);
                }
                output.Add(keyValue);
            }while(offset < destHeader.KeyValueData.Length);

            return(output.ToArray());
        }
示例#4
0
        KTXError ExtractFace(
            Stream src,
            Stream dest,
            KTXHeader header,
            KTXMipmapData mipmap,
            byte[] dataBuffer,
            KTXFaceData[] faces
            )
        {
            mipmap.Common.PixelWidth  = Math.Max(1, header.PixelWidth >> mipmap.Common.Level);
            mipmap.Common.PixelHeight = Math.Max(1, header.PixelHeight >> mipmap.Common.Level);
            mipmap.Common.PixelDepth  = Math.Max(1, header.PixelDepth >> mipmap.Common.Level);

            for (int face = 0; face < header.NumberOfFaces; ++face)
            {
                var bytesRead = src.Read(dataBuffer, 0, mipmap.SizeRounded);
                if (bytesRead != mipmap.SizeRounded)
                {
                    return(KTXError.UnexpectedEndOfFile);
                }

                var bytesToRead = (int)mipmap.Common.Size;

                /* Perform endianness conversion on texture data */
                if (header.RequiresSwap() && header.GlTypeSize == 2)
                {
                    KTXHeader.SwapEndian16(dataBuffer, bytesToRead);
                }
                else if (header.RequiresSwap() && header.GlTypeSize == 4)
                {
                    KTXHeader.SwapEndian32(dataBuffer, bytesToRead);
                }

                mipmap.Common.NumberOfFaces     = (int)header.NumberOfFaces;
                mipmap.ViewType                 = header.Instructions.ViewType;
                mipmap.Common.IsCompressed      = header.Instructions.IsCompressed;
                mipmap.Common.TextureDimensions = header.Instructions.TextureDimensions;
                mipmap.Common.FaceIndex         = face;

                if (header.Instructions.TextureDimensions == 1)
                {
                }
                else if (header.Instructions.TextureDimensions == 2)
                {
                    if (header.NumberOfArrayElements > 0)
                    {
                        mipmap.Common.PixelHeight = header.NumberOfArrayElements;
                    }
                }
                else if (header.Instructions.TextureDimensions == 3)
                {
                    if (header.NumberOfArrayElements > 0)
                    {
                        mipmap.Common.PixelDepth = header.NumberOfArrayElements;
                    }
                }

                faces[face].Mipmaps[mipmap.Common.Level] = new MgImageMipmap
                {
                    // TODO : MAKE SURE IT DOES NOT "EXPLODE" LATER
                    Offset = (uint)dest.Position,
                    Width  = mipmap.Common.PixelWidth,
                    Height = mipmap.Common.PixelHeight,
                    Size   = mipmap.Common.Size,
                };

                dest.Write(dataBuffer, 0, bytesToRead);


                //            // Renderion is returning INVALID_VALUE. Oops!!
                //            if (mETCUnpacker.IsRequired (header.Instructions, mipmap.GLError))
                //{
                //	var result = mETCUnpacker.UnpackCompressedTexture (
                //		header.Instructions,
                //		mipmap.Common.Level,
                //		face,
                //		mipmap.Common.PixelWidth,
                //		mipmap.Common.PixelHeight,
                //		mipmap.Common.Data);

                //	if (result != KTXError.Success)
                //	{
                //		return result;
                //	}

                //	mipmap.GLError = mPlatform.GetError ();
                //}
            }
            return(KTXError.Success);
        }
示例#5
0
        KTXTextureOutput LoadTexture(
            Stream src,
            KTXHeader header)
        {
            // default out values
            KTXError errorCode = KTXError.Success;

            bool isFirstTime     = true;
            int  previousLodSize = 0;

            byte[] data = null;

            var faces = new KTXFaceData[header.NumberOfFaces];

            for (var i = 0; i < faces.Length; ++i)
            {
                faces[i] = new KTXFaceData((uint)i, header.NumberOfMipmapLevels);
            }

            using (var dest = new MemoryStream())
            {
                for (int level = 0; level < header.NumberOfMipmapLevels; ++level)
                {
                    UInt32 faceLodSize;
                    if (!header.ExtractUInt32(src, out faceLodSize))
                    {
                        errorCode = KTXError.InvalidOperation;
                        break;
                    }

                    int faceLodSizeRounded = ((int)faceLodSize + 3) & ~3;

                    // array texture is this correct ?
                    if (isFirstTime)
                    {
                        isFirstTime     = false;
                        previousLodSize = faceLodSizeRounded;

                        /* allocate memory sufficient for the first level */
                        data = new byte[faceLodSizeRounded];
                        if (data == null)
                        {
                            errorCode = KTXError.OutOfMemory;
                            break;
                        }
                    }
                    else
                    {
                        if (previousLodSize < faceLodSizeRounded)
                        {
                            /* subsequent levels cannot be larger than the first level */
                            errorCode = KTXError.InvalidValue;
                            break;
                        }
                    }

                    var mipmap = new KTXMipmapData();
                    mipmap.Common.Level = level;
                    mipmap.Common.Data  = data;
                    mipmap.Common.Size  = faceLodSize;
                    mipmap.SizeRounded  = faceLodSizeRounded;

                    var loadError = ExtractFace(src, dest, header, mipmap, data, faces);
                    if (loadError != KTXError.Success)
                    {
                        errorCode = loadError;
                        break;
                    }
                }

                var format = DetermineFormat(header.GlType, header.GlFormat, header.GlInternalFormat);

                // MgImageOptimizer takes
                // 1. byte array
                // 2. image source

                var output = new KTXTextureOutput();

                // one face at a time
                var face = faces[0];

                output.Source = new MgImageSource
                {
                    Format  = format,
                    Height  = header.PixelHeight,
                    Width   = header.PixelWidth,
                    Mipmaps = face.Mipmaps,
                    Size    = (uint)dest.Length,
                };

                output.TextureInfo = mTextureOptimizer.Load(dest.ToArray(), output.Source, null, null);

                // QUEUE WAIT ON
                var err = mGraphicsConfiguration.Queue.QueueWaitIdle();
                Debug.Assert(err == Result.SUCCESS);
                mGraphicsConfiguration.Device.FreeCommandBuffers(
                    mGraphicsConfiguration.Partition.CommandPool,
                    new[] { output.TextureInfo.Command });

                return(output);
            }
        }