예제 #1
0
        private void ReadCompressedImage(ref Action glCommands, BinaryReader reader, int level, int width, int height, int linearSize, UInt32 pfFourCC)
        {
            var pif = (PixelInternalFormat)All.CompressedRgbS3tcDxt1Ext;

            switch ((DDSFourCC)pfFourCC)
            {
            case DDSFourCC.DXT1:
                pif = (PixelInternalFormat)All.CompressedRgbS3tcDxt1Ext;
                break;

            case DDSFourCC.DXT3:
                pif = (PixelInternalFormat)All.CompressedRgbaS3tcDxt3Ext;
                break;

            case DDSFourCC.DXT5:
                pif = (PixelInternalFormat)All.CompressedRgbaS3tcDxt5Ext;
                break;

            default:
                throw new InvalidDataException("Unsupported texture format");
            }
            var buffer = ReadTextureData(reader, linearSize);

            glCommands += () => {
                PlatformRenderer.PushTexture(handle, 0);
                GL.CompressedTexImage2D(TextureTarget.Texture2D, level, pif, width, height, 0, buffer.Length, buffer);
                PlatformRenderer.PopTexture(0);
                PlatformRenderer.CheckErrors();
            };
        }
예제 #2
0
 private void SetTextureParameter(TextureParameterName name, int value)
 {
     if (handle == 0)
     {
         return;
     }
     PlatformRenderer.PushTexture(handle, 0);
     GL.TexParameter(TextureTarget.Texture2D, name, value);
     PlatformRenderer.PopTexture(0);
 }
예제 #3
0
 /// <summary>
 /// Load subtexture from pixel array
 /// Warning: this method doesn't support automatic texture reload after restoring graphics context
 /// </summary>
 public void LoadSubImage(Color4[] pixels, int x, int y, int width, int height)
 {
     Application.InvokeOnMainThread(() => {
         PrepareOpenGLTexture();
         PlatformRenderer.PushTexture(handle, 0);
         GL.TexSubImage2D(TextureTarget.Texture2D, 0, x, y, width, height,
                          PixelFormat.Rgba, PixelType.UnsignedByte, pixels);
         PlatformRenderer.CheckErrors();
         PlatformRenderer.PopTexture(0);
     });
 }
예제 #4
0
        private void CreateTexture()
        {
            if (!Application.CurrentThread.IsMain())
            {
                throw new Lime.Exception("Attempt to create a RenderTexture not from the main thread");
            }
            var t = new uint[1];

            GL.GenFramebuffers(1, t);
            framebuffer = t[0];
            GL.GenTextures(1, t);
            handle = t[0];
            PlatformRenderer.PushTexture(handle, 0);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, textureParams.MinFilter.ToInt());
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, textureParams.MagFilter.ToInt());
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, textureParams.WrapModeU.ToInt());
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, textureParams.WrapModeV.ToInt());
            int bpp;

            if (Format == RenderTextureFormat.RGBA8)
            {
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, size.Width, size.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)null);
                bpp = 4;
            }
            else
            {
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, size.Width, size.Height, 0, PixelFormat.Rgb, PixelType.UnsignedShort565, (IntPtr)null);
                bpp = 2;
            }
            MemoryUsed = SurfaceSize.Width * SurfaceSize.Height * bpp;
            uint oldFramebuffer = PlatformRenderer.CurrentFramebuffer;

            PlatformRenderer.BindFramebuffer(framebuffer);
            PlatformRenderer.CheckErrors();
            GL.FramebufferTexture2D(
                FramebufferTarget.Framebuffer,
                FramebufferSlot.ColorAttachment0,
                TextureTarget.Texture2D,
                handle,
                level: 0);
            if ((int)GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != (int)FramebufferErrorCode.FramebufferComplete)
            {
                throw new Exception("Failed to create render texture. Framebuffer is incomplete.");
            }
            AttachRenderBuffer(FramebufferSlot.DepthAttachment, RenderbufferInternalFormat.DepthComponent16, out depthBuffer);
            Renderer.Clear(0, 0, 0, 0);
            PlatformRenderer.PopTexture(0);
            PlatformRenderer.BindFramebuffer(oldFramebuffer);
            PlatformRenderer.CheckErrors();
        }
예제 #5
0
        private void ReadRGBAImage(ref Action glCommands, BinaryReader reader, int level, int width, int height, int pitch)
        {
            if (pitch != width * 4)
            {
                throw new InvalidDataException("Error reading RGBA texture. Must be 32 bit rgba");
            }
            var buffer = ReadTextureData(reader, pitch * height);

            glCommands += () => {
                PlatformRenderer.PushTexture(handle, 0);
                GL.TexImage2D(TextureTarget.Texture2D, level, PixelInternalFormat.Rgba, width, height, 0,
                              PixelFormat.Rgba, PixelType.UnsignedByte, buffer);
                PlatformRenderer.PopTexture(0);
                PlatformRenderer.CheckErrors();
            };
        }
예제 #6
0
        public void LoadImage(IntPtr pixels, int width, int height)
        {
            if (!Application.CurrentThread.IsMain())
            {
                throw new InvalidOperationException();
            }
            PrepareOpenGLTexture();
            PlatformRenderer.PushTexture(handle, 0);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels);
            MemoryUsed = 4 * width * height;
            PlatformRenderer.PopTexture(0);
            PlatformRenderer.CheckErrors();

            ImageSize   = new Size(width, height);
            SurfaceSize = ImageSize;
            uvRect      = new Rectangle(0, 0, 1, 1);
        }
예제 #7
0
 private void PrepareOpenGLTexture()
 {
     // Generate a new texture.
     if (handle == 0)
     {
         var t = new int[1];
         GL.GenTextures(1, t);
         handle = (uint)t[0];
     }
     PlatformRenderer.PushTexture(handle, 0);
     GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, textureParams.MinFilter.ToInt());
     GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, textureParams.MagFilter.ToInt());
     GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, textureParams.WrapModeU.ToInt());
     GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, textureParams.WrapModeV.ToInt());
     PlatformRenderer.PopTexture(0);
     PlatformRenderer.CheckErrors();
 }
예제 #8
0
        private void InitWithPVRTexture(BinaryReader reader)
        {
            var version = reader.ReadUInt32();

            if (version != PVRMagic)
            {
                throw new Exception("Invalid PVR header");
            }
            reader.ReadUInt32();             // flags
            var pixelFormat = (PVRFormat)reader.ReadUInt64();

            reader.ReadUInt32();             // color space
            reader.ReadUInt32();             // channel type
            var height = reader.ReadInt32();
            var width  = reader.ReadInt32();

            reader.ReadUInt32();             // depth
            reader.ReadUInt32();             // num surfaces
            reader.ReadUInt32();             // num faces
            var numMipmaps   = reader.ReadInt32();
            var metaDataSize = reader.ReadInt32();

            if (metaDataSize > 0)
            {
                reader.ReadChars(metaDataSize);
            }
            SurfaceSize = ImageSize = new Size(width, height);
            Action glCommands = PrepareOpenGLTexture;

            MemoryUsed = 0;
            for (int i = 0; i < numMipmaps; i++)
            {
                if (i > 0 && (width < 8 || height < 8))
                {
                    continue;
                }
                // Cloning variables to prevent wrong capturing
                int mipLevel = i;
                int width2   = width;
                int height2  = height;
                switch (pixelFormat)
                {
#if iOS
                case PVRFormat.PVRTC_4_RGBA: {
                    var buffer = ReadTextureData(reader, width * height * 4 / 8);
                    glCommands += () => {
                        PlatformRenderer.PushTexture(handle, 0);
                        GL.CompressedTexImage2D(All.Texture2D, mipLevel, All.CompressedRgbaPvrtc4Bppv1Img, width2, height2, 0, buffer.Length, buffer);
                        PlatformRenderer.PopTexture(0);
                        PlatformRenderer.CheckErrors();
                    };
                    break;
                }

                case PVRFormat.PVRTC_2_RGBA: {
                    if (i > 0 && height < 16)
                    {
                        continue;
                    }
                    var buffer = ReadTextureData(reader, width * height * 2 / 8);
                    glCommands += () => {
                        PlatformRenderer.PushTexture(handle, 0);
                        GL.CompressedTexImage2D(All.Texture2D, mipLevel, All.CompressedRgbaPvrtc2Bppv1Img, width2, height2, 0, buffer.Length, buffer);
                        PlatformRenderer.PopTexture(0);
                        PlatformRenderer.CheckErrors();
                    };
                    break;
                }
#elif ANDROID
                case PVRFormat.ETC1: {
                    var buffer = ReadTextureData(reader, width * height * 4 / 8);
                    glCommands += () => {
                        PlatformRenderer.PushTexture(handle, 0);
                        GL.CompressedTexImage2D(All.Texture2D, mipLevel, All.Etc1Rgb8Oes, width2, height2, 0, buffer.Length, buffer);
                        PlatformRenderer.PopTexture(0);
                        PlatformRenderer.CheckErrors();
                    };
                    break;
                }
#endif
                case PVRFormat.RGBA4444: {
                    var buffer = ReadTextureData(reader, width * height * 2);
                    glCommands += () => {
                        PlatformRenderer.PushTexture(handle, 0);
                        GL.TexImage2D(TextureTarget.Texture2D, mipLevel, PixelInternalFormat.Rgba, width2, height2, 0, PixelFormat.Rgba, PixelType.UnsignedShort4444, buffer);
                        PlatformRenderer.PopTexture(0);
                        PlatformRenderer.CheckErrors();
                    };
                    break;
                }

                case PVRFormat.RGB565: {
                    var buffer = ReadTextureData(reader, width * height * 2);
                    glCommands += () => {
                        PlatformRenderer.PushTexture(handle, 0);
                        GL.TexImage2D(TextureTarget.Texture2D, mipLevel, PixelInternalFormat.Rgb, width2, height2, 0, PixelFormat.Rgb, PixelType.UnsignedShort565, buffer);
                        PlatformRenderer.PopTexture(0);
                        PlatformRenderer.CheckErrors();
                    };
                    break;
                }

                case PVRFormat.RGBA8888: {
                    var buffer = ReadTextureData(reader, width * height * 4);
                    glCommands += () => {
                        PlatformRenderer.PushTexture(handle, 0);
                        GL.TexImage2D(TextureTarget.Texture2D, mipLevel, PixelInternalFormat.Rgba, width2, height2, 0, PixelFormat.Rgba, PixelType.UnsignedByte, buffer);
                        PlatformRenderer.PopTexture(0);
                        PlatformRenderer.CheckErrors();
                    };
                    break;
                }

                default:
                    throw new NotImplementedException();
                }
                width  /= 2;
                height /= 2;
            }
            Application.InvokeOnMainThread(glCommands);
        }
예제 #9
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);
        }