D3D9.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using Microsoft.Xna.Framework.Graphics;
  4. using SharpDX.Direct3D9;
  5. using DeviceType = SharpDX.Direct3D9.DeviceType;
  6. using PresentInterval = SharpDX.Direct3D9.PresentInterval;
  7. using Texture = SharpDX.Direct3D9.Texture;
  8. namespace WpfInteropSample
  9. {
  10. /// <summary>
  11. /// Represents a Direct3D 9 device required for Direct3D 11 interoperability.
  12. /// </summary>
  13. /// <remarks>
  14. /// It is not possible to set a Direct3D 11 resource (e.g. a texture or render target) in WPF
  15. /// directly because WPF requires Direct3D 9. The <see cref="D3D9"/> class creates a new
  16. /// Direct3D 9 device which can be used for sharing resources between Direct3D 11 and Direct3D
  17. /// 9. Call <see cref="GetSharedTexture"/> to convert a texture from Direct3D 11 to Direct3D 9.
  18. /// </remarks>
  19. internal class D3D9 : IDisposable
  20. {
  21. // The code requires Windows Vista and up using the Windows Display Driver Model (WDDM).
  22. // It does not work with the Windows 2000 Display Driver Model (XDDM).
  23. private bool _disposed;
  24. private Direct3DEx _direct3D;
  25. private DeviceEx _device;
  26. /// <summary>
  27. /// Initializes a new instance of the <see cref="D3D9"/> class.
  28. /// </summary>
  29. public D3D9()
  30. {
  31. // Create Direct3DEx device on Windows Vista/7/8 with a display configured to use
  32. // the Windows Display Driver Model (WDDM). Use Direct3D on any other platform.
  33. _direct3D = new Direct3DEx();
  34. PresentParameters presentparams = new PresentParameters
  35. {
  36. Windowed = true,
  37. SwapEffect = SwapEffect.Discard,
  38. PresentationInterval = PresentInterval.Default,
  39. // The device back buffer is not used.
  40. BackBufferFormat = Format.Unknown,
  41. BackBufferWidth = 1,
  42. BackBufferHeight = 1,
  43. // Use dummy window handle.
  44. DeviceWindowHandle = GetDesktopWindow()
  45. };
  46. _device = new DeviceEx(_direct3D, 0, DeviceType.Hardware, IntPtr.Zero,
  47. CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve,
  48. presentparams);
  49. }
  50. /// <summary>
  51. /// Releases unmanaged resources before an instance of the <see cref="D3D9"/> class is
  52. /// reclaimed by garbage collection.
  53. /// </summary>
  54. /// <remarks>
  55. /// This method releases unmanaged resources by calling the virtual <see cref="Dispose(bool)"/>
  56. /// method, passing in <see langword="false"/>.
  57. /// </remarks>
  58. ~D3D9()
  59. {
  60. Dispose(false);
  61. }
  62. /// <summary>
  63. /// Releases all resources used by an instance of the <see cref="D3D9"/> class.
  64. /// </summary>
  65. /// <remarks>
  66. /// This method calls the virtual <see cref="Dispose(bool)"/> method, passing in
  67. /// <see langword="true"/>, and then suppresses finalization of the instance.
  68. /// </remarks>
  69. public void Dispose()
  70. {
  71. Dispose(true);
  72. GC.SuppressFinalize(this);
  73. }
  74. /// <summary>
  75. /// Releases the unmanaged resources used by an instance of the <see cref="D3D9"/> class
  76. /// and optionally releases the managed resources.
  77. /// </summary>
  78. /// <param name="disposing">
  79. /// <see langword="true"/> to release both managed and unmanaged resources;
  80. /// <see langword="false"/> to release only unmanaged resources.
  81. /// </param>
  82. protected virtual void Dispose(bool disposing)
  83. {
  84. if (!_disposed)
  85. {
  86. if (disposing)
  87. {
  88. // Dispose managed resources.
  89. if (_device != null)
  90. {
  91. _device.Dispose();
  92. _device = null;
  93. }
  94. if (_direct3D != null)
  95. {
  96. _direct3D.Dispose();
  97. _direct3D = null;
  98. }
  99. }
  100. // Release unmanaged resources.
  101. _disposed = true;
  102. }
  103. }
  104. [DllImport("user32.dll", SetLastError = false)]
  105. private static extern IntPtr GetDesktopWindow();
  106. private void ThrowIfDisposed()
  107. {
  108. if (_disposed)
  109. throw new ObjectDisposedException(GetType().FullName);
  110. }
  111. /// <summary>
  112. /// Creates Direct3D 9 texture from the specified Direct3D 11 texture.
  113. /// (The content is shared between the devices.)
  114. /// </summary>
  115. /// <param name="renderTarget">The Direct3D 11 texture.</param>
  116. /// <returns>The Direct3D 9 texture.</returns>
  117. /// <exception cref="ArgumentException">
  118. /// The Direct3D 11 texture is not a shared resource, or the texture format is not
  119. /// supported.
  120. /// </exception>
  121. public Texture GetSharedTexture(Texture2D renderTarget)
  122. {
  123. ThrowIfDisposed();
  124. if (renderTarget == null)
  125. return null;
  126. IntPtr handle = renderTarget.GetSharedHandle();
  127. if (handle == IntPtr.Zero)
  128. throw new ArgumentException("Unable to access resource. The texture needs to be created as a shared resource.", "renderTarget");
  129. Format format;
  130. switch (renderTarget.Format)
  131. {
  132. case SurfaceFormat.Bgr32:
  133. format = Format.X8R8G8B8;
  134. break;
  135. case SurfaceFormat.Bgra32:
  136. format = Format.A8R8G8B8;
  137. break;
  138. default:
  139. throw new ArgumentException("Unexpected surface format. Supported formats are: SurfaceFormat.Bgr32, SurfaceFormat.Bgra32.", "renderTarget");
  140. }
  141. return new Texture(_device, renderTarget.Width, renderTarget.Height, 1, Usage.RenderTarget, format, Pool.Default, ref handle);
  142. }
  143. }
  144. }