GLWidget.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. using Gtk;
  2. using SPB.Graphics;
  3. using SPB.Graphics.OpenGL;
  4. using SPB.Platform;
  5. using SPB.Platform.GLX;
  6. using SPB.Platform.WGL;
  7. using SPB.Windowing;
  8. using System;
  9. using System.ComponentModel;
  10. using System.Runtime.InteropServices;
  11. namespace Ryujinx.Ui
  12. {
  13. [ToolboxItem(true)]
  14. public class GLWidget : DrawingArea
  15. {
  16. private bool _initialized;
  17. public event EventHandler Initialized;
  18. public event EventHandler ShuttingDown;
  19. public OpenGLContextBase OpenGLContext { get; private set; }
  20. public NativeWindowBase NativeWindow { get; private set; }
  21. public FramebufferFormat FramebufferFormat { get; }
  22. public int GLVersionMajor { get; }
  23. public int GLVersionMinor { get; }
  24. public OpenGLContextFlags ContextFlags { get; }
  25. public bool DirectRendering { get; }
  26. public OpenGLContextBase SharedContext { get; }
  27. public GLWidget(FramebufferFormat framebufferFormat, int major, int minor, OpenGLContextFlags flags = OpenGLContextFlags.Default, bool directRendering = true, OpenGLContextBase sharedContext = null)
  28. {
  29. FramebufferFormat = framebufferFormat;
  30. GLVersionMajor = major;
  31. GLVersionMinor = minor;
  32. ContextFlags = flags;
  33. DirectRendering = directRendering;
  34. SharedContext = sharedContext;
  35. }
  36. protected override bool OnDrawn(Cairo.Context cr)
  37. {
  38. if (!_initialized)
  39. {
  40. Intialize();
  41. }
  42. return true;
  43. }
  44. private NativeWindowBase RetrieveNativeWindow()
  45. {
  46. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
  47. {
  48. IntPtr windowHandle = gdk_win32_window_get_handle(Window.Handle);
  49. return new WGLWindow(new NativeHandle(windowHandle));
  50. }
  51. else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
  52. {
  53. IntPtr displayHandle = gdk_x11_display_get_xdisplay(Display.Handle);
  54. IntPtr windowHandle = gdk_x11_window_get_xid(Window.Handle);
  55. return new GLXWindow(new NativeHandle(displayHandle), new NativeHandle(windowHandle));
  56. }
  57. throw new NotImplementedException();
  58. }
  59. [DllImport("libgdk-3-0.dll")]
  60. private static extern IntPtr gdk_win32_window_get_handle(IntPtr d);
  61. [DllImport("libgdk-3.so.0")]
  62. private static extern IntPtr gdk_x11_display_get_xdisplay(IntPtr gdkDisplay);
  63. [DllImport("libgdk-3.so.0")]
  64. private static extern IntPtr gdk_x11_window_get_xid(IntPtr gdkWindow);
  65. private void Intialize()
  66. {
  67. NativeWindow = RetrieveNativeWindow();
  68. Window.EnsureNative();
  69. OpenGLContext = PlatformHelper.CreateOpenGLContext(FramebufferFormat, GLVersionMajor, GLVersionMinor, ContextFlags, DirectRendering, SharedContext);
  70. OpenGLContext.Initialize(NativeWindow);
  71. OpenGLContext.MakeCurrent(NativeWindow);
  72. _initialized = true;
  73. Initialized?.Invoke(this, EventArgs.Empty);
  74. }
  75. protected override void Dispose(bool disposing)
  76. {
  77. // Try to bind the OpenGL context before calling the shutdown event
  78. try
  79. {
  80. OpenGLContext?.MakeCurrent(NativeWindow);
  81. }
  82. catch (Exception) { }
  83. ShuttingDown?.Invoke(this, EventArgs.Empty);
  84. // Unbind context and destroy everything
  85. try
  86. {
  87. OpenGLContext?.MakeCurrent(null);
  88. }
  89. catch (Exception) { }
  90. OpenGLContext.Dispose();
  91. }
  92. }
  93. }