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);
        }
예제 #2
0
        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);
        }