OGLTexture.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Graphics.Gal.Texture;
  3. using System;
  4. namespace Ryujinx.Graphics.Gal.OpenGL
  5. {
  6. class OGLTexture : IGalTexture
  7. {
  8. private OGLCachedResource<ImageHandler> TextureCache;
  9. public OGLTexture()
  10. {
  11. TextureCache = new OGLCachedResource<ImageHandler>(DeleteTexture);
  12. }
  13. public void LockCache()
  14. {
  15. TextureCache.Lock();
  16. }
  17. public void UnlockCache()
  18. {
  19. TextureCache.Unlock();
  20. }
  21. private static void DeleteTexture(ImageHandler CachedImage)
  22. {
  23. GL.DeleteTexture(CachedImage.Handle);
  24. }
  25. public void Create(long Key, byte[] Data, GalImage Image)
  26. {
  27. int Handle = GL.GenTexture();
  28. TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length);
  29. GL.BindTexture(TextureTarget.Texture2D, Handle);
  30. const int Level = 0; //TODO: Support mipmap textures.
  31. const int Border = 0;
  32. if (IsCompressedTextureFormat(Image.Format))
  33. {
  34. InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format);
  35. GL.CompressedTexImage2D(
  36. TextureTarget.Texture2D,
  37. Level,
  38. InternalFmt,
  39. Image.Width,
  40. Image.Height,
  41. Border,
  42. Data.Length,
  43. Data);
  44. }
  45. else
  46. {
  47. if (Image.Format >= GalImageFormat.ASTC_BEGIN && Image.Format <= GalImageFormat.ASTC_END)
  48. {
  49. int TextureBlockWidth = GetAstcBlockWidth(Image.Format);
  50. int TextureBlockHeight = GetAstcBlockHeight(Image.Format);
  51. Data = ASTCDecoder.DecodeToRGBA8888(
  52. Data,
  53. TextureBlockWidth,
  54. TextureBlockHeight, 1,
  55. Image.Width,
  56. Image.Height, 1);
  57. Image.Format = GalImageFormat.A8B8G8R8_UNORM_PACK32;
  58. }
  59. (PixelInternalFormat InternalFormat, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
  60. GL.TexImage2D(
  61. TextureTarget.Texture2D,
  62. Level,
  63. InternalFormat,
  64. Image.Width,
  65. Image.Height,
  66. Border,
  67. Format,
  68. Type,
  69. Data);
  70. }
  71. int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource);
  72. int SwizzleG = (int)OGLEnumConverter.GetTextureSwizzle(Image.YSource);
  73. int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource);
  74. int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource);
  75. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, SwizzleR);
  76. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, SwizzleG);
  77. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, SwizzleB);
  78. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA);
  79. }
  80. public void CreateFb(long Key, long Size, GalImage Image)
  81. {
  82. if (!TryGetImage(Key, out ImageHandler CachedImage))
  83. {
  84. CachedImage = new ImageHandler();
  85. TextureCache.AddOrUpdate(Key, CachedImage, Size);
  86. }
  87. CachedImage.EnsureSetup(Image);
  88. }
  89. public bool TryGetImage(long Key, out ImageHandler CachedImage)
  90. {
  91. if (TextureCache.TryGetValue(Key, out CachedImage))
  92. {
  93. return true;
  94. }
  95. CachedImage = null;
  96. return false;
  97. }
  98. private static int GetAstcBlockWidth(GalImageFormat Format)
  99. {
  100. switch (Format)
  101. {
  102. case GalImageFormat.ASTC_4x4_UNORM_BLOCK: return 4;
  103. case GalImageFormat.ASTC_5x5_UNORM_BLOCK: return 5;
  104. case GalImageFormat.ASTC_6x6_UNORM_BLOCK: return 6;
  105. case GalImageFormat.ASTC_8x8_UNORM_BLOCK: return 8;
  106. case GalImageFormat.ASTC_10x10_UNORM_BLOCK: return 10;
  107. case GalImageFormat.ASTC_12x12_UNORM_BLOCK: return 12;
  108. case GalImageFormat.ASTC_5x4_UNORM_BLOCK: return 5;
  109. case GalImageFormat.ASTC_6x5_UNORM_BLOCK: return 6;
  110. case GalImageFormat.ASTC_8x6_UNORM_BLOCK: return 8;
  111. case GalImageFormat.ASTC_10x8_UNORM_BLOCK: return 10;
  112. case GalImageFormat.ASTC_12x10_UNORM_BLOCK: return 12;
  113. case GalImageFormat.ASTC_8x5_UNORM_BLOCK: return 8;
  114. case GalImageFormat.ASTC_10x5_UNORM_BLOCK: return 10;
  115. case GalImageFormat.ASTC_10x6_UNORM_BLOCK: return 10;
  116. }
  117. throw new ArgumentException(nameof(Format));
  118. }
  119. private static int GetAstcBlockHeight(GalImageFormat Format)
  120. {
  121. switch (Format)
  122. {
  123. case GalImageFormat.ASTC_4x4_UNORM_BLOCK: return 4;
  124. case GalImageFormat.ASTC_5x5_UNORM_BLOCK: return 5;
  125. case GalImageFormat.ASTC_6x6_UNORM_BLOCK: return 6;
  126. case GalImageFormat.ASTC_8x8_UNORM_BLOCK: return 8;
  127. case GalImageFormat.ASTC_10x10_UNORM_BLOCK: return 10;
  128. case GalImageFormat.ASTC_12x12_UNORM_BLOCK: return 12;
  129. case GalImageFormat.ASTC_5x4_UNORM_BLOCK: return 4;
  130. case GalImageFormat.ASTC_6x5_UNORM_BLOCK: return 5;
  131. case GalImageFormat.ASTC_8x6_UNORM_BLOCK: return 6;
  132. case GalImageFormat.ASTC_10x8_UNORM_BLOCK: return 8;
  133. case GalImageFormat.ASTC_12x10_UNORM_BLOCK: return 10;
  134. case GalImageFormat.ASTC_8x5_UNORM_BLOCK: return 5;
  135. case GalImageFormat.ASTC_10x5_UNORM_BLOCK: return 5;
  136. case GalImageFormat.ASTC_10x6_UNORM_BLOCK: return 6;
  137. }
  138. throw new ArgumentException(nameof(Format));
  139. }
  140. public bool TryGetCachedTexture(long Key, long DataSize, out GalImage Image)
  141. {
  142. if (TextureCache.TryGetSize(Key, out long Size) && Size == DataSize)
  143. {
  144. if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
  145. {
  146. Image = CachedImage.Image;
  147. return true;
  148. }
  149. }
  150. Image = default(GalImage);
  151. return false;
  152. }
  153. public void Bind(long Key, int Index)
  154. {
  155. if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
  156. {
  157. GL.ActiveTexture(TextureUnit.Texture0 + Index);
  158. GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle);
  159. }
  160. }
  161. public void SetSampler(GalTextureSampler Sampler)
  162. {
  163. int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU);
  164. int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
  165. int MinFilter = (int)OGLEnumConverter.GetTextureMinFilter(Sampler.MinFilter, Sampler.MipFilter);
  166. int MagFilter = (int)OGLEnumConverter.GetTextureMagFilter(Sampler.MagFilter);
  167. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, WrapS);
  168. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, WrapT);
  169. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter);
  170. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter);
  171. float[] Color = new float[]
  172. {
  173. Sampler.BorderColor.Red,
  174. Sampler.BorderColor.Green,
  175. Sampler.BorderColor.Blue,
  176. Sampler.BorderColor.Alpha
  177. };
  178. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color);
  179. }
  180. private static bool IsCompressedTextureFormat(GalImageFormat Format)
  181. {
  182. switch (Format)
  183. {
  184. case GalImageFormat.BC6H_UFLOAT_BLOCK:
  185. case GalImageFormat.BC6H_SFLOAT_BLOCK:
  186. case GalImageFormat.BC7_UNORM_BLOCK:
  187. case GalImageFormat.BC1_RGBA_UNORM_BLOCK:
  188. case GalImageFormat.BC2_UNORM_BLOCK:
  189. case GalImageFormat.BC3_UNORM_BLOCK:
  190. case GalImageFormat.BC4_SNORM_BLOCK:
  191. case GalImageFormat.BC4_UNORM_BLOCK:
  192. case GalImageFormat.BC5_SNORM_BLOCK:
  193. case GalImageFormat.BC5_UNORM_BLOCK:
  194. return true;
  195. }
  196. return false;
  197. }
  198. }
  199. }