TextureView.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Graphics.GAL;
  3. using Ryujinx.Graphics.GAL.Texture;
  4. using System;
  5. namespace Ryujinx.Graphics.OpenGL
  6. {
  7. class TextureView : ITexture
  8. {
  9. public int Handle { get; private set; }
  10. private Renderer _renderer;
  11. private TextureStorage _parent;
  12. private TextureView _emulatedViewParent;
  13. private TextureCreateInfo _info;
  14. private int _firstLayer;
  15. private int _firstLevel;
  16. private bool _acquired;
  17. private bool _pendingDelete;
  18. public int Width => _info.Width;
  19. public int Height => _info.Height;
  20. public int DepthOrLayers => _info.GetDepthOrLayers();
  21. public int Levels => _info.Levels;
  22. public Target Target => _info.Target;
  23. public Format Format => _info.Format;
  24. public int BlockWidth => _info.BlockWidth;
  25. public int BlockHeight => _info.BlockHeight;
  26. public bool IsCompressed => _info.IsCompressed;
  27. public TextureView(
  28. Renderer renderer,
  29. TextureStorage parent,
  30. TextureCreateInfo info,
  31. int firstLayer,
  32. int firstLevel)
  33. {
  34. _renderer = renderer;
  35. _parent = parent;
  36. _info = info;
  37. _firstLayer = firstLayer;
  38. _firstLevel = firstLevel;
  39. Handle = GL.GenTexture();
  40. CreateView();
  41. }
  42. private void CreateView()
  43. {
  44. TextureTarget target = Target.Convert();
  45. FormatInfo format = FormatTable.GetFormatInfo(_info.Format);
  46. PixelInternalFormat pixelInternalFormat;
  47. if (format.IsCompressed)
  48. {
  49. pixelInternalFormat = (PixelInternalFormat)format.PixelFormat;
  50. }
  51. else
  52. {
  53. pixelInternalFormat = format.PixelInternalFormat;
  54. }
  55. GL.TextureView(
  56. Handle,
  57. target,
  58. _parent.Handle,
  59. pixelInternalFormat,
  60. _firstLevel,
  61. _info.Levels,
  62. _firstLayer,
  63. _info.GetLayers());
  64. GL.ActiveTexture(TextureUnit.Texture0);
  65. GL.BindTexture(target, Handle);
  66. int[] swizzleRgba = new int[]
  67. {
  68. (int)_info.SwizzleR.Convert(),
  69. (int)_info.SwizzleG.Convert(),
  70. (int)_info.SwizzleB.Convert(),
  71. (int)_info.SwizzleA.Convert()
  72. };
  73. GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
  74. int maxLevel = _info.Levels - 1;
  75. if (maxLevel < 0)
  76. {
  77. maxLevel = 0;
  78. }
  79. GL.TexParameter(target, TextureParameterName.TextureMaxLevel, maxLevel);
  80. // GL.TexParameter(target, TextureParameterName.DepthStencilTextureMode, (int)_info.DepthStencilMode.Convert());
  81. }
  82. public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
  83. {
  84. if (_info.IsCompressed == info.IsCompressed)
  85. {
  86. firstLayer += _firstLayer;
  87. firstLevel += _firstLevel;
  88. return _parent.CreateView(info, firstLayer, firstLevel);
  89. }
  90. else
  91. {
  92. // TODO: Improve
  93. TextureView emulatedView = (TextureView)_renderer.CreateTexture(info);
  94. emulatedView._emulatedViewParent = this;
  95. emulatedView._firstLayer = firstLayer;
  96. emulatedView._firstLevel = firstLevel;
  97. return emulatedView;
  98. }
  99. }
  100. public int GetStorageDebugId()
  101. {
  102. return _parent.GetHashCode();
  103. }
  104. public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
  105. {
  106. TextureView destinationView = (TextureView)destination;
  107. TextureCopyUnscaled.Copy(this, destinationView, firstLayer, firstLevel);
  108. int width = Math.Min(Width, destinationView.Width);
  109. int height = Math.Min(Height, destinationView.Height);
  110. int depth = Math.Min(_info.GetDepthOrLayers(), destinationView._info.GetDepthOrLayers());
  111. int levels = Math.Min(_info.Levels, destinationView._info.Levels);
  112. if (destinationView._emulatedViewParent != null)
  113. {
  114. TextureCopyUnscaled.Copy(
  115. this,
  116. destinationView._emulatedViewParent,
  117. destinationView._firstLayer,
  118. destinationView._firstLevel);
  119. }
  120. }
  121. public void CopyTo(ITexture destination, Extents2D srcRegion, Extents2D dstRegion, bool linearFilter)
  122. {
  123. _renderer.TextureCopy.Copy(this, (TextureView)destination, srcRegion, dstRegion, linearFilter);
  124. }
  125. public byte[] GetData()
  126. {
  127. int size = 0;
  128. for (int level = 0; level < _info.Levels; level++)
  129. {
  130. size += _info.GetMipSize(level);
  131. }
  132. byte[] data = new byte[size];
  133. unsafe
  134. {
  135. fixed (byte* ptr = data)
  136. {
  137. WriteTo((IntPtr)ptr);
  138. }
  139. }
  140. return data;
  141. }
  142. private void WriteTo(IntPtr ptr)
  143. {
  144. TextureTarget target = Target.Convert();
  145. Bind(target, 0);
  146. FormatInfo format = FormatTable.GetFormatInfo(_info.Format);
  147. int faces = 1;
  148. if (target == TextureTarget.TextureCubeMap)
  149. {
  150. target = TextureTarget.TextureCubeMapPositiveX;
  151. faces = 6;
  152. }
  153. for (int level = 0; level < _info.Levels; level++)
  154. {
  155. for (int face = 0; face < faces; face++)
  156. {
  157. int faceOffset = face * _info.GetMipSize2D(level);
  158. if (format.IsCompressed)
  159. {
  160. GL.GetCompressedTexImage(target + face, level, ptr + faceOffset);
  161. }
  162. else
  163. {
  164. GL.GetTexImage(
  165. target + face,
  166. level,
  167. format.PixelFormat,
  168. format.PixelType,
  169. ptr + faceOffset);
  170. }
  171. }
  172. ptr += _info.GetMipSize(level);
  173. }
  174. }
  175. public void SetData(Span<byte> data)
  176. {
  177. unsafe
  178. {
  179. fixed (byte* ptr = data)
  180. {
  181. SetData((IntPtr)ptr, data.Length);
  182. }
  183. }
  184. }
  185. private void SetData(IntPtr data, int size)
  186. {
  187. TextureTarget target = Target.Convert();
  188. Bind(target, 0);
  189. FormatInfo format = FormatTable.GetFormatInfo(_info.Format);
  190. int width = _info.Width;
  191. int height = _info.Height;
  192. int depth = _info.Depth;
  193. int offset = 0;
  194. for (int level = 0; level < _info.Levels; level++)
  195. {
  196. int mipSize = _info.GetMipSize(level);
  197. int endOffset = offset + mipSize;
  198. if ((uint)endOffset > (uint)size)
  199. {
  200. return;
  201. }
  202. switch (_info.Target)
  203. {
  204. case Target.Texture1D:
  205. if (format.IsCompressed)
  206. {
  207. GL.CompressedTexSubImage1D(
  208. target,
  209. level,
  210. 0,
  211. width,
  212. format.PixelFormat,
  213. mipSize,
  214. data);
  215. }
  216. else
  217. {
  218. GL.TexSubImage1D(
  219. target,
  220. level,
  221. 0,
  222. width,
  223. format.PixelFormat,
  224. format.PixelType,
  225. data);
  226. }
  227. break;
  228. case Target.Texture1DArray:
  229. case Target.Texture2D:
  230. if (format.IsCompressed)
  231. {
  232. GL.CompressedTexSubImage2D(
  233. target,
  234. level,
  235. 0,
  236. 0,
  237. width,
  238. height,
  239. format.PixelFormat,
  240. mipSize,
  241. data);
  242. }
  243. else
  244. {
  245. GL.TexSubImage2D(
  246. target,
  247. level,
  248. 0,
  249. 0,
  250. width,
  251. height,
  252. format.PixelFormat,
  253. format.PixelType,
  254. data);
  255. }
  256. break;
  257. case Target.Texture2DArray:
  258. case Target.Texture3D:
  259. case Target.CubemapArray:
  260. if (format.IsCompressed)
  261. {
  262. GL.CompressedTexSubImage3D(
  263. target,
  264. level,
  265. 0,
  266. 0,
  267. 0,
  268. width,
  269. height,
  270. depth,
  271. format.PixelFormat,
  272. mipSize,
  273. data);
  274. }
  275. else
  276. {
  277. GL.TexSubImage3D(
  278. target,
  279. level,
  280. 0,
  281. 0,
  282. 0,
  283. width,
  284. height,
  285. depth,
  286. format.PixelFormat,
  287. format.PixelType,
  288. data);
  289. }
  290. break;
  291. case Target.Cubemap:
  292. int faceOffset = 0;
  293. for (int face = 0; face < 6; face++, faceOffset += mipSize / 6)
  294. {
  295. if (format.IsCompressed)
  296. {
  297. GL.CompressedTexSubImage2D(
  298. TextureTarget.TextureCubeMapPositiveX + face,
  299. level,
  300. 0,
  301. 0,
  302. width,
  303. height,
  304. format.PixelFormat,
  305. mipSize / 6,
  306. data + faceOffset);
  307. }
  308. else
  309. {
  310. GL.TexSubImage2D(
  311. TextureTarget.TextureCubeMapPositiveX + face,
  312. level,
  313. 0,
  314. 0,
  315. width,
  316. height,
  317. format.PixelFormat,
  318. format.PixelType,
  319. data + faceOffset);
  320. }
  321. }
  322. break;
  323. }
  324. data += mipSize;
  325. offset += mipSize;
  326. width = Math.Max(1, width >> 1);
  327. height = Math.Max(1, height >> 1);
  328. if (Target == Target.Texture3D)
  329. {
  330. depth = Math.Max(1, depth >> 1);
  331. }
  332. }
  333. }
  334. public void Bind(int unit)
  335. {
  336. Bind(Target.Convert(), unit);
  337. }
  338. private void Bind(TextureTarget target, int unit)
  339. {
  340. GL.ActiveTexture(TextureUnit.Texture0 + unit);
  341. GL.BindTexture(target, Handle);
  342. }
  343. public void Acquire()
  344. {
  345. _acquired = true;
  346. }
  347. public void Release()
  348. {
  349. _acquired = false;
  350. if (_pendingDelete)
  351. {
  352. _pendingDelete = false;
  353. Dispose();
  354. }
  355. }
  356. public void Dispose()
  357. {
  358. if (_acquired)
  359. {
  360. _pendingDelete = true;
  361. return;
  362. }
  363. if (Handle != 0)
  364. {
  365. GL.DeleteTexture(Handle);
  366. _parent.DecrementViewsCount();
  367. Handle = 0;
  368. }
  369. }
  370. }
  371. }