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); }
public void Resize(int width, int height) { mGlHandle = IntPtr.Zero; mDxSharedHandle = IntPtr.Zero; if (mFbo > -1) { gl.DeleteFramebuffer(mFbo); } mFbo = -1; if (mRboDepth > -1) { gl.DeleteRenderbuffer(mRboDepth); } mRboDepth = -1; if (mSharedTexture > -1) { gl.DeleteTexture(mSharedTexture); } mSharedTexture = -1; if (mSurface != null) { mSurface.Dispose(); } mSurface = null; if (mDevice != null) { mDevice.Dispose(); } mDevice = null; mWglInterop = new WGLInterop(); mDevice = new Device(DXInterop.Direct3DCreate9(DXInterop.D3D_SDK_VERSION)); mDevice = new DeviceEx( new Direct3DEx(), 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.PureDevice, new PresentParameters() { Windowed = true, SwapEffect = SwapEffect.Discard, DeviceWindowHandle = IntPtr.Zero, PresentationInterval = PresentInterval.Default, BackBufferFormat = Format.Unknown, BackBufferWidth = width, BackBufferHeight = height }); mSurface = Surface.CreateRenderTarget( mDevice, width, height, Format.A8R8G8B8, MultisampleType.None, 0, false, ref mDxSharedHandle); mFbo = gl.GenFramebuffer(); mSharedTexture = gl.GenTexture(); mGlHandle = mWglInterop.WglDXOpenDeviceNV(mDevice.NativePointer); mWglInterop.WglDXSetResourceShareHandleNV(mSurface.NativePointer, mDxSharedHandle); var genHandle = mWglInterop.WglDXRegisterObjectNV( mGlHandle, mSurface.NativePointer, (uint)mSharedTexture, (uint)TextureTarget.Texture2D, WGLInterop.WGL_ACCESS_READ_WRITE_NV); mGlHandles = new IntPtr[] { genHandle }; gl.BindFramebuffer(FramebufferTarget.Framebuffer, mFbo); gl.FramebufferTexture2D( FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, mSharedTexture, 0); mRboDepth = gl.GenRenderbuffer(); gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, mRboDepth); gl.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent24, width, height); gl.FramebufferRenderbuffer( FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, mRboDepth); gl.BindFramebuffer(FramebufferTarget.Framebuffer, 0); }