private void ReleaseDevice()
        {
            if (_device != null)
            {
                if (!_device.Disposed)
                {
                    _device.Dispose();
                    _device = null;
                    OnDeviceDestroyed(EventArgs.Empty);
                }
            }

            if (_deviceEx != null)
            {
                if (!_deviceEx.Disposed)
                {
                    _deviceEx.Dispose();
                    _deviceEx = null;
                    OnDeviceDestroyed(EventArgs.Empty);
                }
            }

            D3Dimage.Lock();
            D3Dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero);
            D3Dimage.Unlock();

            ReleaseBackBuffer();
        }
        private void ReleaseBackBuffer()
        {
            if (_backBufferSurface != null && !_backBufferSurface.Disposed)
            {
                _backBufferSurface.Dispose();
                _backBufferSurface = null;

                D3Dimage.Lock();
                D3Dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero);
                D3Dimage.Unlock();
            }
        }
        private void OnRendering(object sender, EventArgs e)
        {
            Debug.Assert(D3Dimage.IsFrontBufferAvailable);

            if (DirectXStatus != DirectXStatus.Available)
            {
                return;
            }

            bool needToReset = false;

            try
            {
                if (Direct3D == null)
                {
                    InitializeDirect3D();
                }
                if (Device == null)
                {
                    InitializeDevice();
                    ForceRendering();
                }
                if (Device == null)
                {
                    // device might still be not available, so we'll just have to try again next time around
                    return;
                }

                if (_sizeChanged)
                {
                    _presentParameters.BackBufferWidth  = (int)ActualWidth;
                    _presentParameters.BackBufferHeight = (int)ActualHeight;
                    ReleaseBackBuffer();
                    OnDeviceLost(EventArgs.Empty);
                    Device.Reset(_presentParameters);
                    OnDeviceReset(EventArgs.Empty);
                    _sizeChanged = false;
                    ForceRendering();
                }

                bool needsRendering = ResetForceRendering();
                if (needsRendering)
                {
                    D3Dimage.Lock();
                    if (D3Dimage.IsFrontBufferAvailable)
                    {
                        Result result = Device.TestCooperativeLevel();
                        if (result.IsFailure)
                        {
                            // we'll change the status in the needToReset block below
                            DirectXStatus = DirectXStatus.Unavailable_Unknown;
                            throw new Direct3D9Exception("Device.TestCooperativeLevel() failed");
                        }

                        Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, new Color4(System.Drawing.Color.CornflowerBlue), 1, 0);
                        Device.BeginScene();

                        try
                        {
                            // call the user's method
                            OnMainLoop(EventArgs.Empty);
                        }
                        catch (Direct3D9Exception d3Dex)
                        {
                            if (d3Dex.Message.StartsWith("D3DERR_OUTOFVIDEOMEMORY"))
                            {
                                needToReset = true;
                            }
                            else
                            {
                                throw;
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [d] " + ex);
                        }

                        Device.EndScene();
                        Device.Present();
                    }
                    _backBufferSurface = Device.GetBackBuffer(0, 0);
                    D3Dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, _backBufferSurface.ComPointer);
                    D3Dimage.AddDirtyRect(new Int32Rect(0, 0, D3Dimage.PixelWidth, D3Dimage.PixelHeight));
                    D3Dimage.Unlock();
                }
            }
            catch (Direct3D9Exception)
            {
                needToReset = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [a] " + ex);
            }

            if (needToReset)
            {
                try
                {
                    InitializeDirect3D();
                    InitializeDevice();
                    if (DirectXStatus != DirectXStatus.Available)
                    {
                        // we were once available (because we were able to enter the OnRender function), but now we're not available
                        // This could be due to a return from Ctrl-Alt-Del under XP and things just aren't ready yet.
                        // Keep everything nulled out and we'll just try the next time around.
                        ReleaseDevice();
                        ReleaseDirect3D();
                        DirectXStatus = DirectXStatus.Available;
                    }
                    else
                    {
                        // we're available now, that's good
                        // force a rendering next time around
                        ForceRendering();
                    }
                }
                catch (Direct3D9Exception ex)
                {
                    MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [b] " + ex);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [c] " + ex);
                }
            }
        }
        /// <summary>
        /// Initializes the Device and starts up the d3dimage object
        /// </summary>
        private void InitializeDevice()
        {
            if (DirectXStatus != DirectXStatus.Available)
            {
                return;
            }

            Debug.Assert(Direct3D != null);

            ReleaseDevice();

            HwndSource hwnd = new HwndSource(0, 0, 0, 0, 0, D3Dimage.PixelWidth, D3Dimage.PixelHeight, "SlimDXControl", IntPtr.Zero);

            _presentParameters = new PresentParameters
            {
                SwapEffect             = SwapEffect.Copy,
                DeviceWindowHandle     = hwnd.Handle,
                Windowed               = true,
                BackBufferWidth        = ((int)ActualWidth <= 0) ? 1 : (int)ActualWidth,
                BackBufferHeight       = ((int)ActualHeight <= 0) ? 1 : (int)ActualHeight,
                BackBufferFormat       = _backbufferFormat,
                AutoDepthStencilFormat = _depthStencilFormat
            };

            try
            {
                if (UseDeviceEx)
                {
                    _deviceEx = new DeviceEx((Direct3DEx)Direct3D, 0,
                                             DeviceType.Hardware,
                                             hwnd.Handle,
                                             _createFlags,
                                             _presentParameters);
                }
                else
                {
                    _device = new Device(Direct3D, 0,
                                         DeviceType.Hardware,
                                         hwnd.Handle,
                                         _createFlags,
                                         _presentParameters);
                }
            }
            catch (Direct3D9Exception)
            {
                DirectXStatus = DirectXStatus.Unavailable_Unknown;
                return;
            }
            // call the user's ones
            OnDeviceCreated(EventArgs.Empty);
            OnDeviceReset(EventArgs.Empty);

            {
                // is it the case that someone else is nulling these out on us?  seems so
                // this means we need to be careful not to let multiple copies of the delegate get onto the list
                // not sure what else we can do here...
                CompositionTarget.Rendering            -= OnRendering;
                D3Dimage.IsFrontBufferAvailableChanged -= OnIsFrontBufferAvailableChanged;
                CompositionTarget.Rendering            += OnRendering;
                D3Dimage.IsFrontBufferAvailableChanged += OnIsFrontBufferAvailableChanged;
            }

            D3Dimage.Lock();
            _backBufferSurface = Device.GetBackBuffer(0, 0);
            D3Dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, _backBufferSurface.ComPointer);
            D3Dimage.Unlock();
        }