OGLTexture.cs 6.5 KB

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