OGLTexture.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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 const long MaxTextureCacheSize = 768 * 1024 * 1024;
  9. private OGLCachedResource<ImageHandler> TextureCache;
  10. public EventHandler<int> TextureDeleted { get; set; }
  11. public OGLTexture()
  12. {
  13. TextureCache = new OGLCachedResource<ImageHandler>(DeleteTexture, MaxTextureCacheSize);
  14. }
  15. public void LockCache()
  16. {
  17. TextureCache.Lock();
  18. }
  19. public void UnlockCache()
  20. {
  21. TextureCache.Unlock();
  22. }
  23. private void DeleteTexture(ImageHandler CachedImage)
  24. {
  25. TextureDeleted?.Invoke(this, CachedImage.Handle);
  26. GL.DeleteTexture(CachedImage.Handle);
  27. }
  28. public void Create(long Key, int Size, GalImage Image)
  29. {
  30. int Handle = GL.GenTexture();
  31. GL.BindTexture(TextureTarget.Texture2D, Handle);
  32. const int Level = 0; //TODO: Support mipmap textures.
  33. const int Border = 0;
  34. TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Size);
  35. if (ImageUtils.IsCompressed(Image.Format))
  36. {
  37. throw new InvalidOperationException("Surfaces with compressed formats are not supported!");
  38. }
  39. (PixelInternalFormat InternalFmt,
  40. PixelFormat Format,
  41. PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
  42. GL.TexImage2D(
  43. TextureTarget.Texture2D,
  44. Level,
  45. InternalFmt,
  46. Image.Width,
  47. Image.Height,
  48. Border,
  49. Format,
  50. Type,
  51. IntPtr.Zero);
  52. }
  53. public void Create(long Key, byte[] Data, GalImage Image)
  54. {
  55. int Handle = GL.GenTexture();
  56. GL.BindTexture(TextureTarget.Texture2D, Handle);
  57. const int Level = 0; //TODO: Support mipmap textures.
  58. const int Border = 0;
  59. TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length);
  60. if (ImageUtils.IsCompressed(Image.Format) && !IsAstc(Image.Format))
  61. {
  62. InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format);
  63. GL.CompressedTexImage2D(
  64. TextureTarget.Texture2D,
  65. Level,
  66. InternalFmt,
  67. Image.Width,
  68. Image.Height,
  69. Border,
  70. Data.Length,
  71. Data);
  72. }
  73. else
  74. {
  75. //TODO: Use KHR_texture_compression_astc_hdr when available
  76. if (IsAstc(Image.Format))
  77. {
  78. int TextureBlockWidth = ImageUtils.GetBlockWidth(Image.Format);
  79. int TextureBlockHeight = ImageUtils.GetBlockHeight(Image.Format);
  80. Data = ASTCDecoder.DecodeToRGBA8888(
  81. Data,
  82. TextureBlockWidth,
  83. TextureBlockHeight, 1,
  84. Image.Width,
  85. Image.Height, 1);
  86. Image.Format = GalImageFormat.RGBA8 | (Image.Format & GalImageFormat.TypeMask);
  87. }
  88. (PixelInternalFormat InternalFmt,
  89. PixelFormat Format,
  90. PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
  91. GL.TexImage2D(
  92. TextureTarget.Texture2D,
  93. Level,
  94. InternalFmt,
  95. Image.Width,
  96. Image.Height,
  97. Border,
  98. Format,
  99. Type,
  100. Data);
  101. }
  102. }
  103. private static bool IsAstc(GalImageFormat Format)
  104. {
  105. Format &= GalImageFormat.FormatMask;
  106. return Format > GalImageFormat.Astc2DStart && Format < GalImageFormat.Astc2DEnd;
  107. }
  108. public bool TryGetImage(long Key, out GalImage Image)
  109. {
  110. if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
  111. {
  112. Image = CachedImage.Image;
  113. return true;
  114. }
  115. Image = default(GalImage);
  116. return false;
  117. }
  118. public bool TryGetImageHandler(long Key, out ImageHandler CachedImage)
  119. {
  120. if (TextureCache.TryGetValue(Key, out CachedImage))
  121. {
  122. return true;
  123. }
  124. CachedImage = null;
  125. return false;
  126. }
  127. public void Bind(long Key, int Index, GalImage Image)
  128. {
  129. if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
  130. {
  131. GL.ActiveTexture(TextureUnit.Texture0 + Index);
  132. GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle);
  133. int[] SwizzleRgba = new int[]
  134. {
  135. (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource),
  136. (int)OGLEnumConverter.GetTextureSwizzle(Image.YSource),
  137. (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource),
  138. (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource)
  139. };
  140. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, SwizzleRgba);
  141. }
  142. }
  143. public void SetSampler(GalTextureSampler Sampler)
  144. {
  145. int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU);
  146. int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
  147. int MinFilter = (int)OGLEnumConverter.GetTextureMinFilter(Sampler.MinFilter, Sampler.MipFilter);
  148. int MagFilter = (int)OGLEnumConverter.GetTextureMagFilter(Sampler.MagFilter);
  149. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, WrapS);
  150. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, WrapT);
  151. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter);
  152. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter);
  153. float[] Color = new float[]
  154. {
  155. Sampler.BorderColor.Red,
  156. Sampler.BorderColor.Green,
  157. Sampler.BorderColor.Blue,
  158. Sampler.BorderColor.Alpha
  159. };
  160. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color);
  161. }
  162. }
  163. }