OGLTexture.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Graphics.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, int Size, GalImage Image)
  26. {
  27. int Handle = GL.GenTexture();
  28. GL.BindTexture(TextureTarget.Texture2D, Handle);
  29. const int Level = 0; //TODO: Support mipmap textures.
  30. const int Border = 0;
  31. TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Size);
  32. GalImageFormat TypeLess = Image.Format & GalImageFormat.FormatMask;
  33. bool IsASTC = TypeLess >= GalImageFormat.ASTC_BEGIN && TypeLess <= GalImageFormat.ASTC_END;
  34. if (ImageUtils.IsCompressed(Image.Format) && !IsASTC)
  35. {
  36. InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format);
  37. GL.CompressedTexImage2D(
  38. TextureTarget.Texture2D,
  39. Level,
  40. InternalFmt,
  41. Image.Width,
  42. Image.Height,
  43. Border,
  44. Size,
  45. IntPtr.Zero);
  46. }
  47. else
  48. {
  49. (PixelInternalFormat InternalFmt,
  50. PixelFormat Format,
  51. PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
  52. GL.TexImage2D(
  53. TextureTarget.Texture2D,
  54. Level,
  55. InternalFmt,
  56. Image.Width,
  57. Image.Height,
  58. Border,
  59. Format,
  60. Type,
  61. IntPtr.Zero);
  62. }
  63. }
  64. public void Create(long Key, byte[] Data, GalImage Image)
  65. {
  66. int Handle = GL.GenTexture();
  67. GL.BindTexture(TextureTarget.Texture2D, Handle);
  68. const int Level = 0; //TODO: Support mipmap textures.
  69. const int Border = 0;
  70. TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length);
  71. GalImageFormat TypeLess = Image.Format & GalImageFormat.FormatMask;
  72. bool IsASTC = TypeLess >= GalImageFormat.ASTC_BEGIN && TypeLess <= GalImageFormat.ASTC_END;
  73. if (ImageUtils.IsCompressed(Image.Format) && !IsASTC)
  74. {
  75. InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format);
  76. GL.CompressedTexImage2D(
  77. TextureTarget.Texture2D,
  78. Level,
  79. InternalFmt,
  80. Image.Width,
  81. Image.Height,
  82. Border,
  83. Data.Length,
  84. Data);
  85. }
  86. else
  87. {
  88. //TODO: Use KHR_texture_compression_astc_hdr when available
  89. if (IsASTC)
  90. {
  91. int TextureBlockWidth = ImageUtils.GetBlockWidth(Image.Format);
  92. int TextureBlockHeight = ImageUtils.GetBlockHeight(Image.Format);
  93. Data = ASTCDecoder.DecodeToRGBA8888(
  94. Data,
  95. TextureBlockWidth,
  96. TextureBlockHeight, 1,
  97. Image.Width,
  98. Image.Height, 1);
  99. Image.Format = GalImageFormat.A8B8G8R8 | GalImageFormat.Unorm;
  100. }
  101. else if (TypeLess == GalImageFormat.G8R8)
  102. {
  103. Data = ImageConverter.G8R8ToR8G8(
  104. Data,
  105. Image.Width,
  106. Image.Height,
  107. 1);
  108. Image.Format = GalImageFormat.R8G8 | (Image.Format & GalImageFormat.TypeMask);
  109. }
  110. (PixelInternalFormat InternalFmt,
  111. PixelFormat Format,
  112. PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
  113. GL.TexImage2D(
  114. TextureTarget.Texture2D,
  115. Level,
  116. InternalFmt,
  117. Image.Width,
  118. Image.Height,
  119. Border,
  120. Format,
  121. Type,
  122. Data);
  123. }
  124. }
  125. public bool TryGetImage(long Key, out GalImage Image)
  126. {
  127. if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
  128. {
  129. Image = CachedImage.Image;
  130. return true;
  131. }
  132. Image = default(GalImage);
  133. return false;
  134. }
  135. public bool TryGetImageHandler(long Key, out ImageHandler CachedImage)
  136. {
  137. if (TextureCache.TryGetValue(Key, out CachedImage))
  138. {
  139. return true;
  140. }
  141. CachedImage = null;
  142. return false;
  143. }
  144. public void Bind(long Key, int Index, GalImage Image)
  145. {
  146. if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
  147. {
  148. GL.ActiveTexture(TextureUnit.Texture0 + Index);
  149. GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle);
  150. int[] SwizzleRgba = new int[]
  151. {
  152. (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource),
  153. (int)OGLEnumConverter.GetTextureSwizzle(Image.YSource),
  154. (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource),
  155. (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource)
  156. };
  157. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, SwizzleRgba);
  158. }
  159. }
  160. public void SetSampler(GalTextureSampler Sampler)
  161. {
  162. int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU);
  163. int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
  164. int MinFilter = (int)OGLEnumConverter.GetTextureMinFilter(Sampler.MinFilter, Sampler.MipFilter);
  165. int MagFilter = (int)OGLEnumConverter.GetTextureMagFilter(Sampler.MagFilter);
  166. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, WrapS);
  167. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, WrapT);
  168. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter);
  169. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter);
  170. float[] Color = new float[]
  171. {
  172. Sampler.BorderColor.Red,
  173. Sampler.BorderColor.Green,
  174. Sampler.BorderColor.Blue,
  175. Sampler.BorderColor.Alpha
  176. };
  177. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color);
  178. }
  179. }
  180. }