mirror of
https://github.com/Ryujinx/Opentk.git
synced 2024-12-26 17:15:33 +00:00
7b591962e8
As the original_resolution field needs to be accessed from outside the module, it should be an internal property as opposed to an internal field
222 lines
8.7 KiB
C#
222 lines
8.7 KiB
C#
#region License
|
|
//
|
|
// The Open Toolkit Library License
|
|
//
|
|
// Copyright (c) 2006 - 2010 the Open Toolkit library.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights to
|
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
// the Software, and to permit persons to whom the Software is furnished to do
|
|
// so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
// OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
#endregion
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
#if !MINIMAL
|
|
using Microsoft.Win32;
|
|
#endif
|
|
|
|
namespace OpenTK.Platform.Windows
|
|
{
|
|
sealed class WinDisplayDeviceDriver : DisplayDeviceBase
|
|
{
|
|
readonly object display_lock = new object();
|
|
|
|
#region Constructors
|
|
|
|
public WinDisplayDeviceDriver()
|
|
{
|
|
RefreshDisplayDevices();
|
|
SystemEvents.DisplaySettingsChanged +=
|
|
HandleDisplaySettingsChanged;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IDisplayDeviceDriver Members
|
|
|
|
#region TryChangeResolution
|
|
|
|
public sealed override bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
|
|
{
|
|
DeviceMode mode = null;
|
|
|
|
if (resolution != null)
|
|
{
|
|
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_DISPLAYFREQUENCY;
|
|
}
|
|
|
|
return Constants.DISP_CHANGE_SUCCESSFUL ==
|
|
Functions.ChangeDisplaySettingsEx((string)device.Id, mode, IntPtr.Zero,
|
|
ChangeDisplaySettingsEnum.Fullscreen, IntPtr.Zero);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region TryRestoreResolution
|
|
|
|
public sealed override bool TryRestoreResolution(DisplayDevice device)
|
|
{
|
|
return TryChangeResolution(device, null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Private Members
|
|
|
|
#region RefreshDisplayDevices
|
|
|
|
public void RefreshDisplayDevices()
|
|
{
|
|
lock (display_lock)
|
|
{
|
|
// Store an array of the current available DisplayDevice objects.
|
|
// This is needed to preserve the original resolution.
|
|
DisplayDevice[] previousDevices = AvailableDevices.ToArray();
|
|
|
|
AvailableDevices.Clear();
|
|
|
|
// We save all necessary parameters in temporary variables
|
|
// and construct the device when every needed detail is available.
|
|
// The main DisplayDevice constructor adds the newly constructed device
|
|
// to the list of available devices.
|
|
DisplayDevice opentk_dev;
|
|
DisplayResolution opentk_dev_current_res = null;
|
|
List<DisplayResolution> opentk_dev_available_res = new List<DisplayResolution>();
|
|
bool opentk_dev_primary = false;
|
|
int device_count = 0, mode_count = 0;
|
|
|
|
// Get available video adapters and enumerate all monitors
|
|
WindowsDisplayDevice dev1 = new WindowsDisplayDevice(), dev2 = new WindowsDisplayDevice();
|
|
while (Functions.EnumDisplayDevices(null, device_count++, dev1, 0))
|
|
{
|
|
if ((dev1.StateFlags & DisplayDeviceStateFlags.AttachedToDesktop) == DisplayDeviceStateFlags.None)
|
|
continue;
|
|
|
|
DeviceMode monitor_mode = new DeviceMode();
|
|
|
|
// The second function should only be executed when the first one fails
|
|
// (e.g. when the monitor is disabled)
|
|
if (Functions.EnumDisplaySettingsEx(dev1.DeviceName.ToString(), DisplayModeSettingsEnum.CurrentSettings, monitor_mode, 0) ||
|
|
Functions.EnumDisplaySettingsEx(dev1.DeviceName.ToString(), DisplayModeSettingsEnum.RegistrySettings, monitor_mode, 0))
|
|
{
|
|
VerifyMode(dev1, monitor_mode);
|
|
|
|
float scale = GetScale(ref monitor_mode);
|
|
opentk_dev_current_res = new DisplayResolution(
|
|
(int)(monitor_mode.Position.X / scale), (int)(monitor_mode.Position.Y / scale),
|
|
(int)(monitor_mode.PelsWidth / scale), (int)(monitor_mode.PelsHeight / scale),
|
|
monitor_mode.BitsPerPel, monitor_mode.DisplayFrequency);
|
|
|
|
opentk_dev_primary =
|
|
(dev1.StateFlags & DisplayDeviceStateFlags.PrimaryDevice) != DisplayDeviceStateFlags.None;
|
|
}
|
|
|
|
opentk_dev_available_res.Clear();
|
|
mode_count = 0;
|
|
while (Functions.EnumDisplaySettingsEx(dev1.DeviceName.ToString(), mode_count++, monitor_mode, 0))
|
|
{
|
|
VerifyMode(dev1, monitor_mode);
|
|
|
|
float scale = GetScale(ref monitor_mode);
|
|
DisplayResolution res = new DisplayResolution(
|
|
(int)(monitor_mode.Position.X / scale), (int)(monitor_mode.Position.Y / scale),
|
|
(int)(monitor_mode.PelsWidth / scale), (int)(monitor_mode.PelsHeight / scale),
|
|
monitor_mode.BitsPerPel, monitor_mode.DisplayFrequency);
|
|
|
|
opentk_dev_available_res.Add(res);
|
|
}
|
|
|
|
// Construct the OpenTK DisplayDevice through the accumulated parameters.
|
|
// The constructor will automatically add the DisplayDevice to the list
|
|
// of available devices.
|
|
opentk_dev = new DisplayDevice(
|
|
opentk_dev_current_res,
|
|
opentk_dev_primary,
|
|
opentk_dev_available_res,
|
|
opentk_dev_current_res.Bounds,
|
|
dev1.DeviceName);
|
|
|
|
// Set the original resolution if the DisplayDevice was previously available.
|
|
foreach (DisplayDevice existingDevice in previousDevices)
|
|
if ((string)existingDevice.Id == (string)opentk_dev.Id)
|
|
opentk_dev.OriginalResolution = existingDevice.OriginalResolution;
|
|
|
|
AvailableDevices.Add(opentk_dev);
|
|
|
|
if (opentk_dev_primary)
|
|
Primary = opentk_dev;
|
|
|
|
Debug.Print("DisplayDevice {0} ({1}) supports {2} resolutions.",
|
|
device_count, opentk_dev.IsPrimary ? "primary" : "secondary", opentk_dev.AvailableResolutions.Count);
|
|
}
|
|
}
|
|
}
|
|
|
|
private float GetScale(ref DeviceMode monitor_mode)
|
|
{
|
|
float scale = 1.0f;
|
|
if ((monitor_mode.Fields & Constants.DM_LOGPIXELS) != 0)
|
|
{
|
|
scale = monitor_mode.LogPixels / 96.0f;
|
|
}
|
|
return scale;
|
|
}
|
|
|
|
static void VerifyMode(WindowsDisplayDevice device, DeviceMode mode)
|
|
{
|
|
if (mode.BitsPerPel == 0)
|
|
{
|
|
Debug.Print(
|
|
"[Warning] DisplayDevice '{0}' reported a mode with 0 bpp. Please create a bug report at http://www.opentk.com",
|
|
device.DeviceName.ToString());
|
|
mode.BitsPerPel = 32;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region HandleDisplaySettingsChanged
|
|
|
|
void HandleDisplaySettingsChanged(object sender, EventArgs e)
|
|
{
|
|
RefreshDisplayDevices();
|
|
}
|
|
|
|
#endregion
|
|
|
|
~WinDisplayDeviceDriver()
|
|
{
|
|
SystemEvents.DisplaySettingsChanged -=
|
|
HandleDisplaySettingsChanged;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|