OGLRasterizer.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. using OpenTK.Graphics.OpenGL;
  2. using System;
  3. using System.Collections.Generic;
  4. namespace Ryujinx.Graphics.Gal.OpenGL
  5. {
  6. class OGLRasterizer
  7. {
  8. private static Dictionary<GalVertexAttribSize, int> AttribElements =
  9. new Dictionary<GalVertexAttribSize, int>()
  10. {
  11. { GalVertexAttribSize._32_32_32_32, 4 },
  12. { GalVertexAttribSize._32_32_32, 3 },
  13. { GalVertexAttribSize._16_16_16_16, 4 },
  14. { GalVertexAttribSize._32_32, 2 },
  15. { GalVertexAttribSize._16_16_16, 3 },
  16. { GalVertexAttribSize._8_8_8_8, 4 },
  17. { GalVertexAttribSize._16_16, 2 },
  18. { GalVertexAttribSize._32, 1 },
  19. { GalVertexAttribSize._8_8_8, 3 },
  20. { GalVertexAttribSize._8_8, 2 },
  21. { GalVertexAttribSize._16, 1 },
  22. { GalVertexAttribSize._8, 1 },
  23. { GalVertexAttribSize._10_10_10_2, 4 },
  24. { GalVertexAttribSize._11_11_10, 3 }
  25. };
  26. private static Dictionary<GalVertexAttribSize, VertexAttribPointerType> AttribTypes =
  27. new Dictionary<GalVertexAttribSize, VertexAttribPointerType>()
  28. {
  29. { GalVertexAttribSize._32_32_32_32, VertexAttribPointerType.Int },
  30. { GalVertexAttribSize._32_32_32, VertexAttribPointerType.Int },
  31. { GalVertexAttribSize._16_16_16_16, VertexAttribPointerType.Short },
  32. { GalVertexAttribSize._32_32, VertexAttribPointerType.Int },
  33. { GalVertexAttribSize._16_16_16, VertexAttribPointerType.Short },
  34. { GalVertexAttribSize._8_8_8_8, VertexAttribPointerType.Byte },
  35. { GalVertexAttribSize._16_16, VertexAttribPointerType.Short },
  36. { GalVertexAttribSize._32, VertexAttribPointerType.Int },
  37. { GalVertexAttribSize._8_8_8, VertexAttribPointerType.Byte },
  38. { GalVertexAttribSize._8_8, VertexAttribPointerType.Byte },
  39. { GalVertexAttribSize._16, VertexAttribPointerType.Short },
  40. { GalVertexAttribSize._8, VertexAttribPointerType.Byte },
  41. { GalVertexAttribSize._10_10_10_2, VertexAttribPointerType.Int }, //?
  42. { GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //?
  43. };
  44. private struct VbInfo
  45. {
  46. public int VaoHandle;
  47. public int VboHandle;
  48. }
  49. private struct IbInfo
  50. {
  51. public int IboHandle;
  52. public int Count;
  53. public DrawElementsType Type;
  54. }
  55. private VbInfo[] VertexBuffers;
  56. private IbInfo IndexBuffer;
  57. public OGLRasterizer()
  58. {
  59. VertexBuffers = new VbInfo[32];
  60. IndexBuffer = new IbInfo();
  61. }
  62. public void ClearBuffers(int RtIndex, GalClearBufferFlags Flags)
  63. {
  64. ClearBufferMask Mask = 0;
  65. //OpenGL doesn't support clearing just a single color channel,
  66. //so we can't just clear all channels...
  67. if (Flags.HasFlag(GalClearBufferFlags.ColorRed) &&
  68. Flags.HasFlag(GalClearBufferFlags.ColorGreen) &&
  69. Flags.HasFlag(GalClearBufferFlags.ColorBlue) &&
  70. Flags.HasFlag(GalClearBufferFlags.ColorAlpha))
  71. {
  72. Mask = ClearBufferMask.ColorBufferBit;
  73. }
  74. if (Flags.HasFlag(GalClearBufferFlags.Depth))
  75. {
  76. Mask |= ClearBufferMask.DepthBufferBit;
  77. }
  78. if (Flags.HasFlag(GalClearBufferFlags.Stencil))
  79. {
  80. Mask |= ClearBufferMask.StencilBufferBit;
  81. }
  82. GL.Clear(Mask);
  83. }
  84. public void SetVertexArray(int VbIndex, int Stride, byte[] Buffer, GalVertexAttrib[] Attribs)
  85. {
  86. EnsureVbInitialized(VbIndex);
  87. VbInfo Vb = VertexBuffers[VbIndex];
  88. IntPtr Length = new IntPtr(Buffer.Length);
  89. GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle);
  90. GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
  91. GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
  92. GL.BindVertexArray(Vb.VaoHandle);
  93. for (int Attr = 0; Attr < 16; Attr++)
  94. {
  95. GL.DisableVertexAttribArray(Attr);
  96. }
  97. for (int Index = 0; Index < Attribs.Length; Index++)
  98. {
  99. GalVertexAttrib Attrib = Attribs[Index];
  100. GL.EnableVertexAttribArray(Index);
  101. GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle);
  102. bool Unsigned =
  103. Attrib.Type == GalVertexAttribType.Unorm ||
  104. Attrib.Type == GalVertexAttribType.Uint ||
  105. Attrib.Type == GalVertexAttribType.Uscaled;
  106. bool Normalize =
  107. Attrib.Type == GalVertexAttribType.Snorm ||
  108. Attrib.Type == GalVertexAttribType.Unorm;
  109. VertexAttribPointerType Type = 0;
  110. if (Attrib.Type == GalVertexAttribType.Float)
  111. {
  112. Type = VertexAttribPointerType.Float;
  113. }
  114. else
  115. {
  116. Type = AttribTypes[Attrib.Size] + (Unsigned ? 1 : 0);
  117. }
  118. int Size = AttribElements[Attrib.Size];
  119. int Offset = Attrib.Offset;
  120. GL.VertexAttribPointer(Index, Size, Type, Normalize, Stride, Offset);
  121. }
  122. GL.BindVertexArray(0);
  123. }
  124. public void SetIndexArray(byte[] Buffer, GalIndexFormat Format)
  125. {
  126. EnsureIbInitialized();
  127. IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
  128. IndexBuffer.Count = Buffer.Length >> (int)Format;
  129. IntPtr Length = new IntPtr(Buffer.Length);
  130. GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndexBuffer.IboHandle);
  131. GL.BufferData(BufferTarget.ElementArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
  132. GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
  133. }
  134. public void DrawArrays(int VbIndex, int First, int PrimCount, GalPrimitiveType PrimType)
  135. {
  136. if (PrimCount == 0)
  137. {
  138. return;
  139. }
  140. VbInfo Vb = VertexBuffers[VbIndex];
  141. GL.BindVertexArray(Vb.VaoHandle);
  142. GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount);
  143. }
  144. public void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType)
  145. {
  146. VbInfo Vb = VertexBuffers[VbIndex];
  147. PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
  148. GL.BindVertexArray(Vb.VaoHandle);
  149. GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndexBuffer.IboHandle);
  150. GL.DrawElements(Mode, IndexBuffer.Count, IndexBuffer.Type, First);
  151. }
  152. private void EnsureVbInitialized(int VbIndex)
  153. {
  154. VbInfo Vb = VertexBuffers[VbIndex];
  155. if (Vb.VaoHandle == 0)
  156. {
  157. Vb.VaoHandle = GL.GenVertexArray();
  158. }
  159. if (Vb.VboHandle == 0)
  160. {
  161. Vb.VboHandle = GL.GenBuffer();
  162. }
  163. VertexBuffers[VbIndex] = Vb;
  164. }
  165. private void EnsureIbInitialized()
  166. {
  167. if (IndexBuffer.IboHandle == 0)
  168. {
  169. IndexBuffer.IboHandle = GL.GenBuffer();
  170. }
  171. }
  172. }
  173. }