TextureCopy.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using Ryujinx.Graphics.GAL;
  2. using OpenTK.Graphics.OpenGL;
  3. using System;
  4. namespace Ryujinx.Graphics.OpenGL
  5. {
  6. class TextureCopy : IDisposable
  7. {
  8. private int _srcFramebuffer;
  9. private int _dstFramebuffer;
  10. public void Copy(
  11. TextureView src,
  12. TextureView dst,
  13. Extents2D srcRegion,
  14. Extents2D dstRegion,
  15. bool linearFilter)
  16. {
  17. int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
  18. int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
  19. GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetSrcFramebufferLazy());
  20. GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetDstFramebufferLazy());
  21. Attach(FramebufferTarget.ReadFramebuffer, src.Format, src.Handle);
  22. Attach(FramebufferTarget.DrawFramebuffer, dst.Format, dst.Handle);
  23. ClearBufferMask mask = GetMask(src.Format);
  24. BlitFramebufferFilter filter = linearFilter
  25. ? BlitFramebufferFilter.Linear
  26. : BlitFramebufferFilter.Nearest;
  27. GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
  28. GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
  29. GL.BlitFramebuffer(
  30. srcRegion.X1,
  31. srcRegion.Y1,
  32. srcRegion.X2,
  33. srcRegion.Y2,
  34. dstRegion.X1,
  35. dstRegion.Y1,
  36. dstRegion.X2,
  37. dstRegion.Y2,
  38. mask,
  39. filter);
  40. GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
  41. GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
  42. }
  43. private static void Attach(FramebufferTarget target, Format format, int handle)
  44. {
  45. if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint)
  46. {
  47. GL.FramebufferTexture(target, FramebufferAttachment.DepthStencilAttachment, handle, 0);
  48. }
  49. else if (IsDepthOnly(format))
  50. {
  51. GL.FramebufferTexture(target, FramebufferAttachment.DepthAttachment, handle, 0);
  52. }
  53. else if (format == Format.S8Uint)
  54. {
  55. GL.FramebufferTexture(target, FramebufferAttachment.StencilAttachment, handle, 0);
  56. }
  57. else
  58. {
  59. GL.FramebufferTexture(target, FramebufferAttachment.ColorAttachment0, handle, 0);
  60. }
  61. }
  62. private static ClearBufferMask GetMask(Format format)
  63. {
  64. if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint)
  65. {
  66. return ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit;
  67. }
  68. else if (IsDepthOnly(format))
  69. {
  70. return ClearBufferMask.DepthBufferBit;
  71. }
  72. else if (format == Format.S8Uint)
  73. {
  74. return ClearBufferMask.StencilBufferBit;
  75. }
  76. else
  77. {
  78. return ClearBufferMask.ColorBufferBit;
  79. }
  80. }
  81. private static bool IsDepthOnly(Format format)
  82. {
  83. return format == Format.D16Unorm ||
  84. format == Format.D24X8Unorm ||
  85. format == Format.D32Float;
  86. }
  87. private int GetSrcFramebufferLazy()
  88. {
  89. if (_srcFramebuffer == 0)
  90. {
  91. _srcFramebuffer = GL.GenFramebuffer();
  92. }
  93. return _srcFramebuffer;
  94. }
  95. private int GetDstFramebufferLazy()
  96. {
  97. if (_dstFramebuffer == 0)
  98. {
  99. _dstFramebuffer = GL.GenFramebuffer();
  100. }
  101. return _dstFramebuffer;
  102. }
  103. public void Dispose()
  104. {
  105. if (_srcFramebuffer != 0)
  106. {
  107. GL.DeleteFramebuffer(_srcFramebuffer);
  108. _srcFramebuffer = 0;
  109. }
  110. if (_dstFramebuffer != 0)
  111. {
  112. GL.DeleteFramebuffer(_dstFramebuffer);
  113. _dstFramebuffer = 0;
  114. }
  115. }
  116. }
  117. }