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); }
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); }
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()); }
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); }
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); } }