Пример #1
0
        private void InitWithKTXTexture(BinaryReader reader)
        {
            var identifier = reader.ReadBytes(12);

            if (identifier[1] != 'K' || identifier[2] != 'T' || identifier[3] != 'X')
            {
                throw new InvalidDataException("Invalid KTX header");
            }
            var endiannes = reader.ReadUInt32();

            if (endiannes != 0x04030201)
            {
                throw new InvalidDataException("Unsupported endiannes");
            }
            var glType                = reader.ReadInt32();
            var glTypeSize            = reader.ReadInt32();
            var glFormat              = reader.ReadInt32();
            var glInternalFormat      = reader.ReadInt32();
            var glBaseInternalFormat  = reader.ReadInt32();
            var pixelWidth            = reader.ReadInt32();
            var pixelHeight           = reader.ReadInt32();
            var pixelDepth            = reader.ReadInt32();
            var numberOfArrayElements = reader.ReadInt32();
            var numberOfFaces         = reader.ReadInt32();
            var numberOfMipmapLevels  = reader.ReadInt32();
            var bytesOfKeyValueData   = reader.ReadInt32();

            reader.ReadBytes(bytesOfKeyValueData);
            if (numberOfArrayElements != 0)
            {
                throw new InvalidDataException("Array textures are not supported");
            }
            if (numberOfFaces != 1)
            {
                throw new InvalidDataException("Cubemap textures are not supported");
            }
            if (pixelDepth != 0)
            {
                throw new InvalidDataException("3D Textures are not supported");
            }
            if ((pixelWidth & 3) != 0 || (pixelHeight & 3) != 0)
            {
                throw new InvalidDataException("Texture dimensions should multiple of 4");
            }
            SurfaceSize = ImageSize = new Size(pixelWidth, pixelHeight);
            Action glCommands = PrepareOpenGLTexture;

            PrepareOpenGLTexture();
            for (int i = 0; i < Math.Max(1, numberOfMipmapLevels); i++)
            {
                var dataLength = reader.ReadInt32();
                MemoryUsed = 0;
                if (i > 0 && (pixelWidth < 8 || pixelHeight < 8))
                {
                    continue;
                }
                // Copy variables because they will be captured.
                int mipLevel = i;
                int width    = pixelWidth;
                int height   = pixelHeight;
                if (glFormat == 0)
                {
                    var data = ReadTextureData(reader, dataLength);
                    glCommands += () => {
                        if (!etc2Checked)
                        {
                            etc2Checked = true;
                            if (PlatformRenderer.GetGLESMajorVersion() >= 3)
                            {
                                etc2Supported = true;
                            }
                            else
                            {
                                var ext = GL.GetString(StringName.Extensions);
                                etc2Supported = ext?.Contains("ETC2_RGBA8") ?? false;
                            }
                            Debug.Write(etc2Supported ? "ETC2 textures supported." : "ETC2 textures not supported.");
                        }
                        PlatformRenderer.PushTexture(handle, 0);
                        const int etc1Rgb8Oes = 36196;
                        if (etc2Supported || (Application.Platform == PlatformId.Android && glInternalFormat == etc1Rgb8Oes))
                        {
                            GL.CompressedTexImage2D(
                                TextureTarget.Texture2D, mipLevel, (PixelInternalFormat)glInternalFormat,
                                width, height, 0, dataLength, data);
                        }
                        else
                        {
                            var rgba8Data = Marshal.AllocHGlobal(width * height * 4);
                            Etc2Decoder.Decode(data, rgba8Data, width, height, glInternalFormat);
                            GL.TexImage2D(TextureTarget.Texture2D, mipLevel, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, rgba8Data);
                            Marshal.FreeHGlobal(rgba8Data);
                        }
                        PlatformRenderer.PopTexture(0);
                        PlatformRenderer.CheckErrors();
                    };
                }
                else
                {
                    var data = ReadTextureData(reader, dataLength);
                    glCommands += () => {
                        PlatformRenderer.PushTexture(handle, 0);
                        GL.TexImage2D(
                            TextureTarget.Texture2D, mipLevel, (PixelInternalFormat)glInternalFormat,
                            width, height, 0, (PixelFormat)glFormat, (PixelType)glType, data);
                        PlatformRenderer.PopTexture(0);
                        PlatformRenderer.CheckErrors();
                    };
                }
                pixelWidth  /= 2;
                pixelHeight /= 2;
            }
            Application.InvokeOnMainThread(glCommands);
        }
Пример #2
0
        private void InitWithKTXTexture(BinaryReader reader)
        {
            var identifier = reader.ReadBytes(12);

            if (identifier[1] != 'K' || identifier[2] != 'T' || identifier[3] != 'X')
            {
                throw new InvalidDataException("Invalid KTX header");
            }
            var endiannes = reader.ReadUInt32();

            if (endiannes != 0x04030201)
            {
                throw new InvalidDataException("Unsupported endiannes");
            }
            var glType                = reader.ReadInt32();
            var glTypeSize            = reader.ReadInt32();
            var glFormat              = reader.ReadInt32();
            var glInternalFormat      = reader.ReadInt32();
            var glBaseInternalFormat  = reader.ReadInt32();
            var pixelWidth            = reader.ReadInt32();
            var pixelHeight           = reader.ReadInt32();
            var pixelDepth            = reader.ReadInt32();
            var numberOfArrayElements = reader.ReadInt32();
            var numberOfFaces         = reader.ReadInt32();
            var numberOfMipmapLevels  = Math.Max(1, reader.ReadInt32());
            var bytesOfKeyValueData   = reader.ReadInt32();

            reader.ReadBytes(bytesOfKeyValueData);
            if (numberOfArrayElements != 0)
            {
                throw new InvalidDataException("Array textures are not supported");
            }
            if (numberOfFaces != 1)
            {
                throw new InvalidDataException("Cubemap textures are not supported");
            }
            if (pixelDepth != 0)
            {
                throw new InvalidDataException("3D Textures are not supported");
            }
            if ((pixelWidth & 3) != 0 || (pixelHeight & 3) != 0)
            {
                throw new InvalidDataException("Texture dimensions should multiple of 4");
            }
            if (numberOfMipmapLevels > 1 && numberOfMipmapLevels != GraphicsUtility.CalculateMipLevelCount(pixelWidth, pixelHeight))
            {
                throw new InvalidDataException();
            }
            var format    = ConvertGLFormat(glInternalFormat, glBaseInternalFormat, glFormat, glType);
            var etcFormat =
                format == Format.ETC1_R8G8B8_UNorm_Block ||
                format == Format.ETC2_R8G8B8_UNorm_Block ||
                format == Format.ETC2_R8G8B8A1_UNorm_Block ||
                format == Format.ETC2_R8G8B8A8_UNorm_Block;

            SurfaceSize = ImageSize = new Size(pixelWidth, pixelHeight);
            Action deferredCommands = null;

            for (int level = 0; level < numberOfMipmapLevels; level++)
            {
                var levelCopy  = level;
                var dataLength = reader.ReadInt32();
                var data       = ReadTextureData(reader, dataLength);
                GraphicsUtility.CalculateMipLevelSize(levelCopy, pixelWidth, pixelHeight, out var levelWidth, out var levelHeight);
                MemoryUsed        = 0;
                deferredCommands += () => {
                    var formatFeatures = PlatformRenderer.Context.GetFormatFeatures(format);
                    if (etcFormat && (formatFeatures & FormatFeatures.Sample) == 0)
                    {
                        var rgba8Data = Marshal.AllocHGlobal(levelWidth * levelHeight * 4);
                        try {
                            Etc2Decoder.Decode(data, rgba8Data, levelWidth, levelHeight, format);
                            EnsurePlatformTexture(Format.R8G8B8A8_UNorm, pixelWidth, pixelHeight, numberOfMipmapLevels > 1);
                            platformTexture.SetData(levelCopy, rgba8Data);
                        } finally {
                            Marshal.FreeHGlobal(rgba8Data);
                        }
                    }
                    else
                    {
                        EnsurePlatformTexture(format, pixelWidth, pixelHeight, numberOfMipmapLevels > 1);
                        platformTexture.SetData(levelCopy, data);
                    }
                };
            }
            Window.Current.InvokeOnRendering(deferredCommands);
        }