OGLTexture.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Graphics.Gal.Texture;
  3. using System;
  4. namespace Ryujinx.Graphics.Gal.OpenGL
  5. {
  6. class OGLTexture
  7. {
  8. private class TCE
  9. {
  10. public int Handle;
  11. public GalTexture Texture;
  12. public TCE(int Handle, GalTexture Texture)
  13. {
  14. this.Handle = Handle;
  15. this.Texture = Texture;
  16. }
  17. }
  18. private OGLCachedResource<TCE> TextureCache;
  19. public OGLTexture()
  20. {
  21. TextureCache = new OGLCachedResource<TCE>(DeleteTexture);
  22. }
  23. private static void DeleteTexture(TCE CachedTexture)
  24. {
  25. GL.DeleteTexture(CachedTexture.Handle);
  26. }
  27. public void Create(long Tag, byte[] Data, GalTexture Texture)
  28. {
  29. int Handle = GL.GenTexture();
  30. TextureCache.AddOrUpdate(Tag, new TCE(Handle, Texture), (uint)Data.Length);
  31. GL.BindTexture(TextureTarget.Texture2D, Handle);
  32. const int Level = 0; //TODO: Support mipmap textures.
  33. const int Border = 0;
  34. if (IsCompressedTextureFormat(Texture.Format))
  35. {
  36. PixelInternalFormat InternalFmt = OGLEnumConverter.GetCompressedTextureFormat(Texture.Format);
  37. GL.CompressedTexImage2D(
  38. TextureTarget.Texture2D,
  39. Level,
  40. InternalFmt,
  41. Texture.Width,
  42. Texture.Height,
  43. Border,
  44. Data.Length,
  45. Data);
  46. }
  47. else
  48. {
  49. if (Texture.Format >= GalTextureFormat.Astc2D4x4)
  50. {
  51. int TextureBlockWidth = GetAstcBlockWidth(Texture.Format);
  52. int TextureBlockHeight = GetAstcBlockHeight(Texture.Format);
  53. Data = ASTCDecoder.DecodeToRGBA8888(
  54. Data,
  55. TextureBlockWidth,
  56. TextureBlockHeight, 1,
  57. Texture.Width,
  58. Texture.Height, 1);
  59. Texture.Format = GalTextureFormat.A8B8G8R8;
  60. }
  61. const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
  62. (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(Texture.Format);
  63. GL.TexImage2D(
  64. TextureTarget.Texture2D,
  65. Level,
  66. InternalFmt,
  67. Texture.Width,
  68. Texture.Height,
  69. Border,
  70. Format,
  71. Type,
  72. Data);
  73. }
  74. int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Texture.XSource);
  75. int SwizzleG = (int)OGLEnumConverter.GetTextureSwizzle(Texture.YSource);
  76. int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Texture.ZSource);
  77. int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Texture.WSource);
  78. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, SwizzleR);
  79. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, SwizzleG);
  80. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, SwizzleB);
  81. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA);
  82. }
  83. private static int GetAstcBlockWidth(GalTextureFormat Format)
  84. {
  85. switch (Format)
  86. {
  87. case GalTextureFormat.Astc2D4x4: return 4;
  88. case GalTextureFormat.Astc2D5x5: return 5;
  89. case GalTextureFormat.Astc2D6x6: return 6;
  90. case GalTextureFormat.Astc2D8x8: return 8;
  91. case GalTextureFormat.Astc2D10x10: return 10;
  92. case GalTextureFormat.Astc2D12x12: return 12;
  93. case GalTextureFormat.Astc2D5x4: return 5;
  94. case GalTextureFormat.Astc2D6x5: return 6;
  95. case GalTextureFormat.Astc2D8x6: return 8;
  96. case GalTextureFormat.Astc2D10x8: return 10;
  97. case GalTextureFormat.Astc2D12x10: return 12;
  98. case GalTextureFormat.Astc2D8x5: return 8;
  99. case GalTextureFormat.Astc2D10x5: return 10;
  100. case GalTextureFormat.Astc2D10x6: return 10;
  101. }
  102. throw new ArgumentException(nameof(Format));
  103. }
  104. private static int GetAstcBlockHeight(GalTextureFormat Format)
  105. {
  106. switch (Format)
  107. {
  108. case GalTextureFormat.Astc2D4x4: return 4;
  109. case GalTextureFormat.Astc2D5x5: return 5;
  110. case GalTextureFormat.Astc2D6x6: return 6;
  111. case GalTextureFormat.Astc2D8x8: return 8;
  112. case GalTextureFormat.Astc2D10x10: return 10;
  113. case GalTextureFormat.Astc2D12x12: return 12;
  114. case GalTextureFormat.Astc2D5x4: return 4;
  115. case GalTextureFormat.Astc2D6x5: return 5;
  116. case GalTextureFormat.Astc2D8x6: return 6;
  117. case GalTextureFormat.Astc2D10x8: return 8;
  118. case GalTextureFormat.Astc2D12x10: return 10;
  119. case GalTextureFormat.Astc2D8x5: return 5;
  120. case GalTextureFormat.Astc2D10x5: return 5;
  121. case GalTextureFormat.Astc2D10x6: return 6;
  122. }
  123. throw new ArgumentException(nameof(Format));
  124. }
  125. public bool TryGetCachedTexture(long Tag, long DataSize, out GalTexture Texture)
  126. {
  127. if (TextureCache.TryGetSize(Tag, out long Size) && Size == DataSize)
  128. {
  129. if (TextureCache.TryGetValue(Tag, out TCE CachedTexture))
  130. {
  131. Texture = CachedTexture.Texture;
  132. return true;
  133. }
  134. }
  135. Texture = default(GalTexture);
  136. return false;
  137. }
  138. public void Bind(long Tag, int Index)
  139. {
  140. if (TextureCache.TryGetValue(Tag, out TCE CachedTexture))
  141. {
  142. GL.ActiveTexture(TextureUnit.Texture0 + Index);
  143. GL.BindTexture(TextureTarget.Texture2D, CachedTexture.Handle);
  144. }
  145. }
  146. public static void Set(GalTextureSampler Sampler)
  147. {
  148. int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU);
  149. int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
  150. int MinFilter = (int)OGLEnumConverter.GetTextureMinFilter(Sampler.MinFilter, Sampler.MipFilter);
  151. int MagFilter = (int)OGLEnumConverter.GetTextureMagFilter(Sampler.MagFilter);
  152. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, WrapS);
  153. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, WrapT);
  154. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter);
  155. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter);
  156. float[] Color = new float[]
  157. {
  158. Sampler.BorderColor.Red,
  159. Sampler.BorderColor.Green,
  160. Sampler.BorderColor.Blue,
  161. Sampler.BorderColor.Alpha
  162. };
  163. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color);
  164. }
  165. private static bool IsCompressedTextureFormat(GalTextureFormat Format)
  166. {
  167. switch (Format)
  168. {
  169. case GalTextureFormat.BC7U:
  170. case GalTextureFormat.BC1:
  171. case GalTextureFormat.BC2:
  172. case GalTextureFormat.BC3:
  173. case GalTextureFormat.BC4:
  174. case GalTextureFormat.BC5:
  175. return true;
  176. }
  177. return false;
  178. }
  179. }
  180. }