(ded4a3e0a) v0.9.0.7
This commit is contained in:
@@ -0,0 +1,579 @@
|
||||
// MonoGame - Copyright (C) The MonoGame Team
|
||||
// This file is subject to the terms and conditions defined in
|
||||
// file 'LICENSE.txt', which is part of this source code package.
|
||||
|
||||
using System;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input.Touch;
|
||||
|
||||
namespace Microsoft.Xna.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to initialize and control the presentation of the graphics device.
|
||||
/// </summary>
|
||||
public partial class GraphicsDeviceManager : IGraphicsDeviceService, IDisposable, IGraphicsDeviceManager
|
||||
{
|
||||
private readonly Game _game;
|
||||
private GraphicsDevice _graphicsDevice;
|
||||
private bool _initialized = false;
|
||||
|
||||
private int _preferredBackBufferHeight;
|
||||
private int _preferredBackBufferWidth;
|
||||
private SurfaceFormat _preferredBackBufferFormat;
|
||||
private DepthFormat _preferredDepthStencilFormat;
|
||||
private bool _preferMultiSampling;
|
||||
private DisplayOrientation _supportedOrientations;
|
||||
private bool _synchronizedWithVerticalRetrace = true;
|
||||
private bool _drawBegun;
|
||||
private bool _disposed;
|
||||
private bool _hardwareModeSwitch = true;
|
||||
private bool _wantFullScreen;
|
||||
private GraphicsProfile _graphicsProfile;
|
||||
// dirty flag for ApplyChanges
|
||||
private bool _shouldApplyChanges;
|
||||
|
||||
/// <summary>
|
||||
/// The default back buffer width.
|
||||
/// </summary>
|
||||
public static readonly int DefaultBackBufferWidth = 800;
|
||||
|
||||
/// <summary>
|
||||
/// The default back buffer height.
|
||||
/// </summary>
|
||||
public static readonly int DefaultBackBufferHeight = 480;
|
||||
|
||||
/// <summary>
|
||||
/// Optional override for platform specific defaults.
|
||||
/// </summary>
|
||||
partial void PlatformConstruct();
|
||||
|
||||
/// <summary>
|
||||
/// Associates this graphics device manager to a game instances.
|
||||
/// </summary>
|
||||
/// <param name="game">The game instance to attach.</param>
|
||||
public GraphicsDeviceManager(Game game)
|
||||
{
|
||||
if (game == null)
|
||||
throw new ArgumentNullException("game", "Game cannot be null.");
|
||||
|
||||
_game = game;
|
||||
|
||||
_supportedOrientations = DisplayOrientation.Default;
|
||||
_preferredBackBufferFormat = SurfaceFormat.Color;
|
||||
_preferredDepthStencilFormat = DepthFormat.Depth24;
|
||||
_synchronizedWithVerticalRetrace = true;
|
||||
|
||||
// Assume the window client size as the default back
|
||||
// buffer resolution in the landscape orientation.
|
||||
var clientBounds = _game.Window.ClientBounds;
|
||||
if (clientBounds.Width >= clientBounds.Height)
|
||||
{
|
||||
_preferredBackBufferWidth = clientBounds.Width;
|
||||
_preferredBackBufferHeight = clientBounds.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
_preferredBackBufferWidth = clientBounds.Height;
|
||||
_preferredBackBufferHeight = clientBounds.Width;
|
||||
}
|
||||
|
||||
// Default to windowed mode... this is ignored on platforms that don't support it.
|
||||
_wantFullScreen = false;
|
||||
|
||||
// XNA would read this from the manifest, but it would always default
|
||||
// to reach unless changed. So lets mimic that without the manifest bit.
|
||||
GraphicsProfile = GraphicsProfile.Reach;
|
||||
|
||||
// Let the plaform optionally overload construction defaults.
|
||||
PlatformConstruct();
|
||||
|
||||
if (_game.Services.GetService(typeof(IGraphicsDeviceManager)) != null)
|
||||
throw new ArgumentException("A graphics device manager is already registered. The graphics device manager cannot be changed once it is set.");
|
||||
_game.graphicsDeviceManager = this;
|
||||
|
||||
_game.Services.AddService(typeof(IGraphicsDeviceManager), this);
|
||||
_game.Services.AddService(typeof(IGraphicsDeviceService), this);
|
||||
}
|
||||
|
||||
~GraphicsDeviceManager()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
private void CreateDevice()
|
||||
{
|
||||
if (_graphicsDevice != null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (!_initialized)
|
||||
Initialize();
|
||||
|
||||
var gdi = DoPreparingDeviceSettings();
|
||||
CreateDevice(gdi);
|
||||
}
|
||||
catch (NoSuitableGraphicsDeviceException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new NoSuitableGraphicsDeviceException("Failed to create graphics device!", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateDevice(GraphicsDeviceInformation gdi)
|
||||
{
|
||||
if (_graphicsDevice != null)
|
||||
return;
|
||||
|
||||
_graphicsDevice = new GraphicsDevice(gdi);
|
||||
_shouldApplyChanges = false;
|
||||
|
||||
// hook up reset events
|
||||
GraphicsDevice.DeviceReset += (sender, args) => OnDeviceReset(args);
|
||||
GraphicsDevice.DeviceResetting += (sender, args) => OnDeviceResetting(args);
|
||||
|
||||
// update the touchpanel display size when the graphicsdevice is reset
|
||||
_graphicsDevice.DeviceReset += UpdateTouchPanel;
|
||||
_graphicsDevice.PresentationChanged += OnPresentationChanged;
|
||||
|
||||
OnDeviceCreated(EventArgs.Empty);
|
||||
}
|
||||
|
||||
void IGraphicsDeviceManager.CreateDevice()
|
||||
{
|
||||
CreateDevice();
|
||||
}
|
||||
|
||||
public bool BeginDraw()
|
||||
{
|
||||
if (_graphicsDevice == null)
|
||||
return false;
|
||||
|
||||
_drawBegun = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void EndDraw()
|
||||
{
|
||||
if (_graphicsDevice != null && _drawBegun)
|
||||
{
|
||||
_drawBegun = false;
|
||||
_graphicsDevice.Present();
|
||||
}
|
||||
}
|
||||
|
||||
#region IGraphicsDeviceService Members
|
||||
|
||||
public event EventHandler<EventArgs> DeviceCreated;
|
||||
public event EventHandler<EventArgs> DeviceDisposing;
|
||||
public event EventHandler<EventArgs> DeviceReset;
|
||||
public event EventHandler<EventArgs> DeviceResetting;
|
||||
public event EventHandler<PreparingDeviceSettingsEventArgs> PreparingDeviceSettings;
|
||||
public event EventHandler<EventArgs> Disposed;
|
||||
|
||||
protected void OnDeviceDisposing(EventArgs e)
|
||||
{
|
||||
EventHelpers.Raise(this, DeviceDisposing, e);
|
||||
}
|
||||
|
||||
protected void OnDeviceResetting(EventArgs e)
|
||||
{
|
||||
EventHelpers.Raise(this, DeviceResetting, e);
|
||||
}
|
||||
|
||||
internal void OnDeviceReset(EventArgs e)
|
||||
{
|
||||
EventHelpers.Raise(this, DeviceReset, e);
|
||||
}
|
||||
|
||||
internal void OnDeviceCreated(EventArgs e)
|
||||
{
|
||||
EventHelpers.Raise(this, DeviceCreated, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This populates a GraphicsDeviceInformation instance and invokes PreparingDeviceSettings to
|
||||
/// allow users to change the settings. Then returns that GraphicsDeviceInformation.
|
||||
/// Throws NullReferenceException if users set GraphicsDeviceInformation.PresentationParameters to null.
|
||||
/// </summary>
|
||||
private GraphicsDeviceInformation DoPreparingDeviceSettings()
|
||||
{
|
||||
var gdi = new GraphicsDeviceInformation();
|
||||
PrepareGraphicsDeviceInformation(gdi);
|
||||
var preparingDeviceSettingsHandler = PreparingDeviceSettings;
|
||||
|
||||
if (preparingDeviceSettingsHandler != null)
|
||||
{
|
||||
// this allows users to overwrite settings through the argument
|
||||
var args = new PreparingDeviceSettingsEventArgs(gdi);
|
||||
preparingDeviceSettingsHandler(this, args);
|
||||
|
||||
if (gdi.PresentationParameters == null || gdi.Adapter == null)
|
||||
throw new NullReferenceException("Members should not be set to null in PreparingDeviceSettingsEventArgs");
|
||||
}
|
||||
|
||||
return gdi;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_graphicsDevice != null)
|
||||
{
|
||||
_graphicsDevice.Dispose();
|
||||
_graphicsDevice = null;
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
EventHelpers.Raise(this, Disposed, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
partial void PlatformApplyChanges();
|
||||
|
||||
partial void PlatformPreparePresentationParameters(PresentationParameters presentationParameters);
|
||||
|
||||
private void PreparePresentationParameters(PresentationParameters presentationParameters)
|
||||
{
|
||||
presentationParameters.BackBufferFormat = _preferredBackBufferFormat;
|
||||
presentationParameters.BackBufferWidth = _preferredBackBufferWidth;
|
||||
presentationParameters.BackBufferHeight = _preferredBackBufferHeight;
|
||||
presentationParameters.DepthStencilFormat = _preferredDepthStencilFormat;
|
||||
presentationParameters.IsFullScreen = _wantFullScreen;
|
||||
presentationParameters.HardwareModeSwitch = _hardwareModeSwitch;
|
||||
presentationParameters.PresentationInterval = _synchronizedWithVerticalRetrace ? PresentInterval.One : PresentInterval.Immediate;
|
||||
presentationParameters.DisplayOrientation = _game.Window.CurrentOrientation;
|
||||
#if WINDOWS && DIRECTX
|
||||
presentationParameters.DeviceWindowHandle = _game.Window.Hwnd;
|
||||
#else
|
||||
presentationParameters.DeviceWindowHandle = _game.Window.Handle;
|
||||
#endif
|
||||
|
||||
if (_preferMultiSampling)
|
||||
{
|
||||
// always initialize MultiSampleCount to the maximum, if users want to overwrite
|
||||
// this they have to respond to the PreparingDeviceSettingsEvent and modify
|
||||
// args.GraphicsDeviceInformation.PresentationParameters.MultiSampleCount
|
||||
presentationParameters.MultiSampleCount = GraphicsDevice != null
|
||||
? GraphicsDevice.GraphicsCapabilities.MaxMultiSampleCount
|
||||
: 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
presentationParameters.MultiSampleCount = 0;
|
||||
}
|
||||
|
||||
PlatformPreparePresentationParameters(presentationParameters);
|
||||
}
|
||||
|
||||
private void PrepareGraphicsDeviceInformation(GraphicsDeviceInformation gdi)
|
||||
{
|
||||
gdi.Adapter = GraphicsAdapter.DefaultAdapter;
|
||||
gdi.GraphicsProfile = GraphicsProfile;
|
||||
var pp = new PresentationParameters();
|
||||
PreparePresentationParameters(pp);
|
||||
gdi.PresentationParameters = pp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies any pending property changes to the graphics device.
|
||||
/// </summary>
|
||||
public void ApplyChanges()
|
||||
{
|
||||
// If the device hasn't been created then create it now.
|
||||
if (_graphicsDevice == null)
|
||||
CreateDevice();
|
||||
|
||||
if (!_shouldApplyChanges)
|
||||
return;
|
||||
|
||||
_shouldApplyChanges = false;
|
||||
|
||||
_game.Window.SetSupportedOrientations(_supportedOrientations);
|
||||
|
||||
// Allow for optional platform specific behavior.
|
||||
PlatformApplyChanges();
|
||||
|
||||
// populates a gdi with settings in this gdm and allows users to override them with
|
||||
// PrepareDeviceSettings event this information should be applied to the GraphicsDevice
|
||||
var gdi = DoPreparingDeviceSettings();
|
||||
|
||||
if (gdi.GraphicsProfile != GraphicsDevice.GraphicsProfile)
|
||||
{
|
||||
// if the GraphicsProfile changed we need to create a new GraphicsDevice
|
||||
DisposeGraphicsDevice();
|
||||
CreateDevice(gdi);
|
||||
return;
|
||||
}
|
||||
|
||||
GraphicsDevice.Reset(gdi.PresentationParameters);
|
||||
}
|
||||
|
||||
private void DisposeGraphicsDevice()
|
||||
{
|
||||
_graphicsDevice.Dispose();
|
||||
EventHelpers.Raise(this, DeviceDisposing, EventArgs.Empty);
|
||||
_graphicsDevice = null;
|
||||
}
|
||||
|
||||
partial void PlatformInitialize(PresentationParameters presentationParameters);
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
_game.Window.SetSupportedOrientations(_supportedOrientations);
|
||||
|
||||
var presentationParameters = new PresentationParameters();
|
||||
PreparePresentationParameters(presentationParameters);
|
||||
|
||||
// Allow for any per-platform changes to the presentation.
|
||||
PlatformInitialize(presentationParameters);
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
private void UpdateTouchPanel(object sender, EventArgs eventArgs)
|
||||
{
|
||||
TouchPanel.DisplayWidth = _graphicsDevice.PresentationParameters.BackBufferWidth;
|
||||
TouchPanel.DisplayHeight = _graphicsDevice.PresentationParameters.BackBufferHeight;
|
||||
TouchPanel.DisplayOrientation = _graphicsDevice.PresentationParameters.DisplayOrientation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles between windowed and fullscreen modes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that on platforms that do not support windowed modes this has no affect.
|
||||
/// </remarks>
|
||||
public void ToggleFullScreen()
|
||||
{
|
||||
IsFullScreen = !IsFullScreen;
|
||||
ApplyChanges();
|
||||
}
|
||||
|
||||
private void OnPresentationChanged(object sender, PresentationEventArgs args)
|
||||
{
|
||||
_game.Platform.OnPresentationChanged(args.PresentationParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The profile which determines the graphics feature level.
|
||||
/// </summary>
|
||||
public GraphicsProfile GraphicsProfile
|
||||
{
|
||||
get
|
||||
{
|
||||
return _graphicsProfile;
|
||||
}
|
||||
set
|
||||
{
|
||||
_shouldApplyChanges = true;
|
||||
_graphicsProfile = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the graphics device for this manager.
|
||||
/// </summary>
|
||||
public GraphicsDevice GraphicsDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
return _graphicsDevice;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the desire to switch into fullscreen mode.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When called at startup this will automatically set fullscreen mode during initialization. If
|
||||
/// set after startup you must call ApplyChanges() for the fullscreen mode to be changed.
|
||||
/// Note that for some platforms that do not support windowed modes this property has no affect.
|
||||
/// </remarks>
|
||||
public bool IsFullScreen
|
||||
{
|
||||
get { return _wantFullScreen; }
|
||||
set
|
||||
{
|
||||
_shouldApplyChanges = true;
|
||||
_wantFullScreen = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the boolean which defines how window switches from windowed to fullscreen state.
|
||||
/// "Hard" mode(true) is slow to switch, but more effecient for performance, while "soft" mode(false) is vice versa.
|
||||
/// The default value is <c>true</c>.
|
||||
/// </summary>
|
||||
public bool HardwareModeSwitch
|
||||
{
|
||||
get { return _hardwareModeSwitch;}
|
||||
set
|
||||
{
|
||||
_shouldApplyChanges = true;
|
||||
_hardwareModeSwitch = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the desire for a multisampled back buffer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When called at startup this will automatically set the MSAA mode during initialization. If
|
||||
/// set after startup you must call ApplyChanges() for the MSAA mode to be changed.
|
||||
/// </remarks>
|
||||
public bool PreferMultiSampling
|
||||
{
|
||||
get
|
||||
{
|
||||
return _preferMultiSampling;
|
||||
}
|
||||
set
|
||||
{
|
||||
_shouldApplyChanges = true;
|
||||
_preferMultiSampling = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the desired back buffer color format.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When called at startup this will automatically set the format during initialization. If
|
||||
/// set after startup you must call ApplyChanges() for the format to be changed.
|
||||
/// </remarks>
|
||||
public SurfaceFormat PreferredBackBufferFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return _preferredBackBufferFormat;
|
||||
}
|
||||
set
|
||||
{
|
||||
_shouldApplyChanges = true;
|
||||
_preferredBackBufferFormat = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the desired back buffer height in pixels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When called at startup this will automatically set the height during initialization. If
|
||||
/// set after startup you must call ApplyChanges() for the height to be changed.
|
||||
/// </remarks>
|
||||
public int PreferredBackBufferHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
return _preferredBackBufferHeight;
|
||||
}
|
||||
set
|
||||
{
|
||||
_shouldApplyChanges = true;
|
||||
_preferredBackBufferHeight = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the desired back buffer width in pixels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When called at startup this will automatically set the width during initialization. If
|
||||
/// set after startup you must call ApplyChanges() for the width to be changed.
|
||||
/// </remarks>
|
||||
public int PreferredBackBufferWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return _preferredBackBufferWidth;
|
||||
}
|
||||
set
|
||||
{
|
||||
_shouldApplyChanges = true;
|
||||
_preferredBackBufferWidth = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the desired depth-stencil buffer format.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The depth-stencil buffer format defines the scene depth precision and stencil bits available for effects during rendering.
|
||||
/// When called at startup this will automatically set the format during initialization. If
|
||||
/// set after startup you must call ApplyChanges() for the format to be changed.
|
||||
/// </remarks>
|
||||
public DepthFormat PreferredDepthStencilFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return _preferredDepthStencilFormat;
|
||||
}
|
||||
set
|
||||
{
|
||||
_shouldApplyChanges = true;
|
||||
_preferredDepthStencilFormat = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the desire for vsync when presenting the back buffer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Vsync limits the frame rate of the game to the monitor referesh rate to prevent screen tearing.
|
||||
/// When called at startup this will automatically set the vsync mode during initialization. If
|
||||
/// set after startup you must call ApplyChanges() for the vsync mode to be changed.
|
||||
/// </remarks>
|
||||
public bool SynchronizeWithVerticalRetrace
|
||||
{
|
||||
get
|
||||
{
|
||||
return _synchronizedWithVerticalRetrace;
|
||||
}
|
||||
set
|
||||
{
|
||||
_shouldApplyChanges = true;
|
||||
_synchronizedWithVerticalRetrace = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates the desired allowable display orientations when the device is rotated.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property only applies to mobile platforms with automatic display rotation.
|
||||
/// When called at startup this will automatically apply the supported orientations during initialization. If
|
||||
/// set after startup you must call ApplyChanges() for the supported orientations to be changed.
|
||||
/// </remarks>
|
||||
public DisplayOrientation SupportedOrientations
|
||||
{
|
||||
get
|
||||
{
|
||||
return _supportedOrientations;
|
||||
}
|
||||
set
|
||||
{
|
||||
_shouldApplyChanges = true;
|
||||
_supportedOrientations = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user