public Direct3D9Settings Clone()
        {
            Direct3D9Settings clone = new Direct3D9Settings();

            clone.AdapterFormat     = AdapterFormat;
            clone.AdapterOrdinal    = AdapterOrdinal;
            clone.CreationFlags     = CreationFlags;
            clone.DeviceType        = DeviceType;
            clone.PresentParameters = PresentParameters;

            return(clone);
        }
        static DisplayMode FindValidResolution(SettingsCombo9 combo, Direct3D9Settings input)
        {
            DisplayMode bestMode = new DisplayMode();

            if (combo.Windowed)
            {
                bestMode.Width  = input.PresentParameters.BackBufferWidth;
                bestMode.Height = input.PresentParameters.BackBufferHeight;
                return(bestMode);
            }

            int bestRanking = 100000;
            int ranking;

            foreach (DisplayMode mode in combo.AdapterInfo.DisplayModes)
            {
                if (mode.Format != combo.AdapterFormat)
                {
                    continue;
                }

                ranking = Math.Abs(mode.Width - input.PresentParameters.BackBufferWidth) +
                          Math.Abs(mode.Height - input.PresentParameters.BackBufferHeight);

                if (ranking < bestRanking)
                {
                    bestMode    = mode;
                    bestRanking = ranking;

                    if (bestRanking == 0)
                    {
                        break;
                    }
                }
            }

            if (bestMode.Width == 0)
            {
                bestMode.Width  = input.PresentParameters.BackBufferWidth;
                bestMode.Height = input.PresentParameters.BackBufferHeight;
            }

            return(bestMode);
        }
        /// <summary>
        /// Finds valid device settings based upon the desired settings.
        /// </summary>
        /// <param name="settings">The desired settings.</param>
        /// <returns>The best valid device settings matching the input settings.</returns>
        public static DeviceSettings FindValidSettings(DeviceSettings settings)
        {
            try
            {
                GraphicsDeviceManager.EnsureD3D9();
            }
            catch (Exception e)
            {
                throw new NoCompatibleDevicesException("Could not initialize Direct3D9.", e);
            }

            if (!Enumeration9.HasEnumerated)
            {
                Enumeration9.Enumerate();
            }

            DeviceSettings    newSettings = settings.Clone();
            Direct3D9Settings d3d9        = FindValidD3D9Settings(settings);

            newSettings.Direct3D9 = d3d9;
            return(newSettings);
        }
        static Direct3D9Settings FindValidD3D9Settings(DeviceSettings settings)
        {
            Direct3D9Settings optimal = Direct3D9Settings.BuildOptimalSettings(settings);

            SettingsCombo9 bestCombo   = null;
            float          bestRanking = -1.0f;

            foreach (AdapterInfo9 adapterInfo in Enumeration9.Adapters)
            {
                DisplayMode desktopMode = GraphicsDeviceManager.Direct3D9Object.GetAdapterDisplayMode(adapterInfo.AdapterOrdinal);
                foreach (DeviceInfo9 deviceInfo in adapterInfo.Devices)
                {
                    foreach (SettingsCombo9 combo in deviceInfo.DeviceSettings)
                    {
                        if (combo.Windowed && combo.AdapterFormat != desktopMode.Format)
                        {
                            continue;
                        }

                        float ranking = Direct3D9Settings.RankSettingsCombo(combo, optimal, desktopMode);
                        if (ranking > bestRanking)
                        {
                            bestCombo   = combo;
                            bestRanking = ranking;
                        }
                    }
                }
            }

            if (bestCombo == null)
            {
                throw new NoCompatibleDevicesException("No compatible Direct3D9 devices found.");
            }

            return(Direct3D9Settings.BuildValidSettings(bestCombo, optimal));
        }
        public static Direct3D9Settings BuildOptimalSettings(DeviceSettings settings)
        {
            DisplayMode       desktopMode = GraphicsDeviceManager.Direct3D9Object.GetAdapterDisplayMode(0);
            Direct3D9Settings optimal     = new Direct3D9Settings();
            var pp = optimal.PresentParameters;

            optimal.AdapterOrdinal       = settings.AdapterOrdinal;
            optimal.DeviceType           = settings.DeviceType;
            pp.Windowed                  = settings.Windowed;
            pp.BackBufferCount           = settings.BackBufferCount;
            pp.MultiSampleType           = settings.MultisampleType;
            pp.MultiSampleQuality        = settings.MultisampleQuality;
            pp.FullScreenRefreshRateInHz = settings.RefreshRate;

            if (settings.Multithreaded)
            {
                optimal.CreationFlags |= CreateFlags.Multithreaded;
            }

            if (optimal.PresentParameters.Windowed || ConversionMethods.GetColorBits(desktopMode.Format) >= 8)
            {
                optimal.AdapterFormat = desktopMode.Format;
            }
            else
            {
                optimal.AdapterFormat = Format.X8R8G8B8;
            }

            if (settings.BackBufferWidth == 0 || settings.BackBufferHeight == 0)
            {
                if (optimal.PresentParameters.Windowed)
                {
                    pp.BackBufferWidth  = 640;
                    pp.BackBufferHeight = 480;
                }
                else
                {
                    pp.BackBufferWidth  = desktopMode.Width;
                    pp.BackBufferHeight = desktopMode.Height;
                }
            }
            else
            {
                pp.BackBufferWidth  = settings.BackBufferWidth;
                pp.BackBufferHeight = settings.BackBufferHeight;
            }

            if (settings.BackBufferFormat == Format.Unknown)
            {
                pp.BackBufferFormat = optimal.AdapterFormat;
            }
            else
            {
                pp.BackBufferFormat = settings.BackBufferFormat;
            }

            if (settings.DepthStencilFormat == Format.Unknown)
            {
                if (ConversionMethods.GetColorBits(optimal.PresentParameters.BackBufferFormat) >= 8)
                {
                    pp.AutoDepthStencilFormat = Format.D32;
                }
                else
                {
                    pp.AutoDepthStencilFormat = Format.D16;
                }
            }
            else
            {
                pp.AutoDepthStencilFormat = settings.DepthStencilFormat;
            }

            if (!settings.EnableVSync)
            {
                pp.PresentationInterval = PresentInterval.Immediate;
            }

            optimal.PresentParameters = pp;
            return(optimal);
        }
        public static Direct3D9Settings BuildValidSettings(SettingsCombo9 combo, Direct3D9Settings input)
        {
            Direct3D9Settings settings = new Direct3D9Settings();
            var pp = settings.PresentParameters;

            settings.AdapterOrdinal = combo.AdapterOrdinal;
            settings.DeviceType     = combo.DeviceType;
            settings.AdapterFormat  = combo.AdapterFormat;
            pp.Windowed             = combo.Windowed;
            pp.BackBufferFormat     = combo.BackBufferFormat;
            pp.SwapEffect           = input.PresentParameters.SwapEffect;
            pp.PresentFlags         = input.PresentParameters.PresentFlags | PresentFlags.DiscardDepthStencil;

            settings.CreationFlags = input.CreationFlags;
            if ((combo.DeviceInfo.Capabilities.DeviceCaps & DeviceCaps.HWTransformAndLight) == 0 &&
                ((settings.CreationFlags & CreateFlags.HardwareVertexProcessing) != 0 ||
                 (settings.CreationFlags & CreateFlags.MixedVertexProcessing) != 0))
            {
                settings.CreationFlags &= ~CreateFlags.HardwareVertexProcessing;
                settings.CreationFlags &= ~CreateFlags.MixedVertexProcessing;
                settings.CreationFlags |= CreateFlags.SoftwareVertexProcessing;
            }

            if ((settings.CreationFlags & CreateFlags.HardwareVertexProcessing) == 0 &&
                (settings.CreationFlags & CreateFlags.MixedVertexProcessing) == 0 &&
                (settings.CreationFlags & CreateFlags.SoftwareVertexProcessing) == 0)
            {
                if ((combo.DeviceInfo.Capabilities.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0)
                {
                    settings.CreationFlags |= CreateFlags.HardwareVertexProcessing;
                }
                else
                {
                    settings.CreationFlags |= CreateFlags.SoftwareVertexProcessing;
                }
            }

            DisplayMode bestDisplayMode = FindValidResolution(combo, input);

            pp.BackBufferWidth  = bestDisplayMode.Width;
            pp.BackBufferHeight = bestDisplayMode.Height;

            pp.BackBufferCount = input.PresentParameters.BackBufferCount;
            if (pp.BackBufferCount > 3)
            {
                pp.BackBufferCount = 3;
            }
            if (pp.BackBufferCount < 1)
            {
                pp.BackBufferCount = 1;
            }

            if (input.PresentParameters.SwapEffect != SwapEffect.Discard)
            {
                pp.MultiSampleType    = MultisampleType.None;
                pp.MultiSampleQuality = 0;
            }
            else
            {
                MultisampleType bestType    = MultisampleType.None;
                int             bestQuality = 0;

                for (int i = 0; i < combo.MultisampleTypes.Count; i++)
                {
                    MultisampleType type    = combo.MultisampleTypes[i];
                    int             quality = combo.MultisampleQualities[i];

                    if (Math.Abs(type - input.PresentParameters.MultiSampleType) < Math.Abs(bestType - input.PresentParameters.MultiSampleType))
                    {
                        bestType    = type;
                        bestQuality = Math.Min(quality - 1, input.PresentParameters.MultiSampleQuality);
                    }
                }

                pp.MultiSampleType    = bestType;
                pp.MultiSampleQuality = bestQuality;
            }

            List <int> rankings             = new List <int>();
            int        inputDepthBitDepth   = ConversionMethods.GetDepthBits(input.PresentParameters.AutoDepthStencilFormat);
            int        inputStencilBitDepth = ConversionMethods.GetStencilBits(input.PresentParameters.AutoDepthStencilFormat);

            foreach (Format format in combo.DepthStencilFormats)
            {
                int currentBitDepth     = ConversionMethods.GetDepthBits(format);
                int currentStencilDepth = ConversionMethods.GetStencilBits(format);

                int ranking = Math.Abs(currentBitDepth - inputDepthBitDepth);
                ranking += Math.Abs(currentStencilDepth - inputStencilBitDepth);
                rankings.Add(ranking);
            }

            int bestRanking = int.MaxValue;

            foreach (int ranking in rankings)
            {
                if (ranking < bestRanking)
                {
                    bestRanking = ranking;
                }
            }
            int bestIndex = rankings.IndexOf(bestRanking);

            if (bestIndex >= 0)
            {
                pp.AutoDepthStencilFormat = combo.DepthStencilFormats[bestIndex];
                pp.EnableAutoDepthStencil = true;
            }
            else
            {
                pp.AutoDepthStencilFormat = Format.Unknown;
                pp.EnableAutoDepthStencil = false;
            }

            if (combo.Windowed)
            {
                pp.FullScreenRefreshRateInHz = 0;
            }
            else
            {
                int match = input.PresentParameters.FullScreenRefreshRateInHz;
                bestDisplayMode.RefreshRate = 0;
                if (match != 0)
                {
                    bestRanking = 100000;
                    foreach (DisplayMode displayMode in combo.AdapterInfo.DisplayModes)
                    {
                        if (displayMode.Format != combo.AdapterFormat ||
                            displayMode.Width != bestDisplayMode.Width ||
                            displayMode.Height != bestDisplayMode.Height)
                        {
                            continue;
                        }

                        int ranking = Math.Abs(displayMode.RefreshRate - match);

                        if (ranking < bestRanking)
                        {
                            bestDisplayMode.RefreshRate = displayMode.RefreshRate;
                            bestRanking = ranking;

                            if (bestRanking == 0)
                            {
                                break;
                            }
                        }
                    }
                }

                pp.FullScreenRefreshRateInHz = bestDisplayMode.RefreshRate;
            }

            if (combo.PresentIntervals.Contains(input.PresentParameters.PresentationInterval))
            {
                pp.PresentationInterval = input.PresentParameters.PresentationInterval;
            }
            else
            {
                pp.PresentationInterval = PresentInterval.Default;
            }

            settings.PresentParameters = pp;
            return(settings);
        }
        public static float RankSettingsCombo(SettingsCombo9 combo, Direct3D9Settings optimal, DisplayMode desktopMode)
        {
            float ranking = 0.0f;

            if (combo.AdapterOrdinal == optimal.AdapterOrdinal)
            {
                ranking += 1000.0f;
            }

            if (combo.DeviceType == optimal.DeviceType)
            {
                ranking += 100.0f;
            }

            if (combo.DeviceType == DeviceType.Hardware)
            {
                ranking += 0.1f;
            }

            if (combo.Windowed == optimal.PresentParameters.Windowed)
            {
                ranking += 10.0f;
            }

            if (combo.AdapterFormat == optimal.AdapterFormat)
            {
                ranking += 1.0f;
            }
            else
            {
                int bitDepthDelta = Math.Abs(ConversionMethods.GetColorBits(combo.AdapterFormat) -
                                             ConversionMethods.GetColorBits(optimal.AdapterFormat));
                float scale = Math.Max(0.9f - bitDepthDelta * 0.2f, 0.0f);
                ranking += scale;
            }

            if (!combo.Windowed)
            {
                bool match;
                if (ConversionMethods.GetColorBits(desktopMode.Format) >= 8)
                {
                    match = (combo.AdapterFormat == desktopMode.Format);
                }
                else
                {
                    match = (combo.AdapterFormat == Format.X8R8G8B8);
                }

                if (match)
                {
                    ranking += 0.1f;
                }
            }

            if ((optimal.CreationFlags & CreateFlags.HardwareVertexProcessing) != 0 &&
                (optimal.CreationFlags & CreateFlags.MixedVertexProcessing) != 0)
            {
                if ((combo.DeviceInfo.Capabilities.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0)
                {
                    ranking += 1.0f;
                }
            }

            if ((combo.DeviceInfo.Capabilities.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0)
            {
                ranking += 0.1f;
            }

            foreach (DisplayMode displayMode in combo.AdapterInfo.DisplayModes)
            {
                if (displayMode.Format == combo.AdapterFormat &&
                    displayMode.Width == optimal.PresentParameters.BackBufferWidth &&
                    displayMode.Height == optimal.PresentParameters.BackBufferHeight)
                {
                    ranking += 1.0f;
                    break;
                }
            }

            if (combo.BackBufferFormat == optimal.PresentParameters.BackBufferFormat)
            {
                ranking += 1.0f;
            }
            else
            {
                int bitDepthDelta = Math.Abs(ConversionMethods.GetColorBits(combo.BackBufferFormat) -
                                             ConversionMethods.GetColorBits(optimal.PresentParameters.BackBufferFormat));
                float scale = Math.Max(0.9f - bitDepthDelta * 0.2f, 0.0f);
                ranking += scale;
            }

            if (combo.BackBufferFormat == combo.AdapterFormat)
            {
                ranking += 0.1f;
            }

            for (int i = 0; i < combo.MultisampleTypes.Count; i++)
            {
                MultisampleType type    = combo.MultisampleTypes[i];
                int             quality = combo.MultisampleQualities[i];

                if (type == optimal.PresentParameters.MultiSampleType && quality == optimal.PresentParameters.MultiSampleQuality)
                {
                    ranking += 1.0f;
                    break;
                }
            }

            if (combo.DepthStencilFormats.Contains(optimal.PresentParameters.AutoDepthStencilFormat))
            {
                ranking += 1.0f;
            }

            foreach (DisplayMode displayMode in combo.AdapterInfo.DisplayModes)
            {
                if (displayMode.Format == combo.AdapterFormat &&
                    displayMode.RefreshRate == optimal.PresentParameters.FullScreenRefreshRateInHz)
                {
                    ranking += 1.0f;
                    break;
                }
            }

            if (combo.PresentIntervals.Contains(optimal.PresentParameters.PresentationInterval))
            {
                ranking += 1.0f;
            }

            return(ranking);
        }