/// <summary> /// Function to update the settings for the swap chain. /// </summary> /// <param name="mode">New video mode to use.</param> /// <param name="depthStencilFormat">The format of the internal depth/stencil buffer.</param> /// <param name="isWindowed">TRUE to switch to windowed mode, FALSE to switch to full screen.</param> /// <param name="bufferCount">Number of back buffers.</param> /// <remarks>If the <see cref="P:GorgonLibrary.Graphics.GorgonSwapChainSettings.SwapEffect">SwapEffect</see> for the swap chain is set to discard, then the <paramref name="bufferCount"/> must be greater than 1.</remarks> /// <exception cref="System.ArgumentException">Thrown when the <see cref="P:GorgonLibrary.Graphics.GorgonSwapChainSettings.Window">GorgonSwapChainSettings.Window</see> property is NULL (Nothing in VB.Net), and the <see cref="P:GorgonLibrary.Gorgon.ApplicationForm">Gorgon application window</see> is NULL. /// <para>-or-</para> /// <para>Thrown when the <see cref="GorgonLibrary.Graphics.GorgonVideoMode.Format">GorgonSwapChainSettings.VideoMode.Format</see> property cannot be used by the video device for displaying data.</para> /// </exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the video output could not be determined from the window. /// <para>-or-</para> /// <para>Thrown when the swap chain is going to full screen mode and another swap chain is already on the video output.</para> /// </exception> public void UpdateSettings(GorgonVideoMode mode, bool isWindowed, BufferFormat depthStencilFormat, int bufferCount) { if (GISwapChain == null) { return; } if (_parentForm != null) { _parentForm.Activated -= _parentForm_Activated; _parentForm.Deactivate -= _parentForm_Deactivate; } // Assign the new settings. Settings.IsWindowed = isWindowed; Settings.VideoMode = mode; Settings.BufferCount = bufferCount; Settings.DepthStencilFormat = depthStencilFormat; // Validate and modify the settings as appropriate. Graphics.ImmediateContext.Output.ValidateSwapChainSettings(Settings); ModeStateUpdate(); // Ensure our window is the proper size. if ((_parentForm == Settings.Window) && (Settings.IsWindowed) && ((Settings.VideoMode.Width != Settings.Window.ClientSize.Width) || (Settings.VideoMode.Height != Settings.Window.ClientSize.Height))) { Settings.Window.ClientSize = new Size(Settings.VideoMode.Width, Settings.VideoMode.Height); } }
/// <summary> /// Function to find the nearest video mode to the one specified. /// </summary> /// <param name="output">Output for the video mode.</param> /// <param name="mode">Mode to find.</param> /// <returns>The closest matching video mode to the <paramref name="mode"/> parameter.</returns> internal GorgonVideoMode FindMode(GI.Output output, GorgonVideoMode mode) { GI.ModeDescription findMode = GorgonVideoMode.Convert(mode); GI.ModeDescription result; output.GetClosestMatchingMode(VideoDevice.Graphics.D3DDevice, findMode, out result); return(GorgonVideoMode.Convert(result)); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonVideoOutput"/> class. /// </summary> internal GorgonVideoOutput() { var area = Screen.AllScreens.Aggregate(Rectangle.Empty, (current, t) => Rectangle.Union(current, t.Bounds)); Index = 0; Handle = Win32API.GetMonitor(null); IsAttachedToDesktop = true; Name = Resources.GORGFX_OUTPUT_SOFTWARE_DEV_NAME; OutputBounds = Screen.PrimaryScreen.Bounds; Rotation = 0; DefaultVideoMode = new GorgonVideoMode(area.Width, area.Height, BufferFormat.R8G8B8A8_UIntNormal); }
#pragma warning disable 0618 /// <summary> /// Function to find the nearest video mode to the one specified. /// </summary> /// <param name="mode">Mode to find.</param> /// <returns>The closest matching video mode to the <paramref name="mode"/> parameter.</returns> public GorgonVideoMode FindMode(GorgonVideoMode mode) { if ((VideoDevice.Graphics == null) || (VideoDevice.Graphics.D3DDevice == null)) { return(mode); } using (var output = VideoDevice.Graphics.Adapter.GetOutput(Index)) { return(FindMode(output, mode)); } }
/// <summary> /// Function to retrieve the video modes for the output. /// </summary> /// <param name="output">Output that owns the video modes.</param> /// <param name="D3DDevice">D3D device for filtering supported display modes.</param> /// <param name="giOutput">Output that contains the video modes.</param> private static void GetVideoModes(GorgonVideoOutput output, D3D.Device D3DDevice, Output giOutput) { var formats = (BufferFormat[])Enum.GetValues(typeof(BufferFormat)); Gorgon.Log.Print("Retrieving video modes for output '{0}'...", LoggingLevel.Simple, output.Name); Gorgon.Log.Print("===================================================================", LoggingLevel.Verbose); // Test each format for display compatibility. foreach (var format in formats) { var giFormat = (Format)format; ModeDescription[] modes = giOutput.GetDisplayModeList(giFormat, DisplayModeEnumerationFlags.Scaling | DisplayModeEnumerationFlags.Interlaced); if ((modes == null) || (modes.Length <= 0)) { continue; } GorgonVideoMode[] videoModes = (from mode in modes where (D3DDevice.CheckFormatSupport(giFormat) & D3D.FormatSupport.Display) == D3D.FormatSupport.Display select GorgonVideoMode.Convert(mode)).ToArray(); if (videoModes.Length > 0) { output.VideoModes = new ReadOnlyCollection <GorgonVideoMode>(videoModes); } } // Output to log. foreach (var videoMode in output.VideoModes) { Gorgon.Log.Print("Mode: {0}x{1}, Format: {2}, Refresh Rate: {3}/{4}", LoggingLevel.Verbose, videoMode.Width, videoMode.Height, videoMode.Format, videoMode.RefreshRateNumerator, videoMode.RefreshRateDenominator); } Gorgon.Log.Print("===================================================================", LoggingLevel.Verbose); Gorgon.Log.Print("Found {0} video modes for output '{1}'.", LoggingLevel.Simple, output.VideoModes.Count, output.Name); }
/// <summary> /// Function to update the settings for the render target. /// </summary> /// <param name="mode">New video mode to use.</param> /// <param name="depthStencilFormat">The format of the internal depth/stencil buffer.</param> /// <exception cref="GorgonLibrary.GorgonException"> /// Thrown when the <see cref="GorgonLibrary.Graphics.GorgonVideoMode.Format">GorgonSwapChainSettings.VideoMode.Format</see> property cannot be used by the video device for displaying data. /// <para>-or-</para> /// <para>The width and height are not valid for the render target.</para> /// </exception> public void UpdateSettings(GorgonVideoMode mode, BufferFormat depthStencilFormat) { UpdateSettings(mode, Settings.IsWindowed, depthStencilFormat, Settings.BufferCount); }
/// <summary> /// Function to update the settings for the swap chain. /// </summary> /// <param name="mode">New video mode to use.</param> /// <param name="isWindowed">TRUE to use windowed mode, FALSE to use full screen mode.</param> /// <exception cref="System.ArgumentException">Thrown when the <see cref="P:GorgonLibrary.Graphics.GorgonSwapChainSettings.Window">GorgonSwapChainSettings.Window</see> property is NULL (Nothing in VB.Net), and the <see cref="P:GorgonLibrary.Gorgon.ApplicationForm">Gorgon application window</see> is NULL. /// <para>-or-</para> /// <para>Thrown when the <see cref="GorgonLibrary.Graphics.GorgonVideoMode.Format">GorgonSwapChainSettings.VideoMode.Format</see> property cannot be used by the video device for displaying data.</para> /// <para>-or-</para> /// <para>Thrown when the <see cref="GorgonLibrary.Graphics.GorgonMultisampling.Quality">GorgonSwapChainSettings.Multisamplings.Quality</see> property is higher than what the video device can support.</para> /// </exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the video output could not be determined from the window. /// <para>-or-</para> /// <para>Thrown when the swap chain is going to full screen mode and another swap chain is already on the video output.</para> /// </exception> public void UpdateSettings(GorgonVideoMode mode, bool isWindowed) { UpdateSettings(Settings.VideoMode, isWindowed, Settings.DepthStencilFormat, Settings.BufferCount); }
/// <summary> /// Function to intialize the swap chain. /// </summary> internal void Initialize() { var D3DSettings = new GI.SwapChainDescription(); // Resize the window to match requested mode size. if ((_parentForm == Settings.Window) && (Settings.IsWindowed) && (!Settings.NoClientResize)) { _parentForm.ClientSize = new Size(Settings.VideoMode.Width, Settings.VideoMode.Height); } AutoResize = !Settings.NoClientResize; Graphics.GetFullScreenSwapChains(); D3DSettings.BufferCount = Settings.BufferCount; D3DSettings.Flags = GI.SwapChainFlags.AllowModeSwitch; D3DSettings.IsWindowed = true; D3DSettings.ModeDescription = GorgonVideoMode.Convert(Settings.VideoMode); D3DSettings.OutputHandle = Settings.Window.Handle; D3DSettings.SampleDescription = GorgonMultisampling.Convert(Settings.Multisampling); D3DSettings.SwapEffect = GorgonSwapChainSettings.Convert(Settings.SwapEffect); if ((Settings.Flags & SwapChainUsageFlags.RenderTarget) == SwapChainUsageFlags.RenderTarget) { D3DSettings.Usage = GI.Usage.RenderTargetOutput; } if ((Settings.Flags & SwapChainUsageFlags.AllowShaderView) == SwapChainUsageFlags.AllowShaderView) { D3DSettings.Usage |= GI.Usage.ShaderInput; } if ((Settings.Flags & SwapChainUsageFlags.AllowUnorderedAccessView) == SwapChainUsageFlags.AllowUnorderedAccessView) { D3DSettings.Usage |= GI.Usage.UnorderedAccess; } Gorgon.Log.Print("GorgonSwapChain '{0}': Creating D3D11 swap chain...", LoggingLevel.Simple, Name); GISwapChain = new GI.SwapChain(Graphics.GIFactory, Graphics.D3DDevice, D3DSettings) { DebugName = Name + " DXGISwapChain" }; // Due to an issue with winforms and DXGI, we have to manually handle transitions ourselves. Graphics.GIFactory.MakeWindowAssociation(Settings.Window.Handle, GI.WindowAssociationFlags.IgnoreAll); CreateResources(); if (!Settings.IsWindowed) { ModeStateUpdate(); } Settings.Window.Resize += Window_Resize; if (_parentForm == null) { return; } _parentForm.ResizeBegin += _parentForm_ResizeBegin; _parentForm.ResizeEnd += _parentForm_ResizeEnd; }
/// <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)); } }
#pragma warning disable 0618 /// <summary> /// Function to retrieve the list of outputs for the video device. /// </summary> /// <param name="adapter">Adapter containing the outputs.</param> /// <param name="D3DDevice">D3D device to find closest matching mode.</param> /// <param name="device">Device used to filter video modes that aren't supported.</param> /// <param name="outputCount">The number of outputs attached to the device.</param> /// <param name="noOutputDevice">TRUE if the device has no outputs, FALSE if it does.</param> private static void GetOutputs(GorgonVideoDevice device, D3D.Device D3DDevice, Adapter adapter, int outputCount, bool noOutputDevice) { var outputs = new List <GorgonVideoOutput>(outputCount); // We need to fake outputs. // Windows 8 does not support outputs on WARP devices and ref rasterizer devices. if ((noOutputDevice) || (SystemInformation.TerminalServerSession)) { var output = new GorgonVideoOutput(); Gorgon.Log.Print("Found output {0}.", LoggingLevel.Simple, output.Name); Gorgon.Log.Print("===================================================================", LoggingLevel.Verbose); Gorgon.Log.Print("Output bounds: ({0}x{1})-({2}x{3})", LoggingLevel.Verbose, output.OutputBounds.Left, output.OutputBounds.Top, output.OutputBounds.Right, output.OutputBounds.Bottom); Gorgon.Log.Print("Monitor handle: 0x{0}", LoggingLevel.Verbose, output.Handle.FormatHex()); Gorgon.Log.Print("Attached to desktop: {0}", LoggingLevel.Verbose, output.IsAttachedToDesktop); Gorgon.Log.Print("Monitor rotation: {0}\u00B0", LoggingLevel.Verbose, output.Rotation); Gorgon.Log.Print("===================================================================", LoggingLevel.Verbose); outputs.Add(output); // No video modes for these devices. output.VideoModes = new GorgonVideoMode[0]; device.Outputs = new GorgonNamedObjectReadOnlyCollection <GorgonVideoOutput>(false, outputs); Gorgon.Log.Print("Output {0} on device {1} has no video modes.", LoggingLevel.Verbose, output.Name, device.Name); return; } // Get outputs. for (int i = 0; i < outputCount; i++) { using (Output giOutput = adapter.GetOutput(i)) { var output = new GorgonVideoOutput(giOutput, device, i); ModeDescription findMode = GorgonVideoMode.Convert(new GorgonVideoMode(output.OutputBounds.Width, output.OutputBounds.Height, BufferFormat.R8G8B8A8_UIntNormal, 60, 1)); ModeDescription result; // Get the default (desktop) video mode. giOutput.GetClosestMatchingMode(D3DDevice, findMode, out result); output.DefaultVideoMode = GorgonVideoMode.Convert(result); GetVideoModes(output, D3DDevice, giOutput); Gorgon.Log.Print("Found output {0}.", LoggingLevel.Simple, output.Name); Gorgon.Log.Print("===================================================================", LoggingLevel.Verbose); Gorgon.Log.Print("Output bounds: ({0}x{1})-({2}x{3})", LoggingLevel.Verbose, output.OutputBounds.Left, output.OutputBounds.Top, output.OutputBounds.Right, output.OutputBounds.Bottom); Gorgon.Log.Print("Monitor handle: 0x{0}", LoggingLevel.Verbose, output.Handle.FormatHex()); Gorgon.Log.Print("Attached to desktop: {0}", LoggingLevel.Verbose, output.IsAttachedToDesktop); Gorgon.Log.Print("Monitor rotation: {0}\u00B0", LoggingLevel.Verbose, output.Rotation); Gorgon.Log.Print("===================================================================", LoggingLevel.Verbose); if (output.VideoModes.Count > 0) { outputs.Add(output); } else { Gorgon.Log.Print("Output {0} on device {1} has no video modes!", LoggingLevel.Verbose, output.Name, device.Name); } } } device.Outputs = new GorgonNamedObjectReadOnlyCollection <GorgonVideoOutput>(false, outputs); }