OpenGLRenderer.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. using OpenTK.Graphics.OpenGL;
  2. using System;
  3. using System.Collections.Generic;
  4. namespace Ryujinx.Graphics.Gal.OpenGL
  5. {
  6. public class OpenGLRenderer : IGalRenderer
  7. {
  8. private struct VertexBuffer
  9. {
  10. public int VaoHandle;
  11. public int VboHandle;
  12. public int PrimCount;
  13. }
  14. private struct Texture
  15. {
  16. public int Handle;
  17. }
  18. private List<VertexBuffer> VertexBuffers;
  19. private Texture[] Textures;
  20. private Queue<Action> ActionsQueue;
  21. public long FrameBufferPtr { get; set; }
  22. public OpenGLRenderer()
  23. {
  24. VertexBuffers = new List<VertexBuffer>();
  25. Textures = new Texture[8];
  26. ActionsQueue = new Queue<Action>();
  27. }
  28. public void QueueAction(Action ActionMthd)
  29. {
  30. ActionsQueue.Enqueue(ActionMthd);
  31. }
  32. public void RunActions()
  33. {
  34. while (ActionsQueue.Count > 0)
  35. {
  36. ActionsQueue.Dequeue()();
  37. }
  38. }
  39. public void Render()
  40. {
  41. for (int Index = 0; Index < VertexBuffers.Count; Index++)
  42. {
  43. VertexBuffer Vb = VertexBuffers[Index];
  44. if (Vb.VaoHandle != 0 &&
  45. Vb.PrimCount != 0)
  46. {
  47. GL.BindVertexArray(Vb.VaoHandle);
  48. GL.DrawArrays(PrimitiveType.TriangleStrip, 0, Vb.PrimCount);
  49. }
  50. }
  51. }
  52. public void SendVertexBuffer(int Index, byte[] Buffer, int Stride, GalVertexAttrib[] Attribs)
  53. {
  54. if (Index < 0)
  55. {
  56. throw new ArgumentOutOfRangeException(nameof(Index));
  57. }
  58. if (Buffer.Length == 0 || Stride == 0)
  59. {
  60. return;
  61. }
  62. EnsureVbInitialized(Index);
  63. VertexBuffer Vb = VertexBuffers[Index];
  64. Vb.PrimCount = Buffer.Length / Stride;
  65. VertexBuffers[Index] = Vb;
  66. IntPtr Length = new IntPtr(Buffer.Length);
  67. GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle);
  68. GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
  69. GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
  70. GL.BindVertexArray(Vb.VaoHandle);
  71. for (int Attr = 0; Attr < 16; Attr++)
  72. {
  73. GL.DisableVertexAttribArray(Attr);
  74. }
  75. foreach (GalVertexAttrib Attrib in Attribs)
  76. {
  77. if (Attrib.Index >= 3) break;
  78. GL.EnableVertexAttribArray(Attrib.Index);
  79. GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle);
  80. int Size = 0;
  81. switch (Attrib.Size)
  82. {
  83. case GalVertexAttribSize._8:
  84. case GalVertexAttribSize._16:
  85. case GalVertexAttribSize._32:
  86. Size = 1;
  87. break;
  88. case GalVertexAttribSize._8_8:
  89. case GalVertexAttribSize._16_16:
  90. case GalVertexAttribSize._32_32:
  91. Size = 2;
  92. break;
  93. case GalVertexAttribSize._8_8_8:
  94. case GalVertexAttribSize._11_11_10:
  95. case GalVertexAttribSize._16_16_16:
  96. case GalVertexAttribSize._32_32_32:
  97. Size = 3;
  98. break;
  99. case GalVertexAttribSize._8_8_8_8:
  100. case GalVertexAttribSize._10_10_10_2:
  101. case GalVertexAttribSize._16_16_16_16:
  102. case GalVertexAttribSize._32_32_32_32:
  103. Size = 4;
  104. break;
  105. }
  106. bool Signed =
  107. Attrib.Type == GalVertexAttribType.Snorm ||
  108. Attrib.Type == GalVertexAttribType.Sint ||
  109. Attrib.Type == GalVertexAttribType.Sscaled;
  110. bool Normalize =
  111. Attrib.Type == GalVertexAttribType.Snorm ||
  112. Attrib.Type == GalVertexAttribType.Unorm;
  113. VertexAttribPointerType Type = 0;
  114. switch (Attrib.Type)
  115. {
  116. case GalVertexAttribType.Snorm:
  117. case GalVertexAttribType.Unorm:
  118. case GalVertexAttribType.Sint:
  119. case GalVertexAttribType.Uint:
  120. case GalVertexAttribType.Uscaled:
  121. case GalVertexAttribType.Sscaled:
  122. {
  123. switch (Attrib.Size)
  124. {
  125. case GalVertexAttribSize._8:
  126. case GalVertexAttribSize._8_8:
  127. case GalVertexAttribSize._8_8_8:
  128. case GalVertexAttribSize._8_8_8_8:
  129. {
  130. Type = Signed
  131. ? VertexAttribPointerType.Byte
  132. : VertexAttribPointerType.UnsignedByte;
  133. break;
  134. }
  135. case GalVertexAttribSize._16:
  136. case GalVertexAttribSize._16_16:
  137. case GalVertexAttribSize._16_16_16:
  138. case GalVertexAttribSize._16_16_16_16:
  139. {
  140. Type = Signed
  141. ? VertexAttribPointerType.Short
  142. : VertexAttribPointerType.UnsignedShort;
  143. break;
  144. }
  145. case GalVertexAttribSize._10_10_10_2:
  146. case GalVertexAttribSize._11_11_10:
  147. case GalVertexAttribSize._32:
  148. case GalVertexAttribSize._32_32:
  149. case GalVertexAttribSize._32_32_32:
  150. case GalVertexAttribSize._32_32_32_32:
  151. {
  152. Type = Signed
  153. ? VertexAttribPointerType.Int
  154. : VertexAttribPointerType.UnsignedInt;
  155. break;
  156. }
  157. }
  158. break;
  159. }
  160. case GalVertexAttribType.Float:
  161. {
  162. Type = VertexAttribPointerType.Float;
  163. break;
  164. }
  165. }
  166. GL.VertexAttribPointer(
  167. Attrib.Index,
  168. Size,
  169. Type,
  170. Normalize,
  171. Stride,
  172. Attrib.Offset);
  173. }
  174. GL.BindVertexArray(0);
  175. }
  176. public void SendR8G8B8A8Texture(int Index, byte[] Buffer, int Width, int Height)
  177. {
  178. EnsureTexInitialized(Index);
  179. GL.BindTexture(TextureTarget.Texture2D, Textures[Index].Handle);
  180. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
  181. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
  182. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
  183. GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
  184. GL.TexImage2D(TextureTarget.Texture2D,
  185. 0,
  186. PixelInternalFormat.Rgba,
  187. Width,
  188. Height,
  189. 0,
  190. PixelFormat.Rgba,
  191. PixelType.UnsignedByte,
  192. Buffer);
  193. }
  194. public void BindTexture(int Index)
  195. {
  196. GL.ActiveTexture(TextureUnit.Texture0 + Index);
  197. GL.BindTexture(TextureTarget.Texture2D, Textures[Index].Handle);
  198. }
  199. private void EnsureVbInitialized(int VbIndex)
  200. {
  201. while (VbIndex >= VertexBuffers.Count)
  202. {
  203. VertexBuffers.Add(new VertexBuffer());
  204. }
  205. VertexBuffer Vb = VertexBuffers[VbIndex];
  206. if (Vb.VaoHandle == 0)
  207. {
  208. Vb.VaoHandle = GL.GenVertexArray();
  209. }
  210. if (Vb.VboHandle == 0)
  211. {
  212. Vb.VboHandle = GL.GenBuffer();
  213. }
  214. VertexBuffers[VbIndex] = Vb;
  215. }
  216. private void EnsureTexInitialized(int TexIndex)
  217. {
  218. Texture Tex = Textures[TexIndex];
  219. if (Tex.Handle == 0)
  220. {
  221. Tex.Handle = GL.GenTexture();
  222. }
  223. Textures[TexIndex] = Tex;
  224. }
  225. }
  226. }