OGLRasterizer.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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 SetIndexArray(int Size, GalIndexFormat Format)
  93. {
  94. IndexBuffer.Type = OGLEnumConverter.GetDrawElementsType(Format);
  95. IndexBuffer.Count = Size >> (int)Format;
  96. IndexBuffer.ElemSizeLog2 = (int)Format;
  97. }
  98. public void DrawArrays(int First, int Count, GalPrimitiveType PrimType)
  99. {
  100. if (Count == 0)
  101. {
  102. return;
  103. }
  104. GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, Count);
  105. }
  106. public void DrawElements(long IboKey, int First, int VertexBase, GalPrimitiveType PrimType)
  107. {
  108. if (!IboCache.TryGetValue(IboKey, out int IboHandle))
  109. {
  110. return;
  111. }
  112. PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
  113. GL.BindBuffer(BufferTarget.ElementArrayBuffer, IboHandle);
  114. First <<= IndexBuffer.ElemSizeLog2;
  115. if (VertexBase != 0)
  116. {
  117. IntPtr Indices = new IntPtr(First);
  118. GL.DrawElementsBaseVertex(Mode, IndexBuffer.Count, IndexBuffer.Type, Indices, VertexBase);
  119. }
  120. else
  121. {
  122. GL.DrawElements(Mode, IndexBuffer.Count, IndexBuffer.Type, First);
  123. }
  124. }
  125. public bool TryGetVbo(long VboKey, out int VboHandle)
  126. {
  127. return VboCache.TryGetValue(VboKey, out VboHandle);
  128. }
  129. }
  130. }