D3D9.cs 6.2 KB

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