From 793744402ed8ae45bcb3c6bbd9843bc53868364f Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Thu, 24 Jan 2008 10:50:39 +0000 Subject: [PATCH] WinDisplayDevice is now multiple-monitor aware. Added SelectResolution function to DisplayDevice. Updated test to change settings on all available monitors. --- .../Examples/Tests/TestResolutionChanges.cs | 8 +- Source/OpenTK/Graphics/DisplayDevice.cs | 102 +++++++++++++----- Source/OpenTK/Graphics/DisplayResolution.cs | 5 + .../OpenTK/Graphics/IDisplayDeviceDriver.cs | 4 +- .../Platform/Windows/WinDisplayDevice.cs | 36 ++++--- 5 files changed, 106 insertions(+), 49 deletions(-) diff --git a/Source/Examples/Tests/TestResolutionChanges.cs b/Source/Examples/Tests/TestResolutionChanges.cs index b353b66f..426d32ca 100644 --- a/Source/Examples/Tests/TestResolutionChanges.cs +++ b/Source/Examples/Tests/TestResolutionChanges.cs @@ -24,9 +24,11 @@ namespace Examples.Tests foreach (DisplayDevice dev in DisplayDevice.AvailableDisplays) { Trace.WriteLine(dev.ToString()); - //MessageBox.Show(dev.ToString()); - //dev.ChangeResolution(640, 480, 32, 60.0f); - //dev.RestoreResolution(); + MessageBox.Show(dev.ToString()); + // Switch to the first available resolution that has the same bpp as the current one (usually 640x480@60Hz) + dev.ChangeResolution(dev.SelectResolution(0, 0, dev.BitsPerPixel, 0)); + MessageBox.Show(dev.ToString()); + dev.RestoreResolution(); } } } diff --git a/Source/OpenTK/Graphics/DisplayDevice.cs b/Source/OpenTK/Graphics/DisplayDevice.cs index 330a154b..96d50455 100644 --- a/Source/OpenTK/Graphics/DisplayDevice.cs +++ b/Source/OpenTK/Graphics/DisplayDevice.cs @@ -67,7 +67,6 @@ namespace OpenTK.Graphics #region --- Public Methods --- - #region public int Width /// Gets a System.Int32 that contains the width of this display in pixels. @@ -108,7 +107,54 @@ namespace OpenTK.Graphics #endregion - #region public void ChangeResolution(int width, int height, int bitsPerPixel, float refreshRate) + #region public DisplayResolution[] AvailableResolutions + + /// + /// Gets an array of OpenTK.DisplayResolution objects, which describe all available resolutions + /// for this device. + /// + public DisplayResolution[] AvailableResolutions + { + get + { + lock (display_lock) + { + return available_resolutions.ToArray(); + } + } + } + + #endregion + + #region public DisplayResolution SelectResolution(int width, int height, int bitsPerPixel, float refreshRate) + + /// + /// Selects an available resolution that matches the specified parameters. + /// + /// The width of the requested resolution in pixels. + /// The height of the requested resolution in pixels. + /// The bits per pixel of the requested resolution. + /// The refresh rate of the requested resolution in Herz. + /// The requested DisplayResolution or null if the parameters cannot be met. + /// + /// A parameter set to 0 will not be used in the search (e.g. if refreshRate is 0, any refresh rate will be considered valid). + /// This function generates garbage. + /// + public DisplayResolution SelectResolution(int width, int height, int bitsPerPixel, float refreshRate) + { + return available_resolutions.Find(delegate(DisplayResolution test) + { + return + ((width > 0 && width == test.Width) || width == 0) && + ((height > 0 && height == test.Height) || height == 0) && + ((bitsPerPixel > 0 && bitsPerPixel == test.BitsPerPixel) || bitsPerPixel == 0) && + ((refreshRate > 0 && (int)refreshRate == (int)test.RefreshRate) || refreshRate == 0); + }); + } + + #endregion + + #region public void ChangeResolution(DisplayResolution resolution) /// Changes the resolution of the DisplayDevice. /// The new width of the DisplayDevice. @@ -116,20 +162,18 @@ namespace OpenTK.Graphics /// The new bits per pixel of the DisplayDevice. /// The new refresh rate of the DisplayDevice. /// Thrown if the requested resolution change failed. - public void ChangeResolution(int width, int height, int bitsPerPixel, float refreshRate) + public void ChangeResolution(DisplayResolution resolution) { - if (width <= 0) throw new ArgumentOutOfRangeException("width", "Must be greater than zero."); - if (height <= 0) throw new ArgumentOutOfRangeException("height", "Must be greater than zero."); - if (bitsPerPixel <= 0) throw new ArgumentOutOfRangeException("bitsPerPixel", "Must be greater than zero."); - if (refreshRate <= 0) throw new ArgumentOutOfRangeException("refreshRate", "Must be greater than zero."); + if (resolution == null) + throw new ArgumentNullException("resulotion", "Must be a valid resolution."); - if (implementation.TryChangeResolution(width, height, bitsPerPixel, refreshRate)) + if (implementation.TryChangeResolution(this, resolution)) { - current_resolution = new DisplayResolution(width, height, bitsPerPixel, refreshRate); + current_resolution = resolution; } else - throw new GraphicsModeException(String.Format("Device {0}: Failed to change resolution to {1}x{2}x{3]@{4]Hz", - ToString(), width, height, bitsPerPixel, refreshRate)); + throw new GraphicsModeException(String.Format("Device {0}: Failed to change resolution to {1}.", + this, resolution)); } #endregion @@ -138,7 +182,7 @@ namespace OpenTK.Graphics public void RestoreResolution() { - implementation.RestoreResolution(); + implementation.RestoreResolution(this); } #endregion @@ -146,7 +190,7 @@ namespace OpenTK.Graphics #region public static DisplayDevice[] AvailableDisplays /// - /// Gets an array of OpenTK.Display objects, which describe all available display devices. + /// Gets an array of OpenTK.DisplayDevice objects, which describe all available display devices. /// public static DisplayDevice[] AvailableDisplays { @@ -191,19 +235,19 @@ namespace OpenTK.Graphics /// Determines whether the specified DisplayDevices are equal. /// The System.Object to check against. /// True if the System.Object is an equal DisplayDevice; false otherwise. - public override bool Equals(object obj) - { - if (obj is DisplayDevice) - { - DisplayDevice dev = (DisplayDevice)obj; - return - IsPrimary == dev.IsPrimary && - current_resolution == dev.current_resolution && - available_resolutions.Count == dev.available_resolutions.Count; - } + //public override bool Equals(object obj) + //{ + // if (obj is DisplayDevice) + // { + // DisplayDevice dev = (DisplayDevice)obj; + // return + // IsPrimary == dev.IsPrimary && + // current_resolution == dev.current_resolution && + // available_resolutions.Count == dev.available_resolutions.Count; + // } - return false; - } + // return false; + //} #endregion @@ -211,10 +255,10 @@ namespace OpenTK.Graphics /// Returns a unique hash representing this DisplayDevice. /// A System.Int32 that may serve as a hash code for this DisplayDevice. - public override int GetHashCode() - { - return current_resolution.GetHashCode() ^ IsPrimary.GetHashCode() ^ available_resolutions.Count; - } + //public override int GetHashCode() + //{ + // return current_resolution.GetHashCode() ^ IsPrimary.GetHashCode() ^ available_resolutions.Count; + //} #endregion diff --git a/Source/OpenTK/Graphics/DisplayResolution.cs b/Source/OpenTK/Graphics/DisplayResolution.cs index 46457bff..1cf62357 100644 --- a/Source/OpenTK/Graphics/DisplayResolution.cs +++ b/Source/OpenTK/Graphics/DisplayResolution.cs @@ -24,6 +24,11 @@ namespace OpenTK.Graphics internal DisplayResolution(int width, int height, int bitsPerPixel, float refreshRate) { + if (width <= 0) throw new ArgumentOutOfRangeException("width", "Must be greater than zero."); + if (height <= 0) throw new ArgumentOutOfRangeException("height", "Must be greater than zero."); + if (bitsPerPixel <= 0) throw new ArgumentOutOfRangeException("bitsPerPixel", "Must be greater than zero."); + if (refreshRate <= 0) throw new ArgumentOutOfRangeException("refreshRate", "Must be greater than zero."); + this.width = width; this.height = height; this.bits_per_pixel = bitsPerPixel; diff --git a/Source/OpenTK/Graphics/IDisplayDeviceDriver.cs b/Source/OpenTK/Graphics/IDisplayDeviceDriver.cs index 6845def2..6b4eac1c 100644 --- a/Source/OpenTK/Graphics/IDisplayDeviceDriver.cs +++ b/Source/OpenTK/Graphics/IDisplayDeviceDriver.cs @@ -14,8 +14,8 @@ namespace OpenTK.Graphics { internal interface IDisplayDeviceDriver { - bool TryChangeResolution(int width, int height, int bitsPerPixel, float refreshRate); - void RestoreResolution(); + bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution); + void RestoreResolution(DisplayDevice device); //DisplayDevice[] AvailableDevices { get; } //DisplayResolution[] } diff --git a/Source/OpenTK/Platform/Windows/WinDisplayDevice.cs b/Source/OpenTK/Platform/Windows/WinDisplayDevice.cs index 1784b861..8458b96a 100644 --- a/Source/OpenTK/Platform/Windows/WinDisplayDevice.cs +++ b/Source/OpenTK/Platform/Windows/WinDisplayDevice.cs @@ -18,8 +18,9 @@ namespace OpenTK.Platform.Windows { internal class WinDisplayDeviceDriver : IDisplayDeviceDriver { - // In OpenTK nomenclature, a DisplayDevice is a screen, not a video card! static object display_lock = new object(); + static Dictionary available_device_names = + new Dictionary(); // Needed for ChangeDisplaySettingsEx #region --- Constructors --- @@ -71,6 +72,8 @@ namespace OpenTK.Platform.Windows // Construct the OpenTK DisplayDevice through the accumulated parameters. opentk_dev = new OpenTK.Graphics.DisplayDevice(opentk_dev_current_res, opentk_dev_primary, opentk_dev_available_res); + + available_device_names.Add(opentk_dev, dev1.DeviceName); } } } @@ -83,31 +86,34 @@ namespace OpenTK.Platform.Windows #region --- IDisplayDeviceDriver Members --- - #region public bool TryChangeResolution(int width, int height, int bitsPerPixel, float refreshRate) + #region public bool TryChangeResolution(OpenTK.Graphics.DisplayDevice device, DisplayResolution resolution) - public bool TryChangeResolution(int width, int height, int bitsPerPixel, float refreshRate) + public bool TryChangeResolution(OpenTK.Graphics.DisplayDevice device, DisplayResolution resolution) { - DeviceMode settings = new DeviceMode(); - settings.PelsWidth = width; - settings.PelsHeight = height; - settings.BitsPerPel = bitsPerPixel; - settings.DisplayFrequency = (int)refreshRate; - settings.Fields = Constants.DM_BITSPERPEL + DeviceMode mode = new DeviceMode(); + mode.PelsWidth = resolution.Width; + mode.PelsHeight = resolution.Height; + mode.BitsPerPel = resolution.BitsPerPixel; + mode.DisplayFrequency = (int)resolution.RefreshRate; + mode.Fields = Constants.DM_BITSPERPEL | Constants.DM_PELSWIDTH - | Constants.DM_PELSHEIGHT; + | Constants.DM_PELSHEIGHT + | Constants.DM_DISPLAYFREQUENCY; - return Functions.ChangeDisplaySettings(settings, ChangeDisplaySettingsEnum.Fullscreen) == + //return Functions.ChangeDisplaySettings(settings, ChangeDisplaySettingsEnum.Fullscreen) == + // Constants.DISP_CHANGE_SUCCESSFUL; + return Functions.ChangeDisplaySettingsEx(available_device_names[device], mode, IntPtr.Zero, 0, IntPtr.Zero) == Constants.DISP_CHANGE_SUCCESSFUL; } #endregion - #region public void RestoreResolution() + #region public void RestoreResolution(OpenTK.Graphics.DisplayDevice device) - public void RestoreResolution() + public void RestoreResolution(OpenTK.Graphics.DisplayDevice device) { - Functions.ChangeDisplaySettings(null, (ChangeDisplaySettingsEnum)0); - //Functions.ChangeDisplaySettings( + //Functions.ChangeDisplaySettings(null, (ChangeDisplaySettingsEnum)0); + Functions.ChangeDisplaySettingsEx(available_device_names[device], null, IntPtr.Zero, 0, IntPtr.Zero); } #endregion