Simplify DisplayDevice

This commit is contained in:
UnknownShadow200 2018-07-13 18:42:49 +10:00
parent 7effbe7932
commit db6c2c6140
6 changed files with 64 additions and 164 deletions

View File

@ -11,29 +11,6 @@ using System.Drawing;
namespace OpenTK { namespace OpenTK {
/// <summary> Contains information regarding a monitor's display resolution. </summary>
public class DisplayResolution {
internal DisplayResolution() { }
// Creates a new DisplayResolution object for the primary DisplayDevice.
internal DisplayResolution(int width, int height, int bitsPerPixel, int refreshRate) {
Width = width; Height = height;
BitsPerPixel = bitsPerPixel; RefreshRate = refreshRate;
}
/// <summary> The width of this display in pixels. </summary>
public int Width;
/// <summary> The height of this display in pixels. </summary>
public int Height;
/// <summary> The number of bits per pixel of this display. Typical values include 8, 16, 24 and 32. </summary>
public int BitsPerPixel;
/// <summary> The vertical refresh rate of this display. </summary>
public int RefreshRate;
}
/// <summary> Defines a display device on the underlying system. </summary> /// <summary> Defines a display device on the underlying system. </summary>
public class DisplayDevice { public class DisplayDevice {
// TODO: Add support for refresh rate queries and switches. // TODO: Add support for refresh rate queries and switches.
@ -41,51 +18,28 @@ namespace OpenTK {
// TODO: Add properties that describe the 'usable' size of the Display, i.e. the maximized size without the taskbar etc. // TODO: Add properties that describe the 'usable' size of the Display, i.e. the maximized size without the taskbar etc.
// TODO: Does not detect changes to primary device. // TODO: Does not detect changes to primary device.
DisplayResolution curResolution = new DisplayResolution();
Rectangle bounds;
static DisplayDevice() { static DisplayDevice() {
Platform.Factory.Default.InitDisplayDeviceDriver(); Platform.Factory.Default.InitDisplayDeviceDriver();
} }
internal DisplayDevice() { } internal DisplayDevice() { }
internal DisplayDevice(DisplayResolution curResolution, bool primary) { /// <summary> Bounds of this Display in pixel coordinates. </summary>
#warning "Consolidate current resolution with bounds? Can they fall out of sync right now?" public Rectangle Bounds;
this.curResolution = curResolution;
IsPrimary = primary;
this.bounds = new Rectangle(0, 0, curResolution.Width, curResolution.Height);
}
/// <summary> Returns bounds of this instance in pixel coordinates. </summary> /// <summary> Width of this display in pixels. </summary>
public Rectangle Bounds { public int Width { get { return Bounds.Width; } }
get { return bounds; }
internal set {
bounds = value;
curResolution.Height = bounds.Height;
curResolution.Width = bounds.Width;
}
}
/// <summary> Returns width of this display in pixels. </summary> /// <summary> Height of this display in pixels. </summary>
public int Width { get { return curResolution.Width; } } public int Height { get { return Bounds.Height; } }
/// <summary> Returns height of this display in pixels. </summary> /// <summary> Number of bits per pixel of this display. Typical values include 8, 16, 24 and 32. </summary>
public int Height { get { return curResolution.Height; } } public int BitsPerPixel;
/// <summary> Returns number of bits per pixel of this display. Typical values include 8, 16, 24 and 32. </summary> /// <summary> Vertical refresh rate of this display. </summary>
public int BitsPerPixel { public int RefreshRate;
get { return curResolution.BitsPerPixel; }
internal set { curResolution.BitsPerPixel = value; }
}
/// <summary> Returns vertical refresh rate of this display. </summary> /// <summary> Whether this Display is the primary Display in systems with multiple Displays.</summary>
public int RefreshRate {
get { return curResolution.RefreshRate; }
internal set { curResolution.RefreshRate = value; }
}
/// <summary> Returns whether this Display is the primary Display in systems with multiple Displays.</summary>
public bool IsPrimary { set { if (value) Primary = this; } } public bool IsPrimary { set { if (value) Primary = this; } }
/// <summary> Data unique to this Display. </summary> /// <summary> Data unique to this Display. </summary>

View File

@ -7,12 +7,6 @@ namespace OpenTK.Platform.MacOS {
internal static IntPtr MainDisplay; internal static IntPtr MainDisplay;
internal unsafe static void Init() { internal unsafe static void Init() {
// To minimize the need to add static methods to OpenTK.Graphics.DisplayDevice
// we only allow settings to be set through its constructor.
// Thus, 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.
const int maxDisplayCount = 20; const int maxDisplayCount = 20;
IntPtr[] displays = new IntPtr[maxDisplayCount]; IntPtr[] displays = new IntPtr[maxDisplayCount];
int displayCount; int displayCount;
@ -38,29 +32,26 @@ namespace OpenTK.Platform.MacOS {
int modesCount = CF.CFArrayGetCount(modes); int modesCount = CF.CFArrayGetCount(modes);
Debug.Print("Supports {0} display modes.", modesCount); Debug.Print("Supports {0} display modes.", modesCount);
DisplayResolution opentk_curRes = null; DisplayDevice device = new DisplayDevice();
IntPtr curMode = CG.CGDisplayCurrentMode(curDisplay); IntPtr curMode = CG.CGDisplayCurrentMode(curDisplay);
for (int j = 0; j < modesCount; j++) { for (int j = 0; j < modesCount; j++) {
IntPtr mode = CF.CFArrayGetValueAtIndex(modes, j); IntPtr mode = CF.CFArrayGetValueAtIndex(modes, j);
if (mode != curMode) continue;
int width = (int)CF.DictGetNumber(mode, "Width");
int height = (int)CF.DictGetNumber(mode, "Height"); device.Bounds.Width = (int)CF.DictGetNumber(mode, "Width");
int bpp = (int)CF.DictGetNumber(mode, "BitsPerPixel"); device.Bounds.Height = (int)CF.DictGetNumber(mode, "Height");
int freq = (int)CF.DictGetNumber(mode, "RefreshRate"); device.BitsPerPixel = (int)CF.DictGetNumber(mode, "BitsPerPixel");
device.RefreshRate = (int)CF.DictGetNumber(mode, "RefreshRate");
if (mode == curMode) {
opentk_curRes = new DisplayResolution(width, height, bpp, freq);
}
} }
HIRect bounds = CG.CGDisplayBounds(curDisplay); HIRect bounds = CG.CGDisplayBounds(curDisplay);
Rectangle newRect = new Rectangle( device.Bounds = new Rectangle(
(int)bounds.Origin.X, (int)bounds.Origin.Y, (int)bounds.Size.X, (int)bounds.Size.Y); (int)bounds.Origin.X, (int)bounds.Origin.Y, (int)bounds.Size.X, (int)bounds.Size.Y);
Debug.Print("Display {0} bounds: {1}", i, newRect); Debug.Print("Display {0} bounds: {1}", i, device.Bounds);
DisplayDevice opentk_dev = new DisplayDevice(opentk_curRes, primary); device.Metadata = curDisplay;
opentk_dev.Bounds = newRect; device.IsPrimary = primary;
opentk_dev.Metadata = curDisplay;
} }
} }
} }

View File

@ -15,42 +15,29 @@ namespace OpenTK.Platform.Windows {
/// <summary>Queries available display devices and display resolutions.</summary> /// <summary>Queries available display devices and display resolutions.</summary>
internal static void Init() { internal static void Init() {
// To minimize the need to add static methods to OpenTK.Graphics.DisplayDevice
// we only allow settings to be set through its constructor.
// Thus, 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.
DisplayResolution currentRes = null;
bool devPrimary = false;
int deviceNum = 0;
// Get available video adapters and enumerate all monitors // Get available video adapters and enumerate all monitors
WindowsDisplayDevice winDev = new WindowsDisplayDevice(); int displayNum = 0;
while (API.EnumDisplayDevices(null, deviceNum++, winDev, 0)) { WindowsDisplayDevice display = new WindowsDisplayDevice();
if ((winDev.StateFlags & DisplayDeviceStateFlags.AttachedToDesktop) == 0)
continue; while (API.EnumDisplayDevices(null, displayNum++, display, 0)) {
if ((display.StateFlags & DisplayDeviceStateFlags.AttachedToDesktop) == 0) continue;
DeviceMode mode = new DeviceMode(); DeviceMode mode = new DeviceMode();
// The second function should only be executed when the first one fails (e.g. when the monitor is disabled) // The second function should only be executed when the first one fails (e.g. when the monitor is disabled)
if (API.EnumDisplaySettings(winDev.DeviceName, (int)DisplayModeSettings.Current, mode) || if (API.EnumDisplaySettings(display.DeviceName, (int)DisplayModeSettings.Current, mode) ||
API.EnumDisplaySettings(winDev.DeviceName, (int)DisplayModeSettings.Registry, mode)) { API.EnumDisplaySettings(display.DeviceName, (int)DisplayModeSettings.Registry, mode)) {
if (mode.BitsPerPel > 0) { } else {
currentRes = new DisplayResolution( mode.BitsPerPel = 0;
mode.PelsWidth, mode.PelsHeight,
mode.BitsPerPel, mode.DisplayFrequency);
devPrimary = (winDev.StateFlags & DisplayDeviceStateFlags.PrimaryDevice) != 0;
}
} }
// This device has no valid resolution, ignore it if (mode.BitsPerPel == 0) continue;
if (currentRes == null) continue; DisplayDevice device = new DisplayDevice();
// Construct the OpenTK DisplayDevice through the accumulated parameters. device.Bounds.Width = mode.PelsWidth;
// The constructor automatically adds the DisplayDevice to the list of available devices. device.Bounds.Height = mode.PelsHeight;
DisplayDevice device = new DisplayDevice(currentRes, devPrimary); device.BitsPerPixel = mode.BitsPerPel;
currentRes = null; device.RefreshRate = mode.DisplayFrequency;
device.IsPrimary = (display.StateFlags & DisplayDeviceStateFlags.PrimaryDevice) != 0;
} }
} }
} }

View File

@ -1,33 +1,10 @@
#include "DisplayDevice.h" #include "DisplayDevice.h"
DisplayResolution DisplayResolution_Make(Int32 width, Int32 height, Int32 bitsPerPixel, Int32 refreshRate) {
DisplayResolution res;
res.Width = width; res.Height = height;
res.BitsPerPixel = bitsPerPixel; res.RefreshRate = refreshRate;
return res;
}
DisplayDevice DisplayDevice_Make(DisplayResolution* curResolution) {
DisplayDevice device;
device.CurResolution = *curResolution;
device.Bounds = Rectangle2D_Make(0, 0, curResolution->Width, curResolution->Height);
device.Metadata = NULL;
return device;
}
void DisplayDevice_SetBounds(DisplayDevice* device, Rectangle2D* bounds) {
device->Bounds = *bounds;
device->CurResolution.Width = bounds->Width;
device->CurResolution.Height = bounds->Height;
}
#if !CC_BUILD_D3D9 #if !CC_BUILD_D3D9
ColorFormat ColorFormat_FromBPP(Int32 bpp) { ColorFormat ColorFormat_FromBPP(Int32 bpp) {
ColorFormat format; ColorFormat format = { 0 };
format.R = 0; format.G = 0; format.B = 0; format.A = 0;
format.BitsPerPixel = bpp; format.BitsPerPixel = bpp;
format.IsIndexed = false;
UInt8 rba; UInt8 rba;
switch (bpp) { switch (bpp) {
@ -81,7 +58,7 @@ GraphicsMode GraphicsMode_Make(ColorFormat color, UInt8 depth, UInt8 stencil, UI
} }
GraphicsMode GraphicsMode_MakeDefault(void) { GraphicsMode GraphicsMode_MakeDefault(void) {
Int32 bpp = DisplayDevice_Default.CurResolution.BitsPerPixel; Int32 bpp = DisplayDevice_Default.BitsPerPixel;
ColorFormat format = ColorFormat_FromBPP(bpp); ColorFormat format = ColorFormat_FromBPP(bpp);
return GraphicsMode_Make(format, 24, 0, 2); return GraphicsMode_Make(format, 24, 0, 2);
} }

View File

@ -12,22 +12,13 @@
* See license.txt for licensing detailed licensing details. * See license.txt for licensing detailed licensing details.
*/ */
typedef struct DisplayResolution_ { typedef struct DisplayDevice_ {
Int32 Width, Height, BitsPerPixel; Int32 Width, Height, BitsPerPixel;
/* The vertical refresh rate of this display. */ /* The vertical refresh rate of this display. */
Int32 RefreshRate; Int32 RefreshRate;
} DisplayResolution;
DisplayResolution DisplayResolution_Make(Int32 width, Int32 height, Int32 bitsPerPixel, Int32 refreshRate);
typedef struct DisplayDevice_ {
DisplayResolution CurResolution;
Rectangle2D Bounds; Rectangle2D Bounds;
void* Metadata; void* Metadata;
} DisplayDevice; } DisplayDevice;
DisplayDevice DisplayDevice_Make(DisplayResolution* curResolution);
void DisplayDevice_SetBounds(DisplayDevice* device, Rectangle2D* bounds);
/* The primary / default / main display device. */ /* The primary / default / main display device. */
DisplayDevice DisplayDevice_Default; DisplayDevice DisplayDevice_Default;

View File

@ -43,33 +43,33 @@ void Platform_Init(void) {
ReturnCode wsaResult = WSAStartup(MAKEWORD(2, 2), &wsaData); ReturnCode wsaResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
ErrorHandler_CheckOrFail(wsaResult, "WSAStartup failed"); ErrorHandler_CheckOrFail(wsaResult, "WSAStartup failed");
UInt32 deviceNum = 0;
/* Get available video adapters and enumerate all monitors */ /* Get available video adapters and enumerate all monitors */
DISPLAY_DEVICEW device = { 0 }; UInt32 displayNum = 0;
device.cb = sizeof(DISPLAY_DEVICEW); DISPLAY_DEVICEW display = { 0 }; display.cb = sizeof(DISPLAY_DEVICEW);
while (EnumDisplayDevicesW(NULL, deviceNum, &device, 0)) { while (EnumDisplayDevicesW(NULL, displayNum, &display, 0)) {
deviceNum++; displayNum++;
if ((device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == 0) continue; if ((display.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == 0) continue;
bool devPrimary = false; DEVMODEW mode = { 0 }; mode.dmSize = sizeof(DEVMODEW);
DisplayResolution resolution = { 0 };
DEVMODEW mode = { 0 };
mode.dmSize = sizeof(DEVMODEW);
/* The second function should only be executed when the first one fails (e.g. when the monitor is disabled) */ /* The second function should only be executed when the first one fails (e.g. when the monitor is disabled) */
if (EnumDisplaySettingsW(device.DeviceName, ENUM_CURRENT_SETTINGS, &mode) || if (EnumDisplaySettingsW(display.DeviceName, ENUM_CURRENT_SETTINGS, &mode) ||
EnumDisplaySettingsW(device.DeviceName, ENUM_REGISTRY_SETTINGS, &mode)) { EnumDisplaySettingsW(display.DeviceName, ENUM_REGISTRY_SETTINGS, &mode)) {
if (mode.dmBitsPerPel > 0) { } else {
resolution = DisplayResolution_Make(mode.dmPelsWidth, mode.dmPelsHeight, mode.dmBitsPerPel = 0;
mode.dmBitsPerPel, mode.dmDisplayFrequency);
devPrimary = (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) != 0;
}
} }
/* This device has no valid resolution, ignore it */ /* This device has no valid resolution, ignore it */
if (resolution.Width == 0 && resolution.Height == 0) continue; if (mode.dmBitsPerPel == 0) continue;
if (!devPrimary) continue; bool isPrimary = (display.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) != 0;
DisplayDevice_Default = DisplayDevice_Make(&resolution); if (!isPrimary) continue;
DisplayDevice device = { 0 };
device.Bounds.Width = mode.dmPelsWidth;
device.Bounds.Height = mode.dmPelsHeight;
device.BitsPerPixel = mode.dmBitsPerPel;
device.RefreshRate = mode.dmDisplayFrequency;
DisplayDevice_Default = device;
} }
} }