void game_FrameStart(object sender, CancelEventArgs e) { if (Direct3D9.Device == null) { e.Cancel = true; return; } //if (!game.IsActive || deviceLost) // #23568 2010.11.3 yyagi: separate conditions to support valiable sleep value when !IsActive. if (deviceLost) { Thread.Sleep(50); } else if (!game.IsActive && !this.CurrentSettings.EnableVSync) // #23568 2010.11.4 yyagi: Don't add sleep() while VSync is enabled. { Thread.Sleep(this.game.InactiveSleepTime.Milliseconds); } if (deviceLost) { Result result = Direct3D9.Device.TestCooperativeLevel(); if (result == ResultCode.DeviceLost) { e.Cancel = true; return; } // if we are windowed, check the adapter format to see if the user // changed the desktop format, causing a lost device if (IsWindowed) { DisplayMode displayMode = GraphicsDeviceManager.Direct3D9Object.GetAdapterDisplayMode(CurrentSettings.Direct3D9.AdapterOrdinal); if (CurrentSettings.Direct3D9.AdapterFormat != displayMode.Format) { DeviceSettings newSettings = CurrentSettings.Clone(); ChangeDevice(newSettings); e.Cancel = true; return; } } result = ResetDevice(); if (result.Failure) { e.Cancel = true; return; } } deviceLost = false; }
public void ChangeDevice(DeviceSettings settings, DeviceSettings minimumSettings) { if (settings == null) { throw new ArgumentNullException("settings"); } Enumeration9.MinimumSettings = minimumSettings; DeviceSettings validSettings = DeviceSettings.FindValidSettings(settings); var pp = validSettings.Direct3D9.PresentParameters; pp.DeviceWindowHandle = game.Window.Handle; validSettings.Direct3D9.PresentParameters = pp; CreateDevice(validSettings); }
public void ToggleFullScreen() { if (!EnsureDevice()) { throw new InvalidOperationException("No valid device."); } DeviceSettings newSettings = CurrentSettings.Clone(); newSettings.Windowed = !newSettings.Windowed; int width = newSettings.Windowed ? windowedWindowWidth : fullscreenWindowWidth; int height = newSettings.Windowed ? windowedWindowHeight : fullscreenWindowHeight; newSettings.BackBufferWidth = width; newSettings.BackBufferHeight = height; ChangeDevice(newSettings); }
void Window_UserResized(object sender, EventArgs e) { if (ignoreSizeChanges || !EnsureDevice() || (!IsWindowed)) { return; } DeviceSettings newSettings = CurrentSettings.Clone(); Rectangle rect = NativeMethods.GetClientRectangle(game.Window.Handle); if (rect.Width != newSettings.BackBufferWidth || rect.Height != newSettings.BackBufferHeight) { newSettings.BackBufferWidth = 0; newSettings.BackBufferHeight = 0; var pp = newSettings.Direct3D9.PresentParameters; pp.BackBufferWidth = GameWindowSize.Width; // #23510 2010.10.31 add yyagi: to avoid setting BackBufferSize=ClientSize pp.BackBufferHeight = GameWindowSize.Height; // #23510 2010.10.31 add yyagi: to avoid setting BackBufferSize=ClientSize newSettings.Direct3D9.PresentParameters = pp; CreateDevice(newSettings); } }
/// <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); }
void CreateDevice(DeviceSettings settings) { DeviceSettings oldSettings = CurrentSettings; CurrentSettings = settings; ignoreSizeChanges = true; bool keepCurrentWindowSize = false; if (settings.BackBufferWidth == 0 && settings.BackBufferHeight == 0) { keepCurrentWindowSize = true; } // handle the window state in Direct3D9 (it will be handled for us in DXGI) // check if we are going to windowed or fullscreen mode if (settings.Windowed) { if (oldSettings != null && !oldSettings.Windowed) { NativeMethods.SetWindowLong(game.Window.Handle, WindowConstants.GWL_STYLE, (uint)windowedStyle); } } else { if (oldSettings == null || oldSettings.Windowed) { savedTopmost = game.Window.TopMost; long style = NativeMethods.GetWindowLong(game.Window.Handle, WindowConstants.GWL_STYLE); style &= ~WindowConstants.WS_MAXIMIZE & ~WindowConstants.WS_MINIMIZE; windowedStyle = style; windowedPlacement = new WINDOWPLACEMENT(); windowedPlacement.length = WINDOWPLACEMENT.Length; NativeMethods.GetWindowPlacement(game.Window.Handle, ref windowedPlacement); } // hide the window until we are done messing with it game.Window.Hide(); NativeMethods.SetWindowLong(game.Window.Handle, WindowConstants.GWL_STYLE, (uint)(WindowConstants.WS_POPUP | WindowConstants.WS_SYSMENU)); WINDOWPLACEMENT placement = new WINDOWPLACEMENT(); placement.length = WINDOWPLACEMENT.Length; NativeMethods.GetWindowPlacement(game.Window.Handle, ref placement); // check if we are in the middle of a restore if ((placement.flags & WindowConstants.WPF_RESTORETOMAXIMIZED) != 0) { // update the flags to avoid sizing issues placement.flags &= ~WindowConstants.WPF_RESTORETOMAXIMIZED; placement.showCmd = WindowConstants.SW_RESTORE; NativeMethods.SetWindowPlacement(game.Window.Handle, ref placement); } } if (settings.Windowed) { if (oldSettings != null && !oldSettings.Windowed) { fullscreenWindowWidth = oldSettings.BackBufferWidth; fullscreenWindowHeight = oldSettings.BackBufferHeight; } } else { if (oldSettings != null && oldSettings.Windowed) { windowedWindowWidth = oldSettings.BackBufferWidth; windowedWindowHeight = oldSettings.BackBufferHeight; } } // check if the device can be reset, or if we need to completely recreate it Result result = ResultCode.Success; bool canReset = CanDeviceBeReset(oldSettings, settings); if (canReset) { result = ResetDevice(); } if (result == ResultCode.DeviceLost) { deviceLost = true; } else if (!canReset || result.Failure) { if (oldSettings != null) { ReleaseDevice(); } InitializeDevice(); } UpdateDeviceInformation(); // check if we changed from fullscreen to windowed mode if (oldSettings != null && !oldSettings.Windowed && settings.Windowed) { NativeMethods.SetWindowPlacement(game.Window.Handle, ref windowedPlacement); game.Window.TopMost = savedTopmost; } // check if we need to resize if (settings.Windowed && !keepCurrentWindowSize) { int width; int height; if (NativeMethods.IsIconic(game.Window.Handle)) { WINDOWPLACEMENT placement = new WINDOWPLACEMENT(); placement.length = WINDOWPLACEMENT.Length; NativeMethods.GetWindowPlacement(game.Window.Handle, ref placement); // check if we are being restored if ((placement.flags & WindowConstants.WPF_RESTORETOMAXIMIZED) != 0 && placement.showCmd == WindowConstants.SW_SHOWMINIMIZED) { NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_RESTORE); Rectangle rect = NativeMethods.GetClientRectangle(game.Window.Handle); width = rect.Width; height = rect.Height; NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_MINIMIZE); } else { NativeRectangle frame = new NativeRectangle(); NativeMethods.AdjustWindowRect(ref frame, (uint)windowedStyle, false); int frameWidth = frame.right - frame.left; int frameHeight = frame.bottom - frame.top; width = placement.rcNormalPosition.right - placement.rcNormalPosition.left - frameWidth; height = placement.rcNormalPosition.bottom - placement.rcNormalPosition.top - frameHeight; } } else { Rectangle rect = NativeMethods.GetClientRectangle(game.Window.Handle); width = rect.Width; height = rect.Height; } // check if we have a different desired size if (width != settings.BackBufferWidth || height != settings.BackBufferHeight) { if (NativeMethods.IsIconic(game.Window.Handle)) { NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_RESTORE); } if (NativeMethods.IsZoomed(game.Window.Handle)) { NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_RESTORE); } NativeRectangle rect = new NativeRectangle(); rect.right = settings.BackBufferWidth; rect.bottom = settings.BackBufferHeight; NativeMethods.AdjustWindowRect(ref rect, NativeMethods.GetWindowLong(game.Window.Handle, WindowConstants.GWL_STYLE), false); NativeMethods.SetWindowPos(game.Window.Handle, IntPtr.Zero, 0, 0, rect.right - rect.left, rect.bottom - rect.top, WindowConstants.SWP_NOZORDER | WindowConstants.SWP_NOMOVE); Rectangle r = NativeMethods.GetClientRectangle(game.Window.Handle); int clientWidth = r.Width; int clientHeight = r.Height; // check if the size was modified by Windows if (clientWidth != settings.BackBufferWidth || clientHeight != settings.BackBufferHeight) { DeviceSettings newSettings = CurrentSettings.Clone(); newSettings.BackBufferWidth = 0; newSettings.BackBufferHeight = 0; if (newSettings.Direct3D9 != null) { var pp = newSettings.Direct3D9.PresentParameters; pp.BackBufferWidth = GameWindowSize.Width; // #23510 2010.10.31 add yyagi: to avoid setting BackBufferSize=ClientSize pp.BackBufferHeight = GameWindowSize.Height; // #23510 2010.10.31 add yyagi: to avoid setting BackBufferSize=ClientSize newSettings.Direct3D9.PresentParameters = pp; } CreateDevice(newSettings); } } } // if the window is still hidden, make sure it is shown if (!game.Window.Visible) { NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_SHOW); } // set the execution state of the thread if (!IsWindowed) { NativeMethods.SetThreadExecutionState(WindowConstants.ES_DISPLAY_REQUIRED | WindowConstants.ES_CONTINUOUS); } else { NativeMethods.SetThreadExecutionState(WindowConstants.ES_CONTINUOUS); } ignoreSizeChanges = false; }
public void ChangeDevice(DeviceSettings settings) { ChangeDevice(settings, null); }