diff options
Diffstat (limited to 'Software/Visual_Studio/SideChains/RealTimeGraphEx/DX2D/Direct2DControl.cs')
| -rw-r--r-- | Software/Visual_Studio/SideChains/RealTimeGraphEx/DX2D/Direct2DControl.cs | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphEx/DX2D/Direct2DControl.cs b/Software/Visual_Studio/SideChains/RealTimeGraphEx/DX2D/Direct2DControl.cs new file mode 100644 index 000000000..4ca6da35b --- /dev/null +++ b/Software/Visual_Studio/SideChains/RealTimeGraphEx/DX2D/Direct2DControl.cs @@ -0,0 +1,261 @@ +namespace RealTimeGraphEx.DX2D +{ + using SharpDX; + using SharpDX.Direct2D1; + using SharpDX.Direct3D10; + using SharpDX.DXGI; + using System; + using System.ComponentModel; + using System.Diagnostics; + using System.Threading; + using System.Windows; + using Device = SharpDX.Direct3D10.Device1; + using FeatureLevel = SharpDX.Direct3D10.FeatureLevel; + + public abstract class Direct2DControl : System.Windows.Controls.Image + { + private Device Device; + private Texture2D RenderTarget; + private DX10ImageSource D3DSurface; + private readonly Stopwatch RenderTimer; + private RenderTarget m_d2dRenderTarget; + protected SharpDX.Direct2D1.Factory m_d2dFactory; + private bool enableRendering; + //private Stopwatch renderWatch; + + //public int FrameRate { get; set; } + + public Direct2DControl() + { + //renderWatch = new Stopwatch(); + //FrameRate = 60; + this.RenderTimer = new Stopwatch(); + this.Loaded += this.Window_Loaded; + this.Unloaded += this.Window_Closing; + this.Stretch = System.Windows.Media.Stretch.Fill; + } + + public void EnableRendering() + { + enableRendering = true; + } + + public void DisableRendering() + { + enableRendering = false; + } + + private void Window_Loaded(object sender, RoutedEventArgs e) + { + if (Direct2DControl.IsInDesignMode) + { + return; + } + + this.StartD3D(); + this.StartRendering(); + } + + private void Window_Closing(object sender, RoutedEventArgs e) + { + if (Direct2DControl.IsInDesignMode) + { + return; + } + + this.StopRendering(); + this.EndD3D(); + } + + private void StartD3D() + { + this.Device = new Device(DriverType.Hardware, DeviceCreationFlags.BgraSupport, FeatureLevel.Level_10_0); + + this.D3DSurface = new DX10ImageSource(); + this.D3DSurface.IsFrontBufferAvailableChanged += OnIsFrontBufferAvailableChanged; + + this.CreateAndBindTargets(); + + this.Source = this.D3DSurface; + } + + private void EndD3D() + { + this.D3DSurface.IsFrontBufferAvailableChanged -= OnIsFrontBufferAvailableChanged; + this.Source = null; + + Disposer.SafeDispose(ref this.m_d2dRenderTarget); + Disposer.SafeDispose(ref this.m_d2dFactory); + Disposer.SafeDispose(ref this.D3DSurface); + Disposer.SafeDispose(ref this.RenderTarget); + Disposer.SafeDispose(ref this.Device); + } + + private void CreateAndBindTargets() + { + if (this.D3DSurface == null) return; + + this.D3DSurface.SetRenderTargetDX10(null); + + Disposer.SafeDispose(ref this.m_d2dRenderTarget); + Disposer.SafeDispose(ref this.m_d2dFactory); + Disposer.SafeDispose(ref this.RenderTarget); + + var width = Math.Max((int)this.ActualWidth, 100); + var height = Math.Max((int)this.ActualHeight, 100); + + var colordesc = new Texture2DDescription + { + BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource, + Format = Format.B8G8R8A8_UNorm, + Width = width, + Height = height, + MipLevels = 1, + SampleDescription = new SampleDescription(1, 0), + Usage = ResourceUsage.Default, + OptionFlags = ResourceOptionFlags.Shared, + CpuAccessFlags = CpuAccessFlags.None, + ArraySize = 1 + }; + + this.RenderTarget = new Texture2D(this.Device, colordesc); + + var surface = this.RenderTarget.QueryInterface<Surface>(); + + m_d2dFactory = new SharpDX.Direct2D1.Factory(); + var rtp = new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)); + m_d2dRenderTarget = new RenderTarget(m_d2dFactory, surface, rtp); + + this.D3DSurface.SetRenderTargetDX10(this.RenderTarget); + } + + private void StartRendering() + { + if (this.RenderTimer.IsRunning) + { + return; + } + + System.Windows.Media.CompositionTarget.Rendering += OnRendering; + this.RenderTimer.Start(); + //renderWatch.Start(); + } + + private void StopRendering() + { + if (!this.RenderTimer.IsRunning) + { + return; + } + + System.Windows.Media.CompositionTarget.Rendering -= OnRendering; + this.RenderTimer.Stop(); + RenderTimer.Stop(); + } + + private void OnRendering(object sender, EventArgs e) + { + if (!this.RenderTimer.IsRunning) + { + return; + } + + //if (renderWatch.ElapsedMilliseconds >= (1000 / FrameRate)) + //{ + //renderWatch.Restart(); + if (enableRendering) + { + this.PrepareAndCallRender(); + this.D3DSurface.InvalidateD3DImage(); + } + //} + } + + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) + { + this.CreateAndBindTargets(); + base.OnRenderSizeChanged(sizeInfo); + } + + private void PrepareAndCallRender() + { + var device = this.Device; + if (device == null) + { + return; + } + + var renderTarget = this.RenderTarget; + if (renderTarget == null) + { + return; + } + + var targetWidth = renderTarget.Description.Width; + var targetHeight = renderTarget.Description.Height; + + device.Rasterizer.SetViewports(new Viewport(0, 0, targetWidth, targetHeight, 0.0f, 1.0f)); + + + // Does the actual rendering + m_d2dRenderTarget.BeginDraw(); + this.Render(m_d2dRenderTarget); + m_d2dRenderTarget.EndDraw(); + //this.ShowFramesPerSecondsOnDebug(); + + device.Flush(); + } + + /// <summary> + /// Does the actual rendering. + /// BeginDraw and EndDraw are already called by the caller. + /// </summary> + public abstract void Render(RenderTarget target); + + /// <summary> + /// Shows the number of frames per seconds on the debug line + /// </summary> + private void ShowFramesPerSecondsOnDebug() + { + // Spits out the Frames per second + f++; + if ((DateTime.Now - last).TotalSeconds > 1) + { + System.Diagnostics.Debug.WriteLine(f); + f = 0; + last = DateTime.Now; + } + } + + private DateTime last; + private int f; + + private void OnIsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e) + { + // this fires when the screensaver kicks in, the machine goes into sleep or hibernate + // and any other catastrophic losses of the d3d device from WPF's point of view + if (this.D3DSurface.IsFrontBufferAvailable) + { + this.StartRendering(); + } + else + { + this.StopRendering(); + } + } + + /// <summary> + /// Gets f value indicating whether the control is in design mode + /// (running in Blend or Visual Studio). + /// </summary> + public static bool IsInDesignMode + { + get + { + var prop = DesignerProperties.IsInDesignModeProperty; + var isDesignMode = (bool)DependencyPropertyDescriptor.FromProperty(prop, typeof(FrameworkElement)).Metadata.DefaultValue; + return isDesignMode; + } + } + } +}
\ No newline at end of file |
