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