using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Rectangle = System.Drawing.Rectangle; // ************************************************************************* // // Disable 'missing xml comment' warning for this file since it has been // generated by .NET Reflector and I'm not going to comment this all // just so I have to start from scratch again when XNA gets updated #pragma warning disable 1591 // ************************************************************************* // namespace Nuclex { /// /// Handles the configuration and management of the graphics device. /// public class GraphicsDeviceManager : IGraphicsDeviceService, IDisposable, IGraphicsDeviceManager { // Fields private bool allowMultiSampling; private SurfaceFormat backBufferFormat = SurfaceFormat.Color; private int backBufferHeight = DefaultBackBufferHeight; private int backBufferWidth = DefaultBackBufferWidth; private bool beginDrawOk; public static readonly int DefaultBackBufferHeight = 600; public static readonly int DefaultBackBufferWidth = 800; private DepthFormat depthStencilFormat = DepthFormat.Depth24; private GraphicsDevice device; private static readonly TimeSpan deviceLostSleepTime = TimeSpan.FromMilliseconds(50); private GameControl game; private bool inDeviceTransition; private bool isDeviceDirty; private bool isFullScreen; private bool isReallyFullScreen; private ShaderProfile minimumPixelShaderProfile; private ShaderProfile minimumVertexShaderProfile = ShaderProfile.VS_1_1; private static MultiSampleType[] multiSampleTypes; private int resizedBackBufferHeight; private int resizedBackBufferWidth; private bool synchronizeWithVerticalRetrace = true; private bool useResizedBackBuffer; /// Specifies the set of adapter formats supported by the GraphicsDeviceManager. public static readonly SurfaceFormat[] ValidAdapterFormats = new SurfaceFormat[] { SurfaceFormat.Bgr32, SurfaceFormat.Bgr555, SurfaceFormat.Bgr565, SurfaceFormat.Bgra1010102 }; /// Specifies the set of back-buffer formats supported by the GraphicsDeviceManager. /// public static readonly SurfaceFormat[] ValidBackBufferFormats = new SurfaceFormat[] { SurfaceFormat.Bgr565, SurfaceFormat.Bgr555, SurfaceFormat.Bgra5551, SurfaceFormat.Bgr32, SurfaceFormat.Color, SurfaceFormat.Bgra1010102 }; /// Specifies the set of valid device types supported by the GraphicsDeviceManager. public static readonly DeviceType[] ValidDeviceTypes = new DeviceType[] { DeviceType.Hardware }; /// Raised when a new graphics device is created. public event EventHandler DeviceCreated; /// Raised when the GraphicsDeviceManager is being disposed. public event EventHandler DeviceDisposing; /// Raised when the GraphicsDeviceManager is reset. public event EventHandler DeviceReset; /// Raised when the GraphicsDeviceManager is about to be reset. public event EventHandler DeviceResetting; /// Raised when the GraphicsDeviceManager is disposed. public event EventHandler Disposed; /// /// Raised when the GraphicsDeviceManager is changing the Graphics.GraphicsDevice settings (during reset or recreation of the Graphics.GraphicsDevice). /// public event EventHandler PreparingDeviceSettings; // Methods static GraphicsDeviceManager() { MultiSampleType[] typeArray2 = new MultiSampleType[0x11]; typeArray2[0] = MultiSampleType.NonMaskable; typeArray2[1] = MultiSampleType.SixteenSamples; typeArray2[2] = MultiSampleType.FifteenSamples; typeArray2[3] = MultiSampleType.FourteenSamples; typeArray2[4] = MultiSampleType.ThirteenSamples; typeArray2[5] = MultiSampleType.TwelveSamples; typeArray2[6] = MultiSampleType.ElevenSamples; typeArray2[7] = MultiSampleType.TenSamples; typeArray2[8] = MultiSampleType.NineSamples; typeArray2[9] = MultiSampleType.EightSamples; typeArray2[10] = MultiSampleType.SevenSamples; typeArray2[11] = MultiSampleType.SixSamples; typeArray2[12] = MultiSampleType.FiveSamples; typeArray2[13] = MultiSampleType.FourSamples; typeArray2[14] = MultiSampleType.ThreeSamples; typeArray2[15] = MultiSampleType.TwoSamples; multiSampleTypes = typeArray2; } /// Creates a new GraphicsDeviceManager and registers it to handle the configuration and management of the graphics device for the specified Game. /// Game the GraphicsDeviceManager should be associated with. public GraphicsDeviceManager(GameControl game) { if (game == null) { throw new ArgumentNullException("Resources.GameCannotBeNull"); } this.game = game; if (game.Services.GetService(typeof(IGraphicsDeviceManager)) != null) { throw new ArgumentException("Resources.GraphicsDeviceManagerAlreadyPresent"); } game.Services.AddService(typeof(IGraphicsDeviceManager), this); game.Services.AddService(typeof(IGraphicsDeviceService), this); game.ClientSizeChanged += new EventHandler(this.GameWindowClientSizeChanged); // TODO: Reenable MultiMon support //game.ScreenDeviceNameChanged += new EventHandler(this.GameWindowScreenDeviceNameChanged); } private void AddDevices(bool anySuitableDevice, List foundDevices) { IntPtr handle = this.game.Handle; foreach (GraphicsAdapter adapter in GraphicsAdapter.Adapters) { if (!anySuitableDevice && !this.IsWindowOnAdapter(handle, adapter)) { continue; } foreach (DeviceType type in ValidDeviceTypes) { try { GraphicsDeviceCapabilities capabilities = adapter.GetCapabilities(type); if ((capabilities.DeviceCapabilities.IsDirect3D9Driver && (capabilities.MaxPixelShaderProfile >= this.MinimumPixelShaderProfile)) && (capabilities.MaxVertexShaderProfile >= this.MinimumVertexShaderProfile)) { GraphicsDeviceInformation baseDeviceInfo = new GraphicsDeviceInformation(); baseDeviceInfo.Adapter = adapter; baseDeviceInfo.DeviceType = type; baseDeviceInfo.PresentationParameters.DeviceWindowHandle = IntPtr.Zero; baseDeviceInfo.PresentationParameters.EnableAutoDepthStencil = true; baseDeviceInfo.PresentationParameters.BackBufferCount = 1; baseDeviceInfo.PresentationParameters.PresentOptions = PresentOptions.None; baseDeviceInfo.PresentationParameters.SwapEffect = SwapEffect.Discard; baseDeviceInfo.PresentationParameters.FullScreenRefreshRateInHz = 0; baseDeviceInfo.PresentationParameters.MultiSampleQuality = 0; baseDeviceInfo.PresentationParameters.MultiSampleType = MultiSampleType.None; baseDeviceInfo.PresentationParameters.IsFullScreen = this.IsFullScreen; baseDeviceInfo.PresentationParameters.PresentationInterval = this.SynchronizeWithVerticalRetrace ? PresentInterval.One : PresentInterval.Immediate; for (int i = 0; i < ValidAdapterFormats.Length; i++) { this.AddDevices(adapter, type, adapter.CurrentDisplayMode, baseDeviceInfo, foundDevices); if (this.isFullScreen) { foreach (DisplayMode mode in adapter.SupportedDisplayModes[ValidAdapterFormats[i]]) { if ((mode.Width >= 640) && (mode.Height >= 480)) { this.AddDevices(adapter, type, mode, baseDeviceInfo, foundDevices); } } } } } } catch (DeviceNotSupportedException) { } } } } private void AddDevices(GraphicsAdapter adapter, DeviceType deviceType, DisplayMode mode, GraphicsDeviceInformation baseDeviceInfo, List foundDevices) { for (int i = 0; i < ValidBackBufferFormats.Length; i++) { SurfaceFormat backBufferFormat = ValidBackBufferFormats[i]; if (adapter.CheckDeviceType(deviceType, mode.Format, backBufferFormat, this.IsFullScreen)) { GraphicsDeviceInformation item = baseDeviceInfo.Clone(); if (this.IsFullScreen) { item.PresentationParameters.BackBufferWidth = mode.Width; item.PresentationParameters.BackBufferHeight = mode.Height; item.PresentationParameters.FullScreenRefreshRateInHz = mode.RefreshRate; } else if (this.useResizedBackBuffer) { item.PresentationParameters.BackBufferWidth = this.resizedBackBufferWidth; item.PresentationParameters.BackBufferHeight = this.resizedBackBufferHeight; } else { item.PresentationParameters.BackBufferWidth = this.PreferredBackBufferWidth; item.PresentationParameters.BackBufferHeight = this.PreferredBackBufferHeight; } item.PresentationParameters.BackBufferFormat = backBufferFormat; item.PresentationParameters.AutoDepthStencilFormat = this.PreferredDepthStencilFormat; if (this.PreferMultiSampling) { for (int j = 0; j < multiSampleTypes.Length; j++) { int qualityLevels = 0; MultiSampleType sampleType = multiSampleTypes[j]; if (adapter.CheckDeviceMultiSampleType(deviceType, backBufferFormat, this.IsFullScreen, sampleType, out qualityLevels)) { GraphicsDeviceInformation information2 = item.Clone(); information2.PresentationParameters.MultiSampleType = sampleType; if (qualityLevels > 0) { information2.PresentationParameters.MultiSampleQuality = qualityLevels - 1; } if (!foundDevices.Contains(information2)) { foundDevices.Add(information2); } break; } } } else if (!foundDevices.Contains(item)) { foundDevices.Add(item); } } } } /// Applies any changes to device-related properties, changing the graphics device as necessary. /// public void ApplyChanges() { if ((this.device == null) || this.isDeviceDirty) { this.ChangeDevice(false); } } protected virtual bool CanResetDevice(GraphicsDeviceInformation newDeviceInfo) { if (this.device.CreationParameters.DeviceType != newDeviceInfo.DeviceType) { return false; } return true; } private void ChangeDevice(bool forceCreate) { if (this.game == null) { throw new InvalidOperationException("Resources.GraphicsComponentNotAttachedToGame"); } this.CheckForAvailableSupportedHardware(); this.inDeviceTransition = true; // TODO: Reenable MultiMon support string screenDeviceName = string.Empty; //this.game.ScreenDeviceName; int clientWidth = this.game.ClientRectangle.Width; int clientHeight = this.game.ClientRectangle.Height; bool flag = false; try { GraphicsDeviceInformation graphicsDeviceInformation = this.FindBestDevice(forceCreate); // TODO: Reenable MultiMon support //this.game.BeginScreenDeviceChange(graphicsDeviceInformation.PresentationParameters.IsFullScreen); flag = true; bool flag2 = true; if (!forceCreate && (this.device != null)) { this.OnPreparingDeviceSettings(this, new PreparingDeviceSettingsEventArgs(graphicsDeviceInformation)); if (this.CanResetDevice(graphicsDeviceInformation)) { try { GraphicsDeviceInformation information2 = graphicsDeviceInformation.Clone(); this.MassagePresentParameters(graphicsDeviceInformation.PresentationParameters); this.ValidateGraphicsDeviceInformation(graphicsDeviceInformation); this.device.Reset(information2.PresentationParameters); flag2 = false; } catch { } } } if (flag2) { this.CreateDevice(graphicsDeviceInformation); } PresentationParameters presentationParameters = this.device.PresentationParameters; screenDeviceName = this.device.CreationParameters.Adapter.DeviceName; this.isReallyFullScreen = presentationParameters.IsFullScreen; if (presentationParameters.BackBufferWidth != 0) { clientWidth = presentationParameters.BackBufferWidth; } if (presentationParameters.BackBufferHeight != 0) { clientHeight = presentationParameters.BackBufferHeight; } this.isDeviceDirty = false; } finally { if (flag) { // TODO: Reenable MultiMon support //this.game.EndScreenDeviceChange(screenDeviceName, clientWidth, clientHeight); } this.inDeviceTransition = false; } } private void CheckForAvailableSupportedHardware() { bool flag = false; bool flag2 = false; foreach (GraphicsAdapter adapter in GraphicsAdapter.Adapters) { if (adapter.IsDeviceTypeAvailable(DeviceType.Hardware)) { flag = true; GraphicsDeviceCapabilities capabilities = adapter.GetCapabilities(DeviceType.Hardware); if (((capabilities.MaxPixelShaderProfile != ShaderProfile.Unknown) && (capabilities.MaxPixelShaderProfile >= ShaderProfile.PS_1_1)) && capabilities.DeviceCapabilities.IsDirect3D9Driver) { flag2 = true; break; } } } if (!flag) { if (GetSystemMetrics(0x1000) != 0) { throw new NoSuitableGraphicsDeviceException("Resources.NoDirect3DAccelerationRemoteDesktop"); } throw new NoSuitableGraphicsDeviceException("Resources.NoDirect3DAcceleration"); } if (!flag2) { throw new NoSuitableGraphicsDeviceException("Resources.NoPixelShader11OrDDI9Support"); } } private void CreateDevice(GraphicsDeviceInformation newInfo) { if (this.device != null) { this.device.Dispose(); this.device = null; } this.OnPreparingDeviceSettings(this, new PreparingDeviceSettingsEventArgs(newInfo)); this.MassagePresentParameters(newInfo.PresentationParameters); try { this.ValidateGraphicsDeviceInformation(newInfo); GraphicsDevice device = new GraphicsDevice(newInfo.Adapter, newInfo.DeviceType, this.game.Handle, newInfo.PresentationParameters); this.device = device; this.device.DeviceResetting += new EventHandler(this.HandleDeviceResetting); this.device.DeviceReset += new EventHandler(this.HandleDeviceReset); this.device.DeviceLost += new EventHandler(this.HandleDeviceLost); this.device.Disposing += new EventHandler(this.HandleDisposing); } catch (DeviceNotSupportedException exception) { throw new NoSuitableGraphicsDeviceException("Resources.Direct3DNotAvailable", exception); } catch (DriverInternalErrorException exception2) { throw new NoSuitableGraphicsDeviceException("Resources.Direct3DInternalDriverError", exception2); } catch (ArgumentException exception3) { throw new NoSuitableGraphicsDeviceException("Resources.Direct3DInvalidCreateParameters", exception3); } catch (Exception exception4) { throw new NoSuitableGraphicsDeviceException("Resources.Direct3DCreateError", exception4); } this.OnDeviceCreated(this, EventArgs.Empty); } /// /// Releases the unmanaged resources used by the GraphicsDeviceManager and optionally releases the managed resources. /// /// true to release both automatic and manual resources; false to release only manual resources. protected virtual void Dispose(bool disposing) { if (disposing) { if (this.game != null) { if (this.game.Services.GetService(typeof(IGraphicsDeviceService)) == this) { this.game.Services.RemoveService(typeof(IGraphicsDeviceService)); } this.game.ClientSizeChanged -= new EventHandler(this.GameWindowClientSizeChanged); // TODO: Reenable MultiMon support //this.game.ScreenDeviceNameChanged -= new EventHandler(this.GameWindowScreenDeviceNameChanged); } if (this.device != null) { this.device.Dispose(); this.device = null; } if (this.Disposed != null) { this.Disposed(this, EventArgs.Empty); } } } private bool EnsureDevice() { if (this.device == null) { return false; } if (this.isReallyFullScreen && !this.game.IsActive) { return false; } switch (this.device.GraphicsDeviceStatus) { case GraphicsDeviceStatus.Lost: Thread.Sleep((int)deviceLostSleepTime.TotalMilliseconds); return false; case GraphicsDeviceStatus.NotReset: Thread.Sleep((int)deviceLostSleepTime.TotalMilliseconds); try { this.ChangeDevice(false); } catch (DeviceLostException) { return false; } catch { this.ChangeDevice(true); } break; } return true; } /// Finds the best device configuration that is compatible with the current device preferences. /// true if the GraphicsDeviceManager.FindBestDevice can select devices from any available adapter; false if only the current adapter should be considered. /// The best device configuration found. protected virtual GraphicsDeviceInformation FindBestDevice(bool anySuitableDevice) { return this.FindBestPlatformDevice(anySuitableDevice); } private GraphicsDeviceInformation FindBestPlatformDevice(bool anySuitableDevice) { List foundDevices = new List(); this.AddDevices(anySuitableDevice, foundDevices); if ((foundDevices.Count == 0) && this.PreferMultiSampling) { this.PreferMultiSampling = false; this.AddDevices(anySuitableDevice, foundDevices); } if (foundDevices.Count == 0) { throw new NoSuitableGraphicsDeviceException("Resources.NoCompatibleDevices"); } this.RankDevices(foundDevices); if (foundDevices.Count == 0) { throw new NoSuitableGraphicsDeviceException("Resources.NoCompatibleDevicesAfterRanking"); } return foundDevices[0]; } private void GameWindowClientSizeChanged(object sender, EventArgs e) { if (!this.inDeviceTransition && ((this.game.ClientRectangle.Height != 0) || (this.game.ClientRectangle.Width != 0))) { this.resizedBackBufferWidth = this.game.ClientRectangle.Width; this.resizedBackBufferHeight = this.game.ClientRectangle.Height; this.useResizedBackBuffer = true; this.ChangeDevice(false); } } private void GameWindowScreenDeviceNameChanged(object sender, EventArgs e) { if (!this.inDeviceTransition) { this.ChangeDevice(false); } } [DllImport("user32.dll")] private static extern int GetSystemMetrics(uint smIndex); private void HandleDeviceLost(object sender, EventArgs e) { } private void HandleDeviceReset(object sender, EventArgs e) { this.OnDeviceReset(this, EventArgs.Empty); } private void HandleDeviceResetting(object sender, EventArgs e) { this.OnDeviceResetting(this, EventArgs.Empty); } private void HandleDisposing(object sender, EventArgs e) { this.OnDeviceDisposing(this, EventArgs.Empty); } private bool IsWindowOnAdapter(IntPtr windowHandle, GraphicsAdapter adapter) { return (ScreenFromAdapter(adapter) == ScreenFromHandle(windowHandle)); } private void MassagePresentParameters(PresentationParameters pp) { bool flag = pp.BackBufferWidth == 0; bool flag2 = pp.BackBufferHeight == 0; if (!pp.IsFullScreen) { NativeMethods.RECT rect; IntPtr hWnd = pp.DeviceWindowHandle; if (hWnd == IntPtr.Zero) { if (this.game == null) { throw new InvalidOperationException("Resources.GraphicsComponentNotAttachedToGame"); } hWnd = this.game.Handle; } NativeMethods.GetClientRect(hWnd, out rect); if (flag && (rect.Right == 0)) { pp.BackBufferWidth = 1; } if (flag2 && (rect.Bottom == 0)) { pp.BackBufferHeight = 1; } } } bool IGraphicsDeviceManager.BeginDraw() { if (!this.EnsureDevice()) { return false; } this.beginDrawOk = true; return true; } void IGraphicsDeviceManager.CreateDevice() { this.ChangeDevice(true); } void IGraphicsDeviceManager.EndDraw() { if (this.beginDrawOk && (this.device != null)) { try { this.device.Present(); } catch (DeviceLostException) { } catch (DeviceNotResetException) { } catch (DriverInternalErrorException) { } } } /// Called when a device is created. Raises the GraphicsDeviceManager.DeviceCreated event. /// The GraphicsDeviceManager. /// Arguments for the GraphicsDeviceManager.DeviceCreated event. protected virtual void OnDeviceCreated(object sender, EventArgs args) { if (this.DeviceCreated != null) { this.DeviceCreated(sender, args); } } /// Called when a device is being disposed. Raises the GraphicsDeviceManager.DeviceDisposing event. /// The GraphicsDeviceManager. /// Arguments for the GraphicsDeviceManager.DeviceDisposing event. protected virtual void OnDeviceDisposing(object sender, EventArgs args) { if (this.DeviceDisposing != null) { this.DeviceDisposing(sender, args); } } /// Called when the device has been reset. Raises the GraphicsDeviceManager.DeviceReset event. /// The GraphicsDeviceManager. /// Arguments for the GraphicsDeviceManager.DeviceReset event. protected virtual void OnDeviceReset(object sender, EventArgs args) { if (this.DeviceReset != null) { this.DeviceReset(sender, args); } } /// /// Called when the device is about to be reset. Raises the GraphicsDeviceManager.DeviceResetting event. /// /// The GraphicsDeviceManager. /// Arguments for the GraphicsDeviceManager.DeviceResetting event. protected virtual void OnDeviceResetting(object sender, EventArgs args) { if (this.DeviceResetting != null) { this.DeviceResetting(sender, args); } } /// /// Called when the GraphicsDeviceManager is changing the Graphics.GraphicsDevice settings (during reset or recreation of the Graphics.GraphicsDevice). /// Raises the GraphicsDeviceManager.PreparingDeviceSettings event. /// /// The GraphicsDeviceManager. /// The graphics device information to modify. protected virtual void OnPreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs args) { if (this.PreparingDeviceSettings != null) { this.PreparingDeviceSettings(sender, args); } } /// Ranks the given list of devices that satisfy the given preferences. /// The list of devices to rank. protected virtual void RankDevices(List foundDevices) { this.RankDevicesPlatform(foundDevices); } private void RankDevicesPlatform(List foundDevices) { int index = 0; while (index < foundDevices.Count) { DeviceType deviceType = foundDevices[index].DeviceType; GraphicsAdapter adapter = foundDevices[index].Adapter; PresentationParameters presentationParameters = foundDevices[index].PresentationParameters; if (!adapter.CheckDeviceFormat(deviceType, adapter.CurrentDisplayMode.Format, TextureUsage.None, QueryUsages.PostPixelShaderBlending, ResourceType.Texture2D, presentationParameters.BackBufferFormat)) { foundDevices.RemoveAt(index); } else { index++; } } foundDevices.Sort(new GraphicsDeviceInformationComparer(this)); } void IDisposable.Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } /// Toggles between full screen and windowed mode. public void ToggleFullScreen() { this.IsFullScreen = !this.IsFullScreen; this.ChangeDevice(false); } private void ValidateGraphicsDeviceInformation(GraphicsDeviceInformation devInfo) { SurfaceFormat displayFormat; GraphicsAdapter adapter = devInfo.Adapter; DeviceType deviceType = devInfo.DeviceType; bool enableAutoDepthStencil = devInfo.PresentationParameters.EnableAutoDepthStencil; DepthFormat autoDepthStencilFormat = devInfo.PresentationParameters.AutoDepthStencilFormat; SurfaceFormat backBufferFormat = devInfo.PresentationParameters.BackBufferFormat; int backBufferWidth = devInfo.PresentationParameters.BackBufferWidth; int backBufferHeight = devInfo.PresentationParameters.BackBufferHeight; PresentationParameters presentationParameters = devInfo.PresentationParameters; SurfaceFormat format4 = presentationParameters.BackBufferFormat; if (!presentationParameters.IsFullScreen) { displayFormat = adapter.CurrentDisplayMode.Format; if (SurfaceFormat.Unknown == presentationParameters.BackBufferFormat) { format4 = displayFormat; } } else { SurfaceFormat format5 = presentationParameters.BackBufferFormat; if (format5 != SurfaceFormat.Color) { if (format5 != SurfaceFormat.Bgra5551) { displayFormat = presentationParameters.BackBufferFormat; } else { displayFormat = SurfaceFormat.Bgr555; } } else { displayFormat = SurfaceFormat.Bgr32; } } if (-1 == Array.IndexOf(ValidBackBufferFormats, format4)) { throw new ArgumentException("Resources.ValidateBackBufferFormatIsInvalid"); } if (!adapter.CheckDeviceType(deviceType, displayFormat, presentationParameters.BackBufferFormat, presentationParameters.IsFullScreen)) { throw new ArgumentException("Resources.ValidateDeviceType"); } if ((presentationParameters.BackBufferCount < 0) || (presentationParameters.BackBufferCount > 3)) { throw new ArgumentException("Resources.ValidateBackBufferCount"); } if ((presentationParameters.BackBufferCount > 1) && (presentationParameters.SwapEffect == SwapEffect.Copy)) { throw new ArgumentException("Resources.ValidateBackBufferCountSwapCopy"); } switch (presentationParameters.SwapEffect) { case SwapEffect.Discard: case SwapEffect.Flip: case SwapEffect.Copy: { int qualityLevels; if (!adapter.CheckDeviceMultiSampleType(deviceType, format4, presentationParameters.IsFullScreen, presentationParameters.MultiSampleType, out qualityLevels)) { throw new ArgumentException("Resources.ValidateMultiSampleTypeInvalid"); } if (presentationParameters.MultiSampleQuality >= qualityLevels) { throw new ArgumentException("Resources.ValidateMultiSampleQualityInvalid"); } if ((presentationParameters.MultiSampleType != MultiSampleType.None) && (presentationParameters.SwapEffect != SwapEffect.Discard)) { throw new ArgumentException("Resources.ValidateMultiSampleSwapEffect"); } if (((presentationParameters.PresentOptions & PresentOptions.DiscardDepthStencil) != PresentOptions.None) && !presentationParameters.EnableAutoDepthStencil) { throw new ArgumentException("Resources.ValidateAutoDepthStencilMismatch"); } if (presentationParameters.EnableAutoDepthStencil) { if (!adapter.CheckDeviceFormat(deviceType, displayFormat, TextureUsage.None, QueryUsages.None, ResourceType.DepthStencilBuffer, presentationParameters.AutoDepthStencilFormat)) { throw new ArgumentException("Resources.ValidateAutoDepthStencilFormatInvalid"); } if (!adapter.CheckDepthStencilMatch(deviceType, displayFormat, format4, presentationParameters.AutoDepthStencilFormat)) { throw new ArgumentException("Resources.ValidateAutoDepthStencilFormatIncompatible"); } } if (!presentationParameters.IsFullScreen) { if (presentationParameters.FullScreenRefreshRateInHz != 0) { throw new ArgumentException("Resources.ValidateRefreshRateInWindow"); } switch (presentationParameters.PresentationInterval) { case PresentInterval.Default: case PresentInterval.One: case PresentInterval.Immediate: return; } throw new ArgumentException("Resources.ValidatePresentationIntervalInWindow"); } if (presentationParameters.FullScreenRefreshRateInHz == 0) { throw new ArgumentException("Resources.ValidateRefreshRateInFullScreen"); } GraphicsDeviceCapabilities capabilities = adapter.GetCapabilities(deviceType); switch (presentationParameters.PresentationInterval) { case PresentInterval.Default: case PresentInterval.One: case PresentInterval.Immediate: goto Label_02E5; case PresentInterval.Two: case PresentInterval.Three: case PresentInterval.Four: if ((capabilities.PresentInterval & presentationParameters.PresentationInterval) == PresentInterval.Default) { throw new ArgumentException("Resources.ValidatePresentationIntervalIncompatibleInFullScreen"); } goto Label_02E5; } break; } default: throw new ArgumentException("Resources.ValidateSwapEffectInvalid"); } throw new ArgumentException("Resources.ValidatePresentationIntervalInFullScreen"); Label_02E5: if (presentationParameters.IsFullScreen) { if ((presentationParameters.BackBufferWidth == 0) || (presentationParameters.BackBufferHeight == 0)) { throw new ArgumentException("Resources.ValidateBackBufferDimsFullScreen"); } bool flag2 = true; bool flag3 = false; DisplayMode currentDisplayMode = adapter.CurrentDisplayMode; if (((currentDisplayMode.Format != displayFormat) && (currentDisplayMode.Width != presentationParameters.BackBufferHeight)) && ((currentDisplayMode.Height != presentationParameters.BackBufferHeight) && (currentDisplayMode.RefreshRate != presentationParameters.FullScreenRefreshRateInHz))) { flag2 = false; foreach (DisplayMode mode2 in adapter.SupportedDisplayModes[displayFormat]) { if ((mode2.Width == presentationParameters.BackBufferWidth) && (mode2.Height == presentationParameters.BackBufferHeight)) { flag3 = true; if (mode2.RefreshRate == presentationParameters.FullScreenRefreshRateInHz) { flag2 = true; break; } } } } if (!flag2 && flag3) { throw new ArgumentException("Resources.ValidateBackBufferDimsModeFullScreen"); } if (!flag2) { throw new ArgumentException("Resources.ValidateBackBufferHzModeFullScreen"); } } if (presentationParameters.EnableAutoDepthStencil != enableAutoDepthStencil) { throw new ArgumentException("Resources.ValidateAutoDepthStencilAdapterGroup"); } if (presentationParameters.EnableAutoDepthStencil) { if (presentationParameters.AutoDepthStencilFormat != autoDepthStencilFormat) { throw new ArgumentException("Resources.ValidateAutoDepthStencilAdapterGroup"); } if (presentationParameters.BackBufferFormat != backBufferFormat) { throw new ArgumentException("Resources.ValidateAutoDepthStencilAdapterGroup"); } if (presentationParameters.BackBufferWidth != backBufferWidth) { throw new ArgumentException("Resources.ValidateAutoDepthStencilAdapterGroup"); } if (presentationParameters.BackBufferHeight != backBufferHeight) { throw new ArgumentException("Resources.ValidateAutoDepthStencilAdapterGroup"); } } } /// Gets the Framework.Graphics.GraphicsDevice associated with the GraphicsDeviceManager. /// /// The Framework.Graphics.GraphicsDevice associated with the GraphicsDeviceManager. /// public GraphicsDevice GraphicsDevice { get { return this.device; } } /// /// Gets or sets a value that indicates whether the device should start in full-screen mode. /// /// Value that indicates whether the device should start in full-screen mode. public bool IsFullScreen { get { return this.isFullScreen; } set { this.isFullScreen = value; this.isDeviceDirty = true; } } /// Gets or sets the minimum pixel shader version required by the GraphicsDeviceManager. /// /// The minimum pixel shader version required by the GraphicsDeviceManager. /// public ShaderProfile MinimumPixelShaderProfile { get { return this.minimumPixelShaderProfile; } set { if ((value < ShaderProfile.PS_1_1) || (value > ShaderProfile.XPS_3_0)) { throw new ArgumentOutOfRangeException("value", "Resources.InvalidPixelShaderProfile"); } this.minimumPixelShaderProfile = value; this.isDeviceDirty = true; } } /// /// Gets or sets the minimum vertex shader version required by the GraphicsDeviceManager. /// /// /// The minimum vertex shader version required by the GraphicsDeviceManager. /// public ShaderProfile MinimumVertexShaderProfile { get { return this.minimumVertexShaderProfile; } set { if ((value < ShaderProfile.VS_1_1) || (value > ShaderProfile.XVS_3_0)) { throw new ArgumentOutOfRangeException("value", "Resources.InvalidVertexShaderProfile"); } this.minimumVertexShaderProfile = value; this.isDeviceDirty = true; } } /// Gets or sets a value that indicates whether to enable a multisampled back buffer. /// Value indicating whether multisampling is enabled on the back buffer. public bool PreferMultiSampling { get { return this.allowMultiSampling; } set { this.allowMultiSampling = value; this.isDeviceDirty = true; } } /// Gets or sets the format of the back buffer. /// The format of the back buffer. public SurfaceFormat PreferredBackBufferFormat { get { return this.backBufferFormat; } set { if (Array.IndexOf(ValidBackBufferFormats, value) == -1) { throw new ArgumentOutOfRangeException("value", "Resources.ValidateBackBufferFormatIsInvalid"); } this.backBufferFormat = value; this.isDeviceDirty = true; } } /// Gets or sets the preferred back-buffer height. /// The preferred back-buffer height. public int PreferredBackBufferHeight { get { return this.backBufferHeight; } set { if (value <= 0) { throw new ArgumentOutOfRangeException("value", "Resources.BackBufferDimMustBePositive"); } this.backBufferHeight = value; this.useResizedBackBuffer = false; this.isDeviceDirty = true; } } /// Gets or sets the preferred back-buffer width. /// The preferred back-buffer width. public int PreferredBackBufferWidth { get { return this.backBufferWidth; } set { if (value <= 0) { throw new ArgumentOutOfRangeException("value", "Resources.BackBufferDimMustBePositive"); } this.backBufferWidth = value; this.useResizedBackBuffer = false; this.isDeviceDirty = true; } } /// Gets or sets the format of the depth stencil. /// The format of the depth stencil. public DepthFormat PreferredDepthStencilFormat { get { return this.depthStencilFormat; } set { switch (value) { case DepthFormat.Depth24Stencil8: case DepthFormat.Depth24Stencil8Single: case DepthFormat.Depth24Stencil4: case DepthFormat.Depth24: case DepthFormat.Depth32: case DepthFormat.Depth16: case DepthFormat.Depth15Stencil1: this.depthStencilFormat = value; this.isDeviceDirty = true; return; } throw new ArgumentOutOfRangeException("value", "Resources.ValidateDepthStencilFormatIsInvalid"); } } /// Gets or sets a value that indicates whether to sync to the vertical trace (vsync) when presenting /// the back buffer. /// /// /// Value that indicates whether to sync to the vertical trace (vsync) when presenting /// the back buffer. /// public bool SynchronizeWithVerticalRetrace { get { return this.synchronizeWithVerticalRetrace; } set { this.synchronizeWithVerticalRetrace = value; this.isDeviceDirty = true; } } #region WindowsGameWindow members internal static Screen ScreenFromAdapter(GraphicsAdapter adapter) { foreach (Screen screen in Screen.AllScreens) { if (DeviceNameFromScreen(screen) == adapter.DeviceName) { return screen; } } throw new ArgumentException("Resources.InvalidScreenAdapter", "adapter"); } internal static Screen ScreenFromHandle(IntPtr windowHandle) { NativeMethods.RECT rect; int num = 0; Screen screen = null; NativeMethods.GetWindowRect(windowHandle, out rect); Rectangle rectangle = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top); foreach (Screen screen2 in Screen.AllScreens) { Rectangle rectangle2 = rectangle; rectangle2.Intersect(screen2.Bounds); int num2 = rectangle2.Width * rectangle2.Height; if (num2 > num) { num = num2; screen = screen2; } } if (screen == null) { screen = Screen.AllScreens[0]; } return screen; } internal static string DeviceNameFromScreen(Screen screen) { string deviceName = screen.DeviceName; int length = screen.DeviceName.IndexOf('\0'); if (length != -1) { deviceName = screen.DeviceName.Substring(0, length); } return deviceName; } #endregion } } // namespace Nuclex