Framebuffer.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Graphics.GAL;
  3. using Ryujinx.Graphics.OpenGL.Image;
  4. using System;
  5. namespace Ryujinx.Graphics.OpenGL
  6. {
  7. class Framebuffer : IDisposable
  8. {
  9. public int Handle { get; private set; }
  10. private FramebufferAttachment _lastDsAttachment;
  11. private readonly TextureView[] _colors;
  12. private int _colorsCount;
  13. private bool _dualSourceBlend;
  14. public Framebuffer()
  15. {
  16. Handle = GL.GenFramebuffer();
  17. _colors = new TextureView[8];
  18. }
  19. public int Bind()
  20. {
  21. GL.BindFramebuffer(FramebufferTarget.Framebuffer, Handle);
  22. return Handle;
  23. }
  24. public void AttachColor(int index, TextureView color)
  25. {
  26. FramebufferAttachment attachment = FramebufferAttachment.ColorAttachment0 + index;
  27. if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Amd ||
  28. HwCapabilities.Vendor == HwCapabilities.GpuVendor.Intel)
  29. {
  30. GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.GetIncompatibleFormatViewHandle() ?? 0, 0);
  31. _colors[index] = color;
  32. }
  33. else
  34. {
  35. GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.Handle ?? 0, 0);
  36. }
  37. }
  38. public void AttachDepthStencil(TextureView depthStencil)
  39. {
  40. // Detach the last depth/stencil buffer if there is any.
  41. if (_lastDsAttachment != 0)
  42. {
  43. GL.FramebufferTexture(FramebufferTarget.Framebuffer, _lastDsAttachment, 0, 0);
  44. }
  45. if (depthStencil != null)
  46. {
  47. FramebufferAttachment attachment;
  48. if (IsPackedDepthStencilFormat(depthStencil.Format))
  49. {
  50. attachment = FramebufferAttachment.DepthStencilAttachment;
  51. }
  52. else if (IsDepthOnlyFormat(depthStencil.Format))
  53. {
  54. attachment = FramebufferAttachment.DepthAttachment;
  55. }
  56. else
  57. {
  58. attachment = FramebufferAttachment.StencilAttachment;
  59. }
  60. GL.FramebufferTexture(
  61. FramebufferTarget.Framebuffer,
  62. attachment,
  63. depthStencil.Handle,
  64. 0);
  65. _lastDsAttachment = attachment;
  66. }
  67. else
  68. {
  69. _lastDsAttachment = 0;
  70. }
  71. }
  72. public void SignalModified()
  73. {
  74. if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Amd ||
  75. HwCapabilities.Vendor == HwCapabilities.GpuVendor.Intel)
  76. {
  77. for (int i = 0; i < 8; i++)
  78. {
  79. if (_colors[i] != null)
  80. {
  81. _colors[i].SignalModified();
  82. }
  83. }
  84. }
  85. }
  86. public void SetDualSourceBlend(bool enable)
  87. {
  88. bool oldEnable = _dualSourceBlend;
  89. _dualSourceBlend = enable;
  90. // When dual source blend is used,
  91. // we can only have one draw buffer.
  92. if (enable)
  93. {
  94. GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
  95. }
  96. else if (oldEnable)
  97. {
  98. SetDrawBuffersImpl(_colorsCount);
  99. }
  100. }
  101. public void SetDrawBuffers(int colorsCount)
  102. {
  103. if (_colorsCount != colorsCount && !_dualSourceBlend)
  104. {
  105. SetDrawBuffersImpl(colorsCount);
  106. }
  107. _colorsCount = colorsCount;
  108. }
  109. private void SetDrawBuffersImpl(int colorsCount)
  110. {
  111. DrawBuffersEnum[] drawBuffers = new DrawBuffersEnum[colorsCount];
  112. for (int index = 0; index < colorsCount; index++)
  113. {
  114. drawBuffers[index] = DrawBuffersEnum.ColorAttachment0 + index;
  115. }
  116. GL.DrawBuffers(colorsCount, drawBuffers);
  117. }
  118. private static bool IsPackedDepthStencilFormat(Format format)
  119. {
  120. return format == Format.D24UnormS8Uint ||
  121. format == Format.D32FloatS8Uint;
  122. }
  123. private static bool IsDepthOnlyFormat(Format format)
  124. {
  125. return format == Format.D16Unorm ||
  126. format == Format.D24X8Unorm ||
  127. format == Format.D32Float;
  128. }
  129. public void Dispose()
  130. {
  131. if (Handle != 0)
  132. {
  133. GL.DeleteFramebuffer(Handle);
  134. Handle = 0;
  135. }
  136. }
  137. }
  138. }