| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- using OpenTK.Graphics.OpenGL;
- using Ryujinx.Graphics.Gal.Texture;
- using System;
- namespace Ryujinx.Graphics.Gal.OpenGL
- {
- class OGLTexture : IGalTexture
- {
- private OGLCachedResource<ImageHandler> TextureCache;
- public OGLTexture()
- {
- TextureCache = new OGLCachedResource<ImageHandler>(DeleteTexture);
- }
- public void LockCache()
- {
- TextureCache.Lock();
- }
- public void UnlockCache()
- {
- TextureCache.Unlock();
- }
- private static void DeleteTexture(ImageHandler CachedImage)
- {
- GL.DeleteTexture(CachedImage.Handle);
- }
- public void Create(long Key, byte[] Data, GalImage Image)
- {
- int Handle = GL.GenTexture();
- TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length);
- GL.BindTexture(TextureTarget.Texture2D, Handle);
- const int Level = 0; //TODO: Support mipmap textures.
- const int Border = 0;
- if (IsCompressedTextureFormat(Image.Format))
- {
- InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format);
- GL.CompressedTexImage2D(
- TextureTarget.Texture2D,
- Level,
- InternalFmt,
- Image.Width,
- Image.Height,
- Border,
- Data.Length,
- Data);
- }
- else
- {
- if (Image.Format >= GalImageFormat.ASTC_BEGIN && Image.Format <= GalImageFormat.ASTC_END)
- {
- int TextureBlockWidth = GetAstcBlockWidth(Image.Format);
- int TextureBlockHeight = GetAstcBlockHeight(Image.Format);
- Data = ASTCDecoder.DecodeToRGBA8888(
- Data,
- TextureBlockWidth,
- TextureBlockHeight, 1,
- Image.Width,
- Image.Height, 1);
- Image.Format = GalImageFormat.A8B8G8R8_UNORM_PACK32;
- }
- (PixelInternalFormat InternalFormat, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
- GL.TexImage2D(
- TextureTarget.Texture2D,
- Level,
- InternalFormat,
- Image.Width,
- Image.Height,
- Border,
- Format,
- Type,
- Data);
- }
- int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource);
- int SwizzleG = (int)OGLEnumConverter.GetTextureSwizzle(Image.YSource);
- int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource);
- int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, SwizzleR);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, SwizzleG);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, SwizzleB);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA);
- }
- public void CreateFb(long Key, long Size, GalImage Image)
- {
- if (!TryGetImage(Key, out ImageHandler CachedImage))
- {
- CachedImage = new ImageHandler();
- TextureCache.AddOrUpdate(Key, CachedImage, Size);
- }
- CachedImage.EnsureSetup(Image);
- }
- public bool TryGetImage(long Key, out ImageHandler CachedImage)
- {
- if (TextureCache.TryGetValue(Key, out CachedImage))
- {
- return true;
- }
- CachedImage = null;
- return false;
- }
- private static int GetAstcBlockWidth(GalImageFormat Format)
- {
- switch (Format)
- {
- case GalImageFormat.ASTC_4x4_UNORM_BLOCK: return 4;
- case GalImageFormat.ASTC_5x5_UNORM_BLOCK: return 5;
- case GalImageFormat.ASTC_6x6_UNORM_BLOCK: return 6;
- case GalImageFormat.ASTC_8x8_UNORM_BLOCK: return 8;
- case GalImageFormat.ASTC_10x10_UNORM_BLOCK: return 10;
- case GalImageFormat.ASTC_12x12_UNORM_BLOCK: return 12;
- case GalImageFormat.ASTC_5x4_UNORM_BLOCK: return 5;
- case GalImageFormat.ASTC_6x5_UNORM_BLOCK: return 6;
- case GalImageFormat.ASTC_8x6_UNORM_BLOCK: return 8;
- case GalImageFormat.ASTC_10x8_UNORM_BLOCK: return 10;
- case GalImageFormat.ASTC_12x10_UNORM_BLOCK: return 12;
- case GalImageFormat.ASTC_8x5_UNORM_BLOCK: return 8;
- case GalImageFormat.ASTC_10x5_UNORM_BLOCK: return 10;
- case GalImageFormat.ASTC_10x6_UNORM_BLOCK: return 10;
- }
- throw new ArgumentException(nameof(Format));
- }
- private static int GetAstcBlockHeight(GalImageFormat Format)
- {
- switch (Format)
- {
- case GalImageFormat.ASTC_4x4_UNORM_BLOCK: return 4;
- case GalImageFormat.ASTC_5x5_UNORM_BLOCK: return 5;
- case GalImageFormat.ASTC_6x6_UNORM_BLOCK: return 6;
- case GalImageFormat.ASTC_8x8_UNORM_BLOCK: return 8;
- case GalImageFormat.ASTC_10x10_UNORM_BLOCK: return 10;
- case GalImageFormat.ASTC_12x12_UNORM_BLOCK: return 12;
- case GalImageFormat.ASTC_5x4_UNORM_BLOCK: return 4;
- case GalImageFormat.ASTC_6x5_UNORM_BLOCK: return 5;
- case GalImageFormat.ASTC_8x6_UNORM_BLOCK: return 6;
- case GalImageFormat.ASTC_10x8_UNORM_BLOCK: return 8;
- case GalImageFormat.ASTC_12x10_UNORM_BLOCK: return 10;
- case GalImageFormat.ASTC_8x5_UNORM_BLOCK: return 5;
- case GalImageFormat.ASTC_10x5_UNORM_BLOCK: return 5;
- case GalImageFormat.ASTC_10x6_UNORM_BLOCK: return 6;
- }
- throw new ArgumentException(nameof(Format));
- }
- public bool TryGetCachedTexture(long Key, long DataSize, out GalImage Image)
- {
- if (TextureCache.TryGetSize(Key, out long Size) && Size == DataSize)
- {
- if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
- {
- Image = CachedImage.Image;
- return true;
- }
- }
- Image = default(GalImage);
- return false;
- }
- public void Bind(long Key, int Index)
- {
- if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
- {
- GL.ActiveTexture(TextureUnit.Texture0 + Index);
- GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle);
- }
- }
- public void SetSampler(GalTextureSampler Sampler)
- {
- int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU);
- int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
- int MinFilter = (int)OGLEnumConverter.GetTextureMinFilter(Sampler.MinFilter, Sampler.MipFilter);
- int MagFilter = (int)OGLEnumConverter.GetTextureMagFilter(Sampler.MagFilter);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, WrapS);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, WrapT);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter);
- float[] Color = new float[]
- {
- Sampler.BorderColor.Red,
- Sampler.BorderColor.Green,
- Sampler.BorderColor.Blue,
- Sampler.BorderColor.Alpha
- };
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color);
- }
- private static bool IsCompressedTextureFormat(GalImageFormat Format)
- {
- switch (Format)
- {
- case GalImageFormat.BC6H_UFLOAT_BLOCK:
- case GalImageFormat.BC6H_SFLOAT_BLOCK:
- case GalImageFormat.BC7_UNORM_BLOCK:
- case GalImageFormat.BC1_RGBA_UNORM_BLOCK:
- case GalImageFormat.BC2_UNORM_BLOCK:
- case GalImageFormat.BC3_UNORM_BLOCK:
- case GalImageFormat.BC4_SNORM_BLOCK:
- case GalImageFormat.BC4_UNORM_BLOCK:
- case GalImageFormat.BC5_SNORM_BLOCK:
- case GalImageFormat.BC5_UNORM_BLOCK:
- return true;
- }
- return false;
- }
- }
- }
|