OGLRasterizer.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. using OpenTK.Graphics.OpenGL;
  2. using System;
  3. namespace Ryujinx.Graphics.Gal.OpenGL
  4. {
  5. class OGLRasterizer : IGalRasterizer
  6. {
  7. public bool DepthWriteEnabled { set; private get; }
  8. private int[] VertexBuffers;
  9. private OGLCachedResource<int> VboCache;
  10. private OGLCachedResource<int> IboCache;
  11. private struct IbInfo
  12. {
  13. public int Count;
  14. public int ElemSizeLog2;
  15. public DrawElementsType Type;
  16. }
  17. private IbInfo IndexBuffer;
  18. public OGLRasterizer()
  19. {
  20. VertexBuffers = new int[32];
  21. VboCache = new OGLCachedResource<int>(GL.DeleteBuffer);
  22. IboCache = new OGLCachedResource<int>(GL.DeleteBuffer);
  23. IndexBuffer = new IbInfo();
  24. DepthWriteEnabled = true;
  25. }
  26. public void LockCaches()
  27. {
  28. VboCache.Lock();
  29. IboCache.Lock();
  30. }
  31. public void UnlockCaches()
  32. {
  33. VboCache.Unlock();
  34. IboCache.Unlock();
  35. }
  36. public void ClearBuffers(
  37. GalClearBufferFlags Flags,
  38. int Attachment,
  39. float Red, float Green, float Blue, float Alpha,
  40. float Depth,
  41. int Stencil)
  42. {
  43. //OpenGL needs glDepthMask to be enabled to clear it
  44. if (!DepthWriteEnabled)
  45. {
  46. GL.DepthMask(true);
  47. }
  48. GL.ColorMask(
  49. Flags.HasFlag(GalClearBufferFlags.ColorRed),
  50. Flags.HasFlag(GalClearBufferFlags.ColorGreen),
  51. Flags.HasFlag(GalClearBufferFlags.ColorBlue),
  52. Flags.HasFlag(GalClearBufferFlags.ColorAlpha));
  53. GL.ClearBuffer(ClearBuffer.Color, Attachment, new float[] { Red, Green, Blue, Alpha });
  54. if (Flags.HasFlag(GalClearBufferFlags.Depth))
  55. {
  56. GL.ClearBuffer(ClearBuffer.Depth, 0, ref Depth);
  57. }
  58. if (Flags.HasFlag(GalClearBufferFlags.Stencil))
  59. {
  60. GL.ClearBuffer(ClearBuffer.Stencil, 0, ref Stencil);
  61. }
  62. GL.ColorMask(true, true, true, true);
  63. if (!DepthWriteEnabled)
  64. {
  65. GL.DepthMask(false);
  66. }
  67. }
  68. public bool IsVboCached(long Key, long DataSize)
  69. {
  70. return VboCache.TryGetSize(Key, out long Size) && Size == DataSize;
  71. }
  72. public bool IsIboCached(long Key, long DataSize)
  73. {
  74. return IboCache.TryGetSize(Key, out long Size) && Size == DataSize;
  75. }
  76. public void CreateVbo(long Key, int DataSize, IntPtr HostAddress)
  77. {
  78. int Handle = GL.GenBuffer();
  79. VboCache.AddOrUpdate(Key, Handle, (uint)DataSize);
  80. IntPtr Length = new IntPtr(DataSize);
  81. GL.BindBuffer(BufferTarget.ArrayBuffer, Handle);
  82. GL.BufferData(BufferTarget.ArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
  83. }
  84. public void CreateIbo(long Key, int DataSize, IntPtr HostAddress)
  85. {
  86. int Handle = GL.GenBuffer();
  87. IboCache.AddOrUpdate(Key, Handle, (uint)DataSize);
  88. IntPtr Length = new IntPtr(DataSize);
  89. GL.BindBuffer(BufferTarget.ElementArrayBuffer, Handle);
  90. GL.BufferData(BufferTarget.ElementArrayBuffer, Length, HostAddress, BufferUsageHint.StreamDraw);
  91. }
  92. public void CreateIbo(long Key, int DataSize, byte[] Buffer)
  93. {
  94. int Handle = GL.GenBuffer();
  95. IboCache.AddOrUpdate(Key, Handle, (uint)DataSize);
  96. IntPtr Length = new IntPtr(Buffer.Length);
  97. GL.BindBuffer(BufferTarget.ElementArrayBuffer, Handle);
  98. GL.BufferData(BufferTarget.ElementArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
  99. }
  100. public void SetIndexArray(int Size, GalIndexFormat Format)
  101. {
  102. IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
  103. IndexBuffer.Count = Size >> (int)Format;
  104. IndexBuffer.ElemSizeLog2 = (int)Format;
  105. }
  106. public void DrawArrays(int First, int Count, GalPrimitiveType PrimType)
  107. {
  108. if (Count == 0)
  109. {
  110. return;
  111. }
  112. if (PrimType == GalPrimitiveType.Quads)
  113. {
  114. for (int Offset = 0; Offset < Count; Offset += 4)
  115. {
  116. GL.DrawArrays(PrimitiveType.TriangleFan, First + Offset, 4);
  117. }
  118. }
  119. else if (PrimType == GalPrimitiveType.QuadStrip)
  120. {
  121. GL.DrawArrays(PrimitiveType.TriangleFan, First, 4);
  122. for (int Offset = 2; Offset < Count; Offset += 2)
  123. {
  124. GL.DrawArrays(PrimitiveType.TriangleFan, First + Offset, 4);
  125. }
  126. }
  127. else
  128. {
  129. GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, Count);
  130. }
  131. }
  132. public void DrawElements(long IboKey, int First, int VertexBase, GalPrimitiveType PrimType)
  133. {
  134. if (!IboCache.TryGetValue(IboKey, out int IboHandle))
  135. {
  136. return;
  137. }
  138. PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
  139. GL.BindBuffer(BufferTarget.ElementArrayBuffer, IboHandle);
  140. First <<= IndexBuffer.ElemSizeLog2;
  141. if (VertexBase != 0)
  142. {
  143. IntPtr Indices = new IntPtr(First);
  144. GL.DrawElementsBaseVertex(Mode, IndexBuffer.Count, IndexBuffer.Type, Indices, VertexBase);
  145. }
  146. else
  147. {
  148. GL.DrawElements(Mode, IndexBuffer.Count, IndexBuffer.Type, First);
  149. }
  150. }
  151. public bool TryGetVbo(long VboKey, out int VboHandle)
  152. {
  153. return VboCache.TryGetValue(VboKey, out VboHandle);
  154. }
  155. }
  156. }