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