MonoGameGraphicsDeviceService.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. using System;
  2. using System.Windows;
  3. using System.Windows.Interop;
  4. using Microsoft.Xna.Framework.Graphics;
  5. using SharpDX.Direct3D9;
  6. namespace MonoGame.WpfCore.MonoGameControls
  7. {
  8. public class MonoGameGraphicsDeviceService : IGraphicsDeviceService, IDisposable
  9. {
  10. public MonoGameGraphicsDeviceService()
  11. {
  12. }
  13. public void Dispose()
  14. {
  15. DeviceDisposing?.Invoke(this, EventArgs.Empty);
  16. GraphicsDevice.Dispose();
  17. Direct3DDevice?.Dispose();
  18. Direct3DContext?.Dispose();
  19. }
  20. public Direct3DEx Direct3DContext { get; private set; }
  21. public DeviceEx Direct3DDevice { get; private set; }
  22. public event EventHandler<EventArgs> DeviceCreated;
  23. public event EventHandler<EventArgs> DeviceDisposing;
  24. public event EventHandler<EventArgs> DeviceReset;
  25. public event EventHandler<EventArgs> DeviceResetting;
  26. public void StartDirect3D(Window window)
  27. {
  28. Direct3DContext = new Direct3DEx();
  29. var presentParameters = new PresentParameters
  30. {
  31. Windowed = true,
  32. SwapEffect = SwapEffect.Discard,
  33. DeviceWindowHandle = new WindowInteropHelper(window).Handle,
  34. PresentationInterval = SharpDX.Direct3D9.PresentInterval.Default
  35. };
  36. Direct3DDevice = new DeviceEx(Direct3DContext, 0, DeviceType.Hardware, IntPtr.Zero,
  37. CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve,
  38. presentParameters);
  39. // Create the device using the main window handle, and a placeholder size (1,1).
  40. // The actual size doesn't matter because whenever we render using this GraphicsDevice,
  41. // we will make sure the back buffer is large enough for the window we're rendering into.
  42. // Also, the handle doesn't matter because we call GraphicsDevice.Present(...) with the
  43. // actual window handle to render into.
  44. GraphicsDevice = CreateGraphicsDevice(new WindowInteropHelper(window).Handle, 1, 1, 8);
  45. DeviceCreated?.Invoke(this, EventArgs.Empty);
  46. }
  47. // Store the current device settings.
  48. private PresentationParameters _parameters;
  49. public GraphicsDevice GraphicsDevice { get; private set; }
  50. public GraphicsDevice CreateGraphicsDevice(IntPtr windowHandle, int width, int height, int multisampling = 1)
  51. {
  52. _parameters = new PresentationParameters
  53. {
  54. BackBufferWidth = Math.Max(width, 1),
  55. BackBufferHeight = Math.Max(height, 1),
  56. BackBufferFormat = SurfaceFormat.Color,
  57. DepthStencilFormat = DepthFormat.Depth24,
  58. DeviceWindowHandle = windowHandle,
  59. MultiSampleCount = multisampling,
  60. PresentationInterval = Microsoft.Xna.Framework.Graphics.PresentInterval.Immediate,
  61. IsFullScreen = false
  62. };
  63. return new GraphicsDevice(GraphicsAdapter.DefaultAdapter, GraphicsProfile.HiDef, _parameters);
  64. }
  65. /// <summary>
  66. /// Resets the graphics device to whichever is bigger out of the specified
  67. /// resolution or its current size. This behavior means the device will
  68. /// demand-grow to the largest of all its GraphicsDeviceControl clients.
  69. /// </summary>
  70. public void ResetDevice(int width, int height)
  71. {
  72. var newWidth = Math.Max(_parameters.BackBufferWidth, width);
  73. var newHeight = Math.Max(_parameters.BackBufferHeight, height);
  74. if (newWidth != _parameters.BackBufferWidth || newHeight != _parameters.BackBufferHeight)
  75. {
  76. DeviceResetting?.Invoke(this, EventArgs.Empty);
  77. _parameters.BackBufferWidth = newWidth;
  78. _parameters.BackBufferHeight = newHeight;
  79. GraphicsDevice.Reset(_parameters);
  80. DeviceReset?.Invoke(this, EventArgs.Empty);
  81. }
  82. }
  83. }
  84. }