public override void OnApplyTemplate() { var window = Window.GetWindow(this); _windowHandle = window is null ? IntPtr.Zero : new WindowInteropHelper(window).Handle; _hwnd = new HwndSource(0, 0, 0, 0, 0, "Offscreen Window", _windowHandle); _windowInfo = Utilities.CreateWindowsWindowInfo(_hwnd.Handle); _wpfImage = new Image() { RenderTransformOrigin = new Point(0.5, 0.5), RenderTransform = new ScaleTransform(1, -1) }; var grid = new Grid(); _framesTextBlock = new TextBlock() { HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top, Margin = new Thickness(5), Foreground = new SolidColorBrush(Colors.Blue), FontWeight = FontWeights.Bold }; Panel.SetZIndex(_framesTextBlock, 1); grid.Children.Add(_framesTextBlock); grid.Children.Add(_wpfImage); AddChild(grid); switch (UpdateStrategy) { case UpdateStrategy.WriteableBitmapImage: _updateStrategy = new UpdateStrategyWriteableBitmap(); break; case UpdateStrategy.D3DSurface: _updateStrategy = new UpdateStrategyD3D(); break; } if (UseSeperateRenderThread) { _cts = new CancellationTokenSource(); _renderThread = new Thread((object boxedToken) => { InitOpenGLContext(); while (!_cts.IsCancellationRequested) { UpdateFramerate(); if (_wasResized) { _wasResized = false; _updateStrategy.Resize((int)Math.Round(ActualWidth), (int)Math.Round(ActualHeight)); Dispatcher.Invoke(() => _wpfImage.Source = _updateStrategy.CreateImageSource()); } GLRender?.Invoke(this, EventArgs.Empty); _updateStrategy?.Draw(); Dispatcher.Invoke(() => _updateStrategy.InvalidateImageSource()); } _renderThread.Join(); }) { IsBackground = true, Priority = ThreadPriority.Highest }; _renderThread.Start(_cts); _stopwatch.Start(); } else { _dt = new DispatcherTimer(DispatcherPriority.Send) { Interval = TimeSpan.FromMilliseconds(1) }; InitOpenGLContext(); _dt.Tick += (o, e) => { UpdateFramerate(); if (_wasResized) { _wasResized = false; _updateStrategy.Resize((int)Math.Round(ActualWidth), (int)Math.Round(ActualHeight)); _wpfImage.Source = _updateStrategy.CreateImageSource(); } GLRender?.Invoke(this, EventArgs.Empty); _updateStrategy.Draw(); _updateStrategy.InvalidateImageSource(); }; _dt.Start(); _stopwatch.Start(); } base.OnApplyTemplate(); }
private void OnLoaded(object sender, RoutedEventArgs e) { if (!DesignerProperties.GetIsInDesignMode(new DependencyObject())) { Window.GetWindow(this).Closing += (ss, ee) => { mCts?.Cancel(); } } ; var ptr = DXInterop.Direct3DCreate9(DXInterop.D3D_SDK_VERSION); var window = Window.GetWindow(this); mWndHandle = window is null ? IntPtr.Zero : new WindowInteropHelper(window).Handle; mHwnd = new HwndSource(0, 0, 0, 0, 0, "Offscreen Window", mWndHandle); mWindowInfo = Utilities.CreateWindowsWindowInfo(mHwnd.Handle); mTargetFramerate = FramerateLimit > 0 ? TimeSpan.FromMilliseconds(1000.0d / FramerateLimit) : TimeSpan.Zero; switch (UpdateStrategy) { case UpdateStrategy.WriteableBitmapImage: mUpdateStrategy = new UpdateStrategyWriteableBitmap(); break; case UpdateStrategy.D3DImage: mUpdateStrategy = new UpdateStrategyD3D(); break; } mRenderTread = new Thread((object boxedToken) => { InitOpenGLContext(); while (!mCts.IsCancellationRequested) { ++mFrames; if (mWasResized) { mWasResized = false; mUpdateStrategy.Resize((int)Math.Round(ActualWidth), (int)Math.Round(ActualHeight)); Dispatcher.Invoke(() => mRenderedImg = mUpdateStrategy.CreateImageSource()); } var rt = Render(); var sleep = mTargetFramerate - rt; mAccumulatedDt += rt; if (FramerateLimit > 0) { mAccumulatedDt += sleep; } if (mAccumulatedDt >= TimeSpan.FromSeconds(1)) { mLastFrames = mFrames; mFrames = 0; mAccumulatedDt = TimeSpan.Zero; } if (FramerateLimit > 0) { Thread.Sleep(sleep > TimeSpan.Zero ? sleep : TimeSpan.Zero); } Dispatcher.Invoke(() => InvalidateVisual()); } mRenderTread.Join(); }) { IsBackground = true }; mRenderTread.Start(mCts); }