Window.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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 Window : IWindow, IDisposable
  8. {
  9. private readonly Renderer _renderer;
  10. private int _width;
  11. private int _height;
  12. private int _copyFramebufferHandle;
  13. internal BackgroundContextWorker BackgroundContext { get; private set; }
  14. internal bool ScreenCaptureRequested { get; set; }
  15. public Window(Renderer renderer)
  16. {
  17. _renderer = renderer;
  18. }
  19. public void Present(ITexture texture, ImageCrop crop)
  20. {
  21. GL.Disable(EnableCap.FramebufferSrgb);
  22. CopyTextureToFrameBufferRGB(0, GetCopyFramebufferHandleLazy(), (TextureView)texture, crop);
  23. GL.Enable(EnableCap.FramebufferSrgb);
  24. }
  25. public void SetSize(int width, int height)
  26. {
  27. _width = width;
  28. _height = height;
  29. }
  30. private void CopyTextureToFrameBufferRGB(int drawFramebuffer, int readFramebuffer, TextureView view, ImageCrop crop)
  31. {
  32. (int oldDrawFramebufferHandle, int oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers();
  33. GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
  34. GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
  35. TextureView viewConverted = view.Format.IsBgr() ? _renderer.TextureCopy.BgraSwap(view) : view;
  36. GL.FramebufferTexture(
  37. FramebufferTarget.ReadFramebuffer,
  38. FramebufferAttachment.ColorAttachment0,
  39. viewConverted.Handle,
  40. 0);
  41. GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
  42. GL.Disable(EnableCap.RasterizerDiscard);
  43. GL.Disable(IndexedEnableCap.ScissorTest, 0);
  44. GL.Clear(ClearBufferMask.ColorBufferBit);
  45. int srcX0, srcX1, srcY0, srcY1;
  46. float scale = view.ScaleFactor;
  47. if (crop.Left == 0 && crop.Right == 0)
  48. {
  49. srcX0 = 0;
  50. srcX1 = (int)(view.Width / scale);
  51. }
  52. else
  53. {
  54. srcX0 = crop.Left;
  55. srcX1 = crop.Right;
  56. }
  57. if (crop.Top == 0 && crop.Bottom == 0)
  58. {
  59. srcY0 = 0;
  60. srcY1 = (int)(view.Height / scale);
  61. }
  62. else
  63. {
  64. srcY0 = crop.Top;
  65. srcY1 = crop.Bottom;
  66. }
  67. if (scale != 1f)
  68. {
  69. srcX0 = (int)(srcX0 * scale);
  70. srcY0 = (int)(srcY0 * scale);
  71. srcX1 = (int)Math.Ceiling(srcX1 * scale);
  72. srcY1 = (int)Math.Ceiling(srcY1 * scale);
  73. }
  74. float ratioX = crop.IsStretched ? 1.0f : MathF.Min(1.0f, _height * crop.AspectRatioX / (_width * crop.AspectRatioY));
  75. float ratioY = crop.IsStretched ? 1.0f : MathF.Min(1.0f, _width * crop.AspectRatioY / (_height * crop.AspectRatioX));
  76. int dstWidth = (int)(_width * ratioX);
  77. int dstHeight = (int)(_height * ratioY);
  78. int dstPaddingX = (_width - dstWidth) / 2;
  79. int dstPaddingY = (_height - dstHeight) / 2;
  80. int dstX0 = crop.FlipX ? _width - dstPaddingX : dstPaddingX;
  81. int dstX1 = crop.FlipX ? dstPaddingX : _width - dstPaddingX;
  82. int dstY0 = crop.FlipY ? dstPaddingY : _height - dstPaddingY;
  83. int dstY1 = crop.FlipY ? _height - dstPaddingY : dstPaddingY;
  84. if (ScreenCaptureRequested)
  85. {
  86. CaptureFrame(srcX0, srcY0, srcX1, srcY1, view.Format.IsBgr(), crop.FlipX, crop.FlipY);
  87. ScreenCaptureRequested = false;
  88. }
  89. GL.BlitFramebuffer(
  90. srcX0,
  91. srcY0,
  92. srcX1,
  93. srcY1,
  94. dstX0,
  95. dstY0,
  96. dstX1,
  97. dstY1,
  98. ClearBufferMask.ColorBufferBit,
  99. BlitFramebufferFilter.Linear);
  100. // Remove Alpha channel
  101. GL.ColorMask(false, false, false, true);
  102. GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  103. GL.Clear(ClearBufferMask.ColorBufferBit);
  104. for (int i = 0; i < Constants.MaxRenderTargets; i++)
  105. {
  106. ((Pipeline)_renderer.Pipeline).RestoreComponentMask(i);
  107. }
  108. GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle);
  109. GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle);
  110. ((Pipeline)_renderer.Pipeline).RestoreScissor0Enable();
  111. ((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard();
  112. if (viewConverted != view)
  113. {
  114. viewConverted.Dispose();
  115. }
  116. }
  117. private int GetCopyFramebufferHandleLazy()
  118. {
  119. int handle = _copyFramebufferHandle;
  120. if (handle == 0)
  121. {
  122. handle = GL.GenFramebuffer();
  123. _copyFramebufferHandle = handle;
  124. }
  125. return handle;
  126. }
  127. public void InitializeBackgroundContext(IOpenGLContext baseContext)
  128. {
  129. BackgroundContext = new BackgroundContextWorker(baseContext);
  130. }
  131. public void CaptureFrame(int x, int y, int width, int height, bool isBgra, bool flipX, bool flipY)
  132. {
  133. long size = Math.Abs(4 * width * height);
  134. byte[] bitmap = new byte[size];
  135. GL.ReadPixels(x, y, width, height, isBgra ? PixelFormat.Bgra : PixelFormat.Rgba, PixelType.UnsignedByte, bitmap);
  136. _renderer.OnScreenCaptured(new ScreenCaptureImageInfo(width, height, isBgra, bitmap, flipX, flipY));
  137. }
  138. public void Dispose()
  139. {
  140. BackgroundContext.Dispose();
  141. if (_copyFramebufferHandle != 0)
  142. {
  143. GL.DeleteFramebuffer(_copyFramebufferHandle);
  144. _copyFramebufferHandle = 0;
  145. }
  146. }
  147. }
  148. }