using System; using System.Runtime.InteropServices; using Microsoft.Xna.Framework.Graphics; using SharpDX.Direct3D9; using DeviceType = SharpDX.Direct3D9.DeviceType; using PresentInterval = SharpDX.Direct3D9.PresentInterval; using Texture = SharpDX.Direct3D9.Texture; namespace WpfInteropSample { /// /// Represents a Direct3D 9 device required for Direct3D 11 interoperability. /// /// /// It is not possible to set a Direct3D 11 resource (e.g. a texture or render target) in WPF /// directly because WPF requires Direct3D 9. The class creates a new /// Direct3D 9 device which can be used for sharing resources between Direct3D 11 and Direct3D /// 9. Call to convert a texture from Direct3D 11 to Direct3D 9. /// internal class D3D9 : IDisposable { // The code requires Windows Vista and up using the Windows Display Driver Model (WDDM). // It does not work with the Windows 2000 Display Driver Model (XDDM). private bool _disposed; private Direct3DEx _direct3D; private DeviceEx _device; /// /// Initializes a new instance of the class. /// public D3D9() { // Create Direct3DEx device on Windows Vista/7/8 with a display configured to use // the Windows Display Driver Model (WDDM). Use Direct3D on any other platform. _direct3D = new Direct3DEx(); PresentParameters presentparams = new PresentParameters { Windowed = true, SwapEffect = SwapEffect.Discard, PresentationInterval = PresentInterval.Default, // The device back buffer is not used. BackBufferFormat = Format.Unknown, BackBufferWidth = 1, BackBufferHeight = 1, // Use dummy window handle. DeviceWindowHandle = GetDesktopWindow() }; _device = new DeviceEx(_direct3D, 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve, presentparams); } /// /// Releases unmanaged resources before an instance of the class is /// reclaimed by garbage collection. /// /// /// This method releases unmanaged resources by calling the virtual /// method, passing in . /// ~D3D9() { Dispose(false); } /// /// Releases all resources used by an instance of the class. /// /// /// This method calls the virtual method, passing in /// , and then suppresses finalization of the instance. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Releases the unmanaged resources used by an instance of the class /// and optionally releases the managed resources. /// /// /// to release both managed and unmanaged resources; /// to release only unmanaged resources. /// protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // Dispose managed resources. if (_device != null) { _device.Dispose(); _device = null; } if (_direct3D != null) { _direct3D.Dispose(); _direct3D = null; } } // Release unmanaged resources. _disposed = true; } } [DllImport("user32.dll", SetLastError = false)] private static extern IntPtr GetDesktopWindow(); private void ThrowIfDisposed() { if (_disposed) throw new ObjectDisposedException(GetType().FullName); } /// /// Creates Direct3D 9 texture from the specified Direct3D 11 texture. /// (The content is shared between the devices.) /// /// The Direct3D 11 texture. /// The Direct3D 9 texture. /// /// The Direct3D 11 texture is not a shared resource, or the texture format is not /// supported. /// public Texture GetSharedTexture(Texture2D renderTarget) { ThrowIfDisposed(); if (renderTarget == null) return null; IntPtr handle = renderTarget.GetSharedHandle(); if (handle == IntPtr.Zero) throw new ArgumentException("Unable to access resource. The texture needs to be created as a shared resource.", "renderTarget"); Format format; switch (renderTarget.Format) { case SurfaceFormat.Bgr32: format = Format.X8R8G8B8; break; case SurfaceFormat.Bgra32: format = Format.A8R8G8B8; break; default: throw new ArgumentException("Unexpected surface format. Supported formats are: SurfaceFormat.Bgr32, SurfaceFormat.Bgra32.", "renderTarget"); } return new Texture(_device, renderTarget.Width, renderTarget.Height, 1, Usage.RenderTarget, format, Pool.Default, ref handle); } } }