/// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> private void Dispose(bool disposing) { if (_disposed) { return; } if (disposing) { Settings.Window.ParentChanged -= Window_ParentChanged; if (_topLevelControl != null) { _topLevelControl.ParentChanged -= Window_ParentChanged; } if (_parentForm != null) { _parentForm.ResizeBegin -= _parentForm_ResizeBegin; _parentForm.ResizeEnd -= _parentForm_ResizeEnd; _parentForm.Activated -= _parentForm_Activated; _parentForm.Deactivate -= _parentForm_Deactivate; } Settings.Window.Resize -= Window_Resize; if (_renderTarget != null) { _renderTarget.Dispose(); _renderTarget = null; } Gorgon.Log.Print("GorgonSwapChain '{0}': Removing D3D11 swap chain...", LoggingLevel.Simple, Name); if (GISwapChain != null) { // Always go to windowed mode before destroying the swap chain. GISwapChain.SetFullscreenState(false, null); GISwapChain.Dispose(); } if (Graphics != null) { Graphics.RemoveTrackedObject(this); } GISwapChain = null; } Graphics = null; _disposed = true; }
/// <summary> /// Function to resize the back buffers. /// </summary> private void ResizeBuffers() { if (BeforeSwapChainResized != null) { BeforeSwapChainResized(this, EventArgs.Empty); } var targetReseat = _renderTarget.OnSwapChainResize(); var depthReseat = DepthStencilBuffer != null && DepthStencilBuffer.OnDepthStencilResize(); GISwapChain.ResizeBuffers(Settings.BufferCount, Settings.VideoMode.Width, Settings.VideoMode.Height, (GI.Format)Settings.VideoMode.Format, GI.SwapChainFlags.AllowModeSwitch); CreateResources(targetReseat, depthReseat); if (AfterSwapChainResized != null) { AfterSwapChainResized(this, new GorgonAfterSwapChainResizedEventArgs(this)); } }
/// <summary> /// Handles the Deactivate event of the _parentForm control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void _parentForm_Deactivate(object sender, EventArgs e) { try { if ((GISwapChain == null) || (!Graphics.ResetFullscreenOnFocus)) { return; } Graphics.GetFullScreenSwapChains(); // Reset the video mode to windowed. // Note: For some reason, this is different than it was on SlimDX. I never had to do this before, but with // SharpDX I now have to handle the transition from full screen to windowed manually. if (!GISwapChain.IsFullScreen) { return; } GISwapChain.SetFullscreenState(false, null); Settings.IsWindowed = true; ((Form)Settings.Window).WindowState = FormWindowState.Minimized; } catch (Exception ex) { #if DEBUG GorgonException.Catch(ex, () => GorgonDialogs.ErrorBox(_parentForm, string.Format(Resources.GORGFX_CATASTROPHIC_ERROR, Gorgon.Log.LogPath), null, ex)); // If we fail in here, then we have a terminal error in Gorgon, don't risk further corruption. Gorgon.Quit(); #else GorgonException.Catch(ex); #endif } }
/// <summary> /// Handles the Activated event of the _parentForm control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void _parentForm_Activated(object sender, EventArgs e) { try { if ((GISwapChain == null) || (!Graphics.ResetFullscreenOnFocus)) { return; } Graphics.GetFullScreenSwapChains(); if (GISwapChain.IsFullScreen) { return; } ((Form)Settings.Window).WindowState = FormWindowState.Normal; // Get the current video output. GISwapChain.SetFullscreenState(true, null); Settings.IsWindowed = false; } catch (Exception ex) { #if DEBUG GorgonException.Catch(ex, () => GorgonDialogs.ErrorBox(_parentForm, string.Format(Resources.GORGFX_CATASTROPHIC_ERROR, Gorgon.Log.LogPath), null, ex)); // If we fail in here, then we have a terminal error in Gorgon, don't risk further corruption. Gorgon.Quit(); #else GorgonException.Catch(ex); #endif } }
/// <summary> /// Function to flip the buffers to the front buffer. /// </summary> /// <param name="interval">Vertical blank interval.</param> /// <remarks>If <paramref name="interval"/> parameter is greater than 0, then this method will synchronize to the vertical blank count specified by interval Passing 0 will display immediately. /// <para>If the window that the swap chain is bound with is occluded and/or the swap chain is in between a mode switch, then this method will place the swap chain into stand by mode, and will recover (i.e. turn off stand by) once the device is ready for rendering again.</para> /// </remarks> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the interval parameter is less than 0 or greater than 4.</exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the method encounters an unrecoverable error.</exception> public void Flip(int interval) { var flags = GI.PresentFlags.None; Result result = Result.Ok; GorgonDebug.AssertParamRange(interval, 0, 4, true, true, "interval"); if (GISwapChain == null) { return; } if (IsInStandBy) { flags = GI.PresentFlags.Test; } try { IsInStandBy = false; GISwapChain.Present(interval, flags); } catch (SharpDXException sdex) { if (sdex.ResultCode == Result.Ok) { return; } if (!result.Success) { throw new GorgonException(GorgonResult.CannotWrite, Resources.GORGFX_CATASTROPHIC_ERROR); } IsInStandBy = true; } }
/// <summary> /// Function to update the fullscreen/windowed mode state. /// </summary> private void ModeStateUpdate() { var e = new GorgonBeforeStateTransitionEventArgs(!Settings.IsWindowed); GI.ModeDescription mode = GorgonVideoMode.Convert(Settings.VideoMode); try { GISwapChain.ResizeTarget(ref mode); if (!Settings.IsWindowed) { if (BeforeStateTransition != null) { BeforeStateTransition(this, new GorgonBeforeStateTransitionEventArgs(true)); } if (!e.Cancel) { // We don't need to force an output. We'll just let DXGI figure it out from the // window area on the monitor. Currently SharpDX's ContainingOutput property is // buggy in 2.4.2 and will return multiple ref counts for each time the property is // read. v2.5.0 is in dev, but now has the problem of not returning the correct output. GISwapChain.SetFullscreenState(true, null); if (_parentForm != null) { _parentForm.Activated += _parentForm_Activated; _parentForm.Deactivate += _parentForm_Deactivate; } } } else { if (BeforeStateTransition != null) { BeforeStateTransition(this, new GorgonBeforeStateTransitionEventArgs(false)); } if (!e.Cancel) { GISwapChain.SetFullscreenState(false, null); } } } catch (SharpDXException sdEx) { switch (sdEx.ResultCode.Code) { case (int)GI.DXGIStatus.ModeChangeInProgress: Gorgon.Log.Print("GorgonSwapChain '{0}': Could not switch to full screen mode because the device was busy switching to full screen on another output.", LoggingLevel.All, Name); break; default: if (sdEx.ResultCode != GI.ResultCode.NotCurrentlyAvailable) { throw; } Gorgon.Log.Print( "GorgonSwapChain '{0}': Could not switch to full screen mode because the device is not currently available. Possible causes are: .", LoggingLevel.All, Name); break; } } ResizeBuffers(); if ((!e.Cancel) && (AfterStateTransition != null)) { AfterStateTransition(this, new GorgonAfterSwapChainResizedEventArgs(this)); } }