Window.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Graphics.GAL;
  3. using System;
  4. using System.Collections.Generic;
  5. namespace Ryujinx.Graphics.OpenGL
  6. {
  7. class Window : IWindow
  8. {
  9. private const int NativeWidth = 1280;
  10. private const int NativeHeight = 720;
  11. private int _width = 1280;
  12. private int _height = 720;
  13. private int _blitFramebufferHandle;
  14. private int _copyFramebufferHandle;
  15. private int _screenTextureHandle;
  16. private TextureReleaseCallback _release;
  17. private struct PresentationTexture
  18. {
  19. public TextureView Texture { get; }
  20. public ImageCrop Crop { get; }
  21. public object Context { get; }
  22. public PresentationTexture(TextureView texture, ImageCrop crop, object context)
  23. {
  24. Texture = texture;
  25. Crop = crop;
  26. Context = context;
  27. }
  28. }
  29. private Queue<PresentationTexture> _textures;
  30. public Window()
  31. {
  32. _textures = new Queue<PresentationTexture>();
  33. }
  34. public void Present()
  35. {
  36. GL.Disable(EnableCap.FramebufferSrgb);
  37. CopyTextureFromQueue();
  38. int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
  39. int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
  40. GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
  41. GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetCopyFramebufferHandleLazy());
  42. GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
  43. GL.Clear(ClearBufferMask.ColorBufferBit);
  44. GL.BlitFramebuffer(
  45. 0,
  46. 0,
  47. 1280,
  48. 720,
  49. 0,
  50. 0,
  51. 1280,
  52. 720,
  53. ClearBufferMask.ColorBufferBit,
  54. BlitFramebufferFilter.Linear);
  55. GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
  56. GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
  57. GL.Enable(EnableCap.FramebufferSrgb);
  58. }
  59. private void CopyTextureFromQueue()
  60. {
  61. if (!_textures.TryDequeue(out PresentationTexture presentationTexture))
  62. {
  63. return;
  64. }
  65. TextureView texture = presentationTexture.Texture;
  66. ImageCrop crop = presentationTexture.Crop;
  67. object context = presentationTexture.Context;
  68. int oldReadFramebufferHandle = GL.GetInteger(GetPName.ReadFramebufferBinding);
  69. int oldDrawFramebufferHandle = GL.GetInteger(GetPName.DrawFramebufferBinding);
  70. GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, GetCopyFramebufferHandleLazy());
  71. GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, GetBlitFramebufferHandleLazy());
  72. GL.FramebufferTexture(
  73. FramebufferTarget.ReadFramebuffer,
  74. FramebufferAttachment.ColorAttachment0,
  75. texture.Handle,
  76. 0);
  77. GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
  78. GL.Clear(ClearBufferMask.ColorBufferBit);
  79. int srcX0, srcX1, srcY0, srcY1;
  80. if (crop.Left == 0 && crop.Right == 0)
  81. {
  82. srcX0 = 0;
  83. srcX1 = texture.Width;
  84. }
  85. else
  86. {
  87. srcX0 = crop.Left;
  88. srcX1 = crop.Right;
  89. }
  90. if (crop.Top == 0 && crop.Bottom == 0)
  91. {
  92. srcY0 = 0;
  93. srcY1 = texture.Height;
  94. }
  95. else
  96. {
  97. srcY0 = crop.Top;
  98. srcY1 = crop.Bottom;
  99. }
  100. float ratioX = MathF.Min(1f, (_height * (float)NativeWidth) / ((float)NativeHeight * _width));
  101. float ratioY = MathF.Min(1f, (_width * (float)NativeHeight) / ((float)NativeWidth * _height));
  102. int dstWidth = (int)(_width * ratioX);
  103. int dstHeight = (int)(_height * ratioY);
  104. int dstPaddingX = (_width - dstWidth) / 2;
  105. int dstPaddingY = (_height - dstHeight) / 2;
  106. int dstX0 = crop.FlipX ? _width - dstPaddingX : dstPaddingX;
  107. int dstX1 = crop.FlipX ? dstPaddingX : _width - dstPaddingX;
  108. int dstY0 = crop.FlipY ? dstPaddingY : _height - dstPaddingY;
  109. int dstY1 = crop.FlipY ? _height - dstPaddingY : dstPaddingY;
  110. GL.BlitFramebuffer(
  111. srcX0,
  112. srcY0,
  113. srcX1,
  114. srcY1,
  115. dstX0,
  116. dstY0,
  117. dstX1,
  118. dstY1,
  119. ClearBufferMask.ColorBufferBit,
  120. BlitFramebufferFilter.Linear);
  121. GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
  122. GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
  123. texture.Release();
  124. Release(context);
  125. }
  126. public void QueueTexture(ITexture texture, ImageCrop crop, object context)
  127. {
  128. if (texture == null)
  129. {
  130. Release(context);
  131. return;
  132. }
  133. TextureView textureView = (TextureView)texture;
  134. textureView.Acquire();
  135. _textures.Enqueue(new PresentationTexture(textureView, crop, context));
  136. }
  137. public void RegisterTextureReleaseCallback(TextureReleaseCallback callback)
  138. {
  139. _release = callback;
  140. }
  141. private void Release(object context)
  142. {
  143. if (_release != null)
  144. {
  145. _release(context);
  146. }
  147. }
  148. private int GetBlitFramebufferHandleLazy()
  149. {
  150. int handle = _blitFramebufferHandle;
  151. if (handle == 0)
  152. {
  153. handle = GL.GenFramebuffer();
  154. _blitFramebufferHandle = handle;
  155. }
  156. return handle;
  157. }
  158. private int GetCopyFramebufferHandleLazy()
  159. {
  160. int handle = _copyFramebufferHandle;
  161. if (handle == 0)
  162. {
  163. int textureHandle = GL.GenTexture();
  164. GL.BindTexture(TextureTarget.Texture2D, textureHandle);
  165. GL.TexImage2D(
  166. TextureTarget.Texture2D,
  167. 0,
  168. PixelInternalFormat.Rgba8,
  169. 1280,
  170. 720,
  171. 0,
  172. PixelFormat.Rgba,
  173. PixelType.UnsignedByte,
  174. IntPtr.Zero);
  175. handle = GL.GenFramebuffer();
  176. GL.BindFramebuffer(FramebufferTarget.Framebuffer, handle);
  177. GL.FramebufferTexture(
  178. FramebufferTarget.Framebuffer,
  179. FramebufferAttachment.ColorAttachment0,
  180. textureHandle,
  181. 0);
  182. _screenTextureHandle = textureHandle;
  183. _copyFramebufferHandle = handle;
  184. }
  185. return handle;
  186. }
  187. }
  188. }