Exemplo n.º 1
0
        public void Reinterpret(long key, GalImage newImage)
        {
            if (!_texture.TryGetImage(key, out GalImage oldImage))
            {
                return;
            }

            if (newImage.Format == oldImage.Format &&
                newImage.Width == oldImage.Width &&
                newImage.Height == oldImage.Height &&
                newImage.Depth == oldImage.Depth &&
                newImage.LayerCount == oldImage.LayerCount &&
                newImage.TextureTarget == oldImage.TextureTarget)
            {
                return;
            }

            if (_copyPbo == 0)
            {
                _copyPbo = GL.GenBuffer();
            }

            GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPbo);

            // The buffer should be large enough to hold the largest texture.
            int bufferSize = Math.Max(ImageUtils.GetSize(oldImage),
                                      ImageUtils.GetSize(newImage));

            GL.BufferData(BufferTarget.PixelPackBuffer, bufferSize, IntPtr.Zero, BufferUsageHint.StreamCopy);

            if (!_texture.TryGetImageHandler(key, out ImageHandler cachedImage))
            {
                throw new InvalidOperationException();
            }

            (_, PixelFormat format, PixelType type) = OglEnumConverter.GetImageFormat(cachedImage.Format);

            TextureTarget target = ImageUtils.GetTextureTarget(newImage.TextureTarget);

            GL.BindTexture(target, cachedImage.Handle);

            GL.GetTexImage(target, 0, format, type, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, _copyPbo);

            GL.PixelStore(PixelStoreParameter.UnpackRowLength, oldImage.Width);

            _texture.Create(key, ImageUtils.GetSize(newImage), newImage);

            GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0);

            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
        }
Exemplo n.º 2
0
        public void Create(long key, int size, GalImage image)
        {
            int handle = GL.GenTexture();

            TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);

            GL.BindTexture(target, handle);

            const int level  = 0; //TODO: Support mipmap textures.
            const int border = 0;

            _textureCache.AddOrUpdate(key, new ImageHandler(handle, image), (uint)size);

            if (ImageUtils.IsCompressed(image.Format))
            {
                throw new InvalidOperationException("Surfaces with compressed formats are not supported!");
            }

            (PixelInternalFormat internalFmt,
             PixelFormat format,
             PixelType type) = OglEnumConverter.GetImageFormat(image.Format);

            switch (target)
            {
            case TextureTarget.Texture1D:
                GL.TexImage1D(
                    target,
                    level,
                    internalFmt,
                    image.Width,
                    border,
                    format,
                    type,
                    IntPtr.Zero);
                break;

            case TextureTarget.Texture2D:
                GL.TexImage2D(
                    target,
                    level,
                    internalFmt,
                    image.Width,
                    image.Height,
                    border,
                    format,
                    type,
                    IntPtr.Zero);
                break;

            case TextureTarget.Texture3D:
                GL.TexImage3D(
                    target,
                    level,
                    internalFmt,
                    image.Width,
                    image.Height,
                    image.Depth,
                    border,
                    format,
                    type,
                    IntPtr.Zero);
                break;

            case TextureTarget.Texture2DArray:
                GL.TexImage3D(
                    target,
                    level,
                    internalFmt,
                    image.Width,
                    image.Height,
                    image.LayerCount,
                    border,
                    format,
                    type,
                    IntPtr.Zero);
                break;

            default:
                throw new NotImplementedException($"Unsupported texture target type: {target}");
            }
        }
Exemplo n.º 3
0
        public void Create(long key, byte[] data, GalImage image)
        {
            int handle = GL.GenTexture();

            TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);

            GL.BindTexture(target, handle);

            const int level  = 0; //TODO: Support mipmap textures.
            const int border = 0;

            _textureCache.AddOrUpdate(key, new ImageHandler(handle, image), (uint)data.Length);

            if (ImageUtils.IsCompressed(image.Format) && !IsAstc(image.Format))
            {
                InternalFormat internalFmt = OglEnumConverter.GetCompressedImageFormat(image.Format);

                switch (target)
                {
                case TextureTarget.Texture1D:
                    GL.CompressedTexImage1D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.Texture2D:
                    GL.CompressedTexImage2D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.Texture3D:
                    GL.CompressedTexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.Depth,
                        border,
                        data.Length,
                        data);
                    break;

                // Cube map arrays are just 2D texture arrays with 6 entries
                // per cube map so we can handle them in the same way
                case TextureTarget.TextureCubeMapArray:
                case TextureTarget.Texture2DArray:
                    GL.CompressedTexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.LayerCount,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.TextureCubeMap:
                    Span <byte> array = new Span <byte>(data);

                    int faceSize = ImageUtils.GetSize(image) / 6;

                    for (int Face = 0; Face < 6; Face++)
                    {
                        GL.CompressedTexImage2D(
                            TextureTarget.TextureCubeMapPositiveX + Face,
                            level,
                            internalFmt,
                            image.Width,
                            image.Height,
                            border,
                            faceSize,
                            array.Slice(Face * faceSize, faceSize).ToArray());
                    }
                    break;

                default:
                    throw new NotImplementedException($"Unsupported texture target type: {target}");
                }
            }
            else
            {
                //TODO: Use KHR_texture_compression_astc_hdr when available
                if (IsAstc(image.Format))
                {
                    int textureBlockWidth  = ImageUtils.GetBlockWidth(image.Format);
                    int textureBlockHeight = ImageUtils.GetBlockHeight(image.Format);
                    int textureBlockDepth  = ImageUtils.GetBlockDepth(image.Format);

                    data = AstcDecoder.DecodeToRgba8888(
                        data,
                        textureBlockWidth,
                        textureBlockHeight,
                        textureBlockDepth,
                        image.Width,
                        image.Height,
                        image.Depth);

                    image.Format = GalImageFormat.Rgba8 | (image.Format & GalImageFormat.TypeMask);
                }

                (PixelInternalFormat internalFmt,
                 PixelFormat format,
                 PixelType type) = OglEnumConverter.GetImageFormat(image.Format);


                switch (target)
                {
                case TextureTarget.Texture1D:
                    GL.TexImage1D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.Texture2D:
                    GL.TexImage2D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.Texture3D:
                    GL.TexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.Depth,
                        border,
                        format,
                        type,
                        data);
                    break;

                // Cube map arrays are just 2D texture arrays with 6 entries
                // per cube map so we can handle them in the same way
                case TextureTarget.TextureCubeMapArray:
                case TextureTarget.Texture2DArray:
                    GL.TexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.LayerCount,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.TextureCubeMap:
                    Span <byte> array = new Span <byte>(data);

                    int faceSize = ImageUtils.GetSize(image) / 6;

                    for (int face = 0; face < 6; face++)
                    {
                        GL.TexImage2D(
                            TextureTarget.TextureCubeMapPositiveX + face,
                            level,
                            internalFmt,
                            image.Width,
                            image.Height,
                            border,
                            format,
                            type,
                            array.Slice(face * faceSize, faceSize).ToArray());
                    }
                    break;

                default:
                    throw new NotImplementedException($"Unsupported texture target type: {target}");
                }
            }
        }