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.Black), 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) { //MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [d] " + ex.ToString()); throw; } 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) { //MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [a] " + ex.ToString()); throw; } 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) { //MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [b] " + ex.ToString()); throw; } catch (Exception) { //MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [c] " + ex.ToString()); throw; } } return; }
/// <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(); _presentParameters.SwapEffect = SwapEffect.Copy; _presentParameters.DeviceWindowHandle = hwnd.Handle; _presentParameters.Windowed = true; _presentParameters.BackBufferWidth = ((int)ActualWidth <= 0) ? 1 : (int)ActualWidth; _presentParameters.BackBufferHeight = ((int)ActualHeight <= 0) ? 1 : (int)ActualHeight; _presentParameters.BackBufferFormat = _backbufferFormat; _presentParameters.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(); return; }
/// <summary> /// Initializes the Direct3D objects and sets the Available flag /// </summary> private void InitializeDirect3D() { DirectXStatus = DirectXStatus.Unavailable_Unknown; ReleaseDevice(); ReleaseDirect3D(); // assume that we can't run at all under terminal services if (GetSystemMetrics(SM_REMOTESESSION) != 0) { DirectXStatus = DirectXStatus.Unavailable_RemoteSession; return; } int renderingTier = (RenderCapability.Tier >> 16); if (renderingTier < 2) { DirectXStatus = DirectXStatus.Unavailable_LowTier; return; } #if USE_XP_MODE _direct3D = new Direct3D(); UseDeviceEx = false; #else try { _direct3DEx = new Direct3DEx(); UseDeviceEx = true; } catch { try { _direct3D = new Direct3D(); UseDeviceEx = false; } catch (Direct3DX9NotFoundException) { DirectXStatus = DirectXStatus.Unavailable_MissingDirectX; return; } catch { DirectXStatus = DirectXStatus.Unavailable_Unknown; return; } } #endif bool ok; Result result; ok = Direct3D.CheckDeviceType(0, DeviceType.Hardware, _adapterFormat, _backbufferFormat, true, out result); if (!ok) { //const int D3DERR_NOTAVAILABLE = -2005530518; //if (result.Code == D3DERR_NOTAVAILABLE) //{ // ReleaseDirect3D(); // Available = Status.Unavailable_NotReady; // return; //} ReleaseDirect3D(); return; } ok = Direct3D.CheckDepthStencilMatch(0, DeviceType.Hardware, _adapterFormat, _backbufferFormat, _depthStencilFormat, out result); if (!ok) { ReleaseDirect3D(); return; } Capabilities deviceCaps = Direct3D.GetDeviceCaps(0, DeviceType.Hardware); if ((deviceCaps.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0) { _createFlags |= CreateFlags.HardwareVertexProcessing; } else { _createFlags |= CreateFlags.SoftwareVertexProcessing; } DirectXStatus = DirectXStatus.Available; return; }
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.Black), 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) { //MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [d] " + ex.ToString()); throw; } 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) { //MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [a] " + ex.ToString()); throw; } 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) { //MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [b] " + ex.ToString()); throw; } catch(Exception) { //MessageBox.Show(ex.Message, "Caught Exception in SlimDXControl.OnRendering() [c] " + ex.ToString()); throw; } } return; }
/// <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(); _presentParameters.SwapEffect = SwapEffect.Copy; _presentParameters.DeviceWindowHandle = hwnd.Handle; _presentParameters.Windowed = true; _presentParameters.BackBufferWidth = ((int) ActualWidth < 0) ? 1 : (int) ActualWidth; _presentParameters.BackBufferHeight = ((int) ActualHeight < 0) ? 1 : (int) ActualHeight; _presentParameters.BackBufferFormat = _backbufferFormat; _presentParameters.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(); return; }
/// <summary> /// Initializes the Direct3D objects and sets the Available flag /// </summary> private void InitializeDirect3D() { DirectXStatus = DirectXStatus.Unavailable_Unknown; ReleaseDevice(); ReleaseDirect3D(); // assume that we can't run at all under terminal services if(GetSystemMetrics(SM_REMOTESESSION) != 0) { DirectXStatus = DirectXStatus.Unavailable_RemoteSession; return; } int renderingTier = (RenderCapability.Tier >> 16); if(renderingTier < 2) { DirectXStatus = DirectXStatus.Unavailable_LowTier; return; } #if USE_XP_MODE _direct3D = new Direct3D(); UseDeviceEx = false; #else try { _direct3DEx = new Direct3DEx(); UseDeviceEx = true; } catch { try { _direct3D = new Direct3D(); UseDeviceEx = false; } catch(Direct3DX9NotFoundException) { DirectXStatus = DirectXStatus.Unavailable_MissingDirectX; return; } catch { DirectXStatus = DirectXStatus.Unavailable_Unknown; return; } } #endif bool ok; Result result; ok = Direct3D.CheckDeviceType(0, DeviceType.Hardware, _adapterFormat, _backbufferFormat, true, out result); if(!ok) { //const int D3DERR_NOTAVAILABLE = -2005530518; //if (result.Code == D3DERR_NOTAVAILABLE) //{ // ReleaseDirect3D(); // Available = Status.Unavailable_NotReady; // return; //} ReleaseDirect3D(); return; } ok = Direct3D.CheckDepthStencilMatch(0, DeviceType.Hardware, _adapterFormat, _backbufferFormat, _depthStencilFormat, out result); if(!ok) { ReleaseDirect3D(); return; } Capabilities deviceCaps = Direct3D.GetDeviceCaps(0, DeviceType.Hardware); if((deviceCaps.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0) _createFlags |= CreateFlags.HardwareVertexProcessing; else _createFlags |= CreateFlags.SoftwareVertexProcessing; DirectXStatus = DirectXStatus.Available; return; }