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(); }