DrawTextureEmulation.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Graphics.OpenGL.Image;
  3. using System;
  4. namespace Ryujinx.Graphics.OpenGL
  5. {
  6. class DrawTextureEmulation
  7. {
  8. private const string VertexShader = @"#version 430 core
  9. uniform float srcX0;
  10. uniform float srcY0;
  11. uniform float srcX1;
  12. uniform float srcY1;
  13. layout (location = 0) out vec2 texcoord;
  14. void main()
  15. {
  16. bool x1 = (gl_VertexID & 1) != 0;
  17. bool y1 = (gl_VertexID & 2) != 0;
  18. gl_Position = vec4(x1 ? 1 : -1, y1 ? -1 : 1, 0, 1);
  19. texcoord = vec2(x1 ? srcX1 : srcX0, y1 ? srcY1 : srcY0);
  20. }";
  21. private const string FragmentShader = @"#version 430 core
  22. layout (location = 0) uniform sampler2D tex;
  23. layout (location = 0) in vec2 texcoord;
  24. layout (location = 0) out vec4 colour;
  25. void main()
  26. {
  27. colour = texture(tex, texcoord);
  28. }";
  29. private int _vsHandle;
  30. private int _fsHandle;
  31. private int _programHandle;
  32. private int _uniformSrcX0Location;
  33. private int _uniformSrcY0Location;
  34. private int _uniformSrcX1Location;
  35. private int _uniformSrcY1Location;
  36. private bool _initialized;
  37. public void Draw(
  38. TextureView texture,
  39. Sampler sampler,
  40. float x0,
  41. float y0,
  42. float x1,
  43. float y1,
  44. float s0,
  45. float t0,
  46. float s1,
  47. float t1)
  48. {
  49. EnsureInitialized();
  50. GL.UseProgram(_programHandle);
  51. texture.Bind(0);
  52. sampler.Bind(0);
  53. if (x0 > x1)
  54. {
  55. float temp = s0;
  56. s0 = s1;
  57. s1 = temp;
  58. }
  59. if (y0 > y1)
  60. {
  61. float temp = t0;
  62. t0 = t1;
  63. t1 = temp;
  64. }
  65. GL.Uniform1(_uniformSrcX0Location, s0);
  66. GL.Uniform1(_uniformSrcY0Location, t0);
  67. GL.Uniform1(_uniformSrcX1Location, s1);
  68. GL.Uniform1(_uniformSrcY1Location, t1);
  69. GL.ViewportIndexed(0, MathF.Min(x0, x1), MathF.Min(y0, y1), MathF.Abs(x1 - x0), MathF.Abs(y1 - y0));
  70. GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
  71. }
  72. private void EnsureInitialized()
  73. {
  74. if (_initialized)
  75. {
  76. return;
  77. }
  78. _initialized = true;
  79. _vsHandle = GL.CreateShader(ShaderType.VertexShader);
  80. _fsHandle = GL.CreateShader(ShaderType.FragmentShader);
  81. GL.ShaderSource(_vsHandle, VertexShader);
  82. GL.ShaderSource(_fsHandle, FragmentShader);
  83. GL.CompileShader(_vsHandle);
  84. GL.CompileShader(_fsHandle);
  85. _programHandle = GL.CreateProgram();
  86. GL.AttachShader(_programHandle, _vsHandle);
  87. GL.AttachShader(_programHandle, _fsHandle);
  88. GL.LinkProgram(_programHandle);
  89. GL.DetachShader(_programHandle, _vsHandle);
  90. GL.DetachShader(_programHandle, _fsHandle);
  91. _uniformSrcX0Location = GL.GetUniformLocation(_programHandle, "srcX0");
  92. _uniformSrcY0Location = GL.GetUniformLocation(_programHandle, "srcY0");
  93. _uniformSrcX1Location = GL.GetUniformLocation(_programHandle, "srcX1");
  94. _uniformSrcY1Location = GL.GetUniformLocation(_programHandle, "srcY1");
  95. }
  96. public void Dispose()
  97. {
  98. if (!_initialized)
  99. {
  100. return;
  101. }
  102. GL.DeleteShader(_vsHandle);
  103. GL.DeleteShader(_fsHandle);
  104. GL.DeleteProgram(_programHandle);
  105. _initialized = false;
  106. }
  107. }
  108. }