OGLTexture.cs 6.6 KB

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