namespace RealTimeGraphEx.DX2D { using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; using SharpDX.Direct3D9; using System.Threading; class DX10ImageSource : D3DImage, IDisposable { private static int ActiveClients; private static Direct3DEx D3DContext; private static DeviceEx D3DDevice; private Texture RenderTarget; public DX10ImageSource() { this.StartD3D(); DX10ImageSource.ActiveClients++; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "RenderTarget")] public void Dispose() { this.SetRenderTargetDX10(null); // Here, we have our Dispose call Disposer.SafeDispose(ref this.RenderTarget); DX10ImageSource.ActiveClients--; this.EndD3D(); } public void InvalidateD3DImage() { if (this.RenderTarget != null) { base.Lock(); base.AddDirtyRect(new Int32Rect(0, 0, base.PixelWidth, base.PixelHeight)); base.Unlock(); } } public void SetRenderTargetDX10(SharpDX.Direct3D10.Texture2D renderTarget) { if (this.RenderTarget != null) { this.RenderTarget = null; base.Lock(); base.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero); base.Unlock(); } if (renderTarget == null) return; if (!IsShareable(renderTarget)) { throw new ArgumentException("Texture must be created with ResourceOptionFlags.Shared"); } Format format = DX10ImageSource.TranslateFormat(renderTarget); if (format == Format.Unknown) { throw new ArgumentException("Texture format is not compatible with OpenSharedResource"); } IntPtr handle = GetSharedHandle(renderTarget); if (handle == IntPtr.Zero) { throw new ArgumentNullException("Handle"); } this.RenderTarget = new Texture(DX10ImageSource.D3DDevice, renderTarget.Description.Width, renderTarget.Description.Height, 1, Usage.RenderTarget, format, Pool.Default, ref handle); using (Surface surface = this.RenderTarget.GetSurfaceLevel(0)) { base.Lock(); base.SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface.NativePointer); base.Unlock(); } } private void StartD3D() { if (DX10ImageSource.ActiveClients != 0) { return; } DX10ImageSource.D3DContext = new Direct3DEx(); var presentparams = new PresentParameters(); presentparams.Windowed = true; presentparams.SwapEffect = SwapEffect.Discard; presentparams.DeviceWindowHandle = NativeMethods.GetDesktopWindow(); presentparams.PresentationInterval = PresentInterval.Default; presentparams.MultiSampleQuality = 0; //Set By Roy. DX10ImageSource.D3DDevice = new DeviceEx(D3DContext, 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve, presentparams); } private void EndD3D() { if (DX10ImageSource.ActiveClients != 0) { return; } Disposer.SafeDispose(ref this.RenderTarget); Disposer.SafeDispose(ref DX10ImageSource.D3DDevice); Disposer.SafeDispose(ref DX10ImageSource.D3DContext); } private IntPtr GetSharedHandle(SharpDX.Direct3D10.Texture2D Texture) { var resource = Texture.QueryInterface(); var result = resource.SharedHandle; resource.Dispose(); return result; } private static Format TranslateFormat(SharpDX.Direct3D10.Texture2D Texture) { switch (Texture.Description.Format) { case SharpDX.DXGI.Format.R10G10B10A2_UNorm: return SharpDX.Direct3D9.Format.A2B10G10R10; case SharpDX.DXGI.Format.R16G16B16A16_Float: return SharpDX.Direct3D9.Format.A16B16G16R16F; case SharpDX.DXGI.Format.B8G8R8A8_UNorm: return SharpDX.Direct3D9.Format.A8R8G8B8; default: return SharpDX.Direct3D9.Format.Unknown; } } private static bool IsShareable(SharpDX.Direct3D10.Texture2D Texture) { return (Texture.Description.OptionFlags & SharpDX.Direct3D10.ResourceOptionFlags.Shared) != 0; } } }