summaryrefslogtreecommitdiff
path: root/source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.c')
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.c407
1 files changed, 407 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.c
new file mode 100644
index 0000000..7425d9a
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.c
@@ -0,0 +1,407 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_windowsvideo.h"
+#include "../../../include/SDL_assert.h"
+#include "../../../include/SDL_log.h"
+
+/* Windows CE compatibility */
+#ifndef CDS_FULLSCREEN
+#define CDS_FULLSCREEN 0
+#endif
+
+/* #define DEBUG_MODES */
+
+static void
+WIN_UpdateDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
+{
+ SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
+ HDC hdc;
+
+ data->DeviceMode.dmFields =
+ (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY |
+ DM_DISPLAYFLAGS);
+
+ if (index == ENUM_CURRENT_SETTINGS
+ && (hdc = CreateDC(deviceName, NULL, NULL, NULL)) != NULL) {
+ char bmi_data[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
+ LPBITMAPINFO bmi;
+ HBITMAP hbm;
+ int logical_width = GetDeviceCaps( hdc, HORZRES );
+ int logical_height = GetDeviceCaps( hdc, VERTRES );
+
+ mode->w = logical_width;
+ mode->h = logical_height;
+
+ SDL_zero(bmi_data);
+ bmi = (LPBITMAPINFO) bmi_data;
+ bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+
+ hbm = CreateCompatibleBitmap(hdc, 1, 1);
+ GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
+ GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
+ DeleteObject(hbm);
+ DeleteDC(hdc);
+ if (bmi->bmiHeader.biCompression == BI_BITFIELDS) {
+ switch (*(Uint32 *) bmi->bmiColors) {
+ case 0x00FF0000:
+ mode->format = SDL_PIXELFORMAT_RGB888;
+ break;
+ case 0x000000FF:
+ mode->format = SDL_PIXELFORMAT_BGR888;
+ break;
+ case 0xF800:
+ mode->format = SDL_PIXELFORMAT_RGB565;
+ break;
+ case 0x7C00:
+ mode->format = SDL_PIXELFORMAT_RGB555;
+ break;
+ }
+ } else if (bmi->bmiHeader.biBitCount == 8) {
+ mode->format = SDL_PIXELFORMAT_INDEX8;
+ } else if (bmi->bmiHeader.biBitCount == 4) {
+ mode->format = SDL_PIXELFORMAT_INDEX4LSB;
+ }
+ } else if (mode->format == SDL_PIXELFORMAT_UNKNOWN) {
+ /* FIXME: Can we tell what this will be? */
+ if ((data->DeviceMode.dmFields & DM_BITSPERPEL) == DM_BITSPERPEL) {
+ switch (data->DeviceMode.dmBitsPerPel) {
+ case 32:
+ mode->format = SDL_PIXELFORMAT_RGB888;
+ break;
+ case 24:
+ mode->format = SDL_PIXELFORMAT_RGB24;
+ break;
+ case 16:
+ mode->format = SDL_PIXELFORMAT_RGB565;
+ break;
+ case 15:
+ mode->format = SDL_PIXELFORMAT_RGB555;
+ break;
+ case 8:
+ mode->format = SDL_PIXELFORMAT_INDEX8;
+ break;
+ case 4:
+ mode->format = SDL_PIXELFORMAT_INDEX4LSB;
+ break;
+ }
+ }
+ }
+}
+
+static SDL_bool
+WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
+{
+ SDL_DisplayModeData *data;
+ DEVMODE devmode;
+
+ devmode.dmSize = sizeof(devmode);
+ devmode.dmDriverExtra = 0;
+ if (!EnumDisplaySettings(deviceName, index, &devmode)) {
+ return SDL_FALSE;
+ }
+
+ data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
+ if (!data) {
+ return SDL_FALSE;
+ }
+
+ mode->driverdata = data;
+ data->DeviceMode = devmode;
+
+ mode->format = SDL_PIXELFORMAT_UNKNOWN;
+ mode->w = data->DeviceMode.dmPelsWidth;
+ mode->h = data->DeviceMode.dmPelsHeight;
+ mode->refresh_rate = data->DeviceMode.dmDisplayFrequency;
+
+ /* Fill in the mode information */
+ WIN_UpdateDisplayMode(_this, deviceName, index, mode);
+ return SDL_TRUE;
+}
+
+static SDL_bool
+WIN_AddDisplay(_THIS, HMONITOR hMonitor, const MONITORINFOEX *info)
+{
+ SDL_VideoDisplay display;
+ SDL_DisplayData *displaydata;
+ SDL_DisplayMode mode;
+ DISPLAY_DEVICE device;
+
+#ifdef DEBUG_MODES
+ SDL_Log("Display: %s\n", WIN_StringToUTF8(info->szDevice));
+#endif
+
+ if (!WIN_GetDisplayMode(_this, info->szDevice, ENUM_CURRENT_SETTINGS, &mode)) {
+ return SDL_FALSE;
+ }
+
+ displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
+ if (!displaydata) {
+ return SDL_FALSE;
+ }
+ SDL_memcpy(displaydata->DeviceName, info->szDevice,
+ sizeof(displaydata->DeviceName));
+ displaydata->MonitorHandle = hMonitor;
+
+ SDL_zero(display);
+ device.cb = sizeof(device);
+ if (EnumDisplayDevices(info->szDevice, 0, &device, 0)) {
+ display.name = WIN_StringToUTF8(device.DeviceString);
+ }
+ display.desktop_mode = mode;
+ display.current_mode = mode;
+ display.driverdata = displaydata;
+ SDL_AddVideoDisplay(&display);
+ SDL_free(display.name);
+ return SDL_TRUE;
+}
+
+typedef struct _WIN_AddDisplaysData {
+ SDL_VideoDevice *video_device;
+ SDL_bool want_primary;
+} WIN_AddDisplaysData;
+
+static BOOL CALLBACK
+WIN_AddDisplaysCallback(HMONITOR hMonitor,
+ HDC hdcMonitor,
+ LPRECT lprcMonitor,
+ LPARAM dwData)
+{
+ WIN_AddDisplaysData *data = (WIN_AddDisplaysData*)dwData;
+ MONITORINFOEX info;
+
+ SDL_zero(info);
+ info.cbSize = sizeof(info);
+
+ if (GetMonitorInfo(hMonitor, (LPMONITORINFO)&info) != 0) {
+ const SDL_bool is_primary = ((info.dwFlags & MONITORINFOF_PRIMARY) == MONITORINFOF_PRIMARY);
+
+ if (is_primary == data->want_primary) {
+ WIN_AddDisplay(data->video_device, hMonitor, &info);
+ }
+ }
+
+ // continue enumeration
+ return TRUE;
+}
+
+static void
+WIN_AddDisplays(_THIS)
+{
+ WIN_AddDisplaysData callback_data;
+ callback_data.video_device = _this;
+
+ callback_data.want_primary = SDL_TRUE;
+ EnumDisplayMonitors(NULL, NULL, WIN_AddDisplaysCallback, (LPARAM)&callback_data);
+
+ callback_data.want_primary = SDL_FALSE;
+ EnumDisplayMonitors(NULL, NULL, WIN_AddDisplaysCallback, (LPARAM)&callback_data);
+}
+
+int
+WIN_InitModes(_THIS)
+{
+ WIN_AddDisplays(_this);
+
+ if (_this->num_displays == 0) {
+ return SDL_SetError("No displays available");
+ }
+ return 0;
+}
+
+int
+WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
+{
+ const SDL_DisplayData *data = (const SDL_DisplayData *)display->driverdata;
+ MONITORINFO minfo;
+ BOOL rc;
+
+ SDL_zero(minfo);
+ minfo.cbSize = sizeof(MONITORINFO);
+ rc = GetMonitorInfo(data->MonitorHandle, &minfo);
+
+ if (!rc) {
+ return SDL_SetError("Couldn't find monitor data");
+ }
+
+ rect->x = minfo.rcMonitor.left;
+ rect->y = minfo.rcMonitor.top;
+ rect->w = minfo.rcMonitor.right - minfo.rcMonitor.left;
+ rect->h = minfo.rcMonitor.bottom - minfo.rcMonitor.top;
+
+ return 0;
+}
+
+int
+WIN_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi_out, float * hdpi_out, float * vdpi_out)
+{
+ const SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
+ const SDL_VideoData *videodata = (SDL_VideoData *)display->device->driverdata;
+ float hdpi = 0, vdpi = 0, ddpi = 0;
+
+ if (videodata->GetDpiForMonitor) {
+ UINT hdpi_uint, vdpi_uint;
+ // Windows 8.1+ codepath
+ if (videodata->GetDpiForMonitor(displaydata->MonitorHandle, MDT_EFFECTIVE_DPI, &hdpi_uint, &vdpi_uint) == S_OK) {
+ // GetDpiForMonitor docs promise to return the same hdpi/vdpi
+ hdpi = (float)hdpi_uint;
+ vdpi = (float)hdpi_uint;
+ ddpi = (float)hdpi_uint;
+ } else {
+ return SDL_SetError("GetDpiForMonitor failed");
+ }
+ } else {
+ // Window 8.0 and below: same DPI for all monitors.
+ HDC hdc;
+ int hdpi_int, vdpi_int, hpoints, vpoints, hpix, vpix;
+ float hinches, vinches;
+
+ hdc = GetDC(NULL);
+ if (hdc == NULL) {
+ return SDL_SetError("GetDC failed");
+ }
+ hdpi_int = GetDeviceCaps(hdc, LOGPIXELSX);
+ vdpi_int = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(NULL, hdc);
+
+ hpoints = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ vpoints = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+
+ hpix = MulDiv(hpoints, hdpi_int, 96);
+ vpix = MulDiv(vpoints, vdpi_int, 96);
+
+ hinches = (float)hpoints / 96.0f;
+ vinches = (float)vpoints / 96.0f;
+
+ hdpi = (float)hdpi_int;
+ vdpi = (float)vdpi_int;
+ ddpi = SDL_ComputeDiagonalDPI(hpix, vpix, hinches, vinches);
+ }
+
+ if (ddpi_out) {
+ *ddpi_out = ddpi;
+ }
+ if (hdpi_out) {
+ *hdpi_out = hdpi;
+ }
+ if (vdpi_out) {
+ *vdpi_out = vdpi;
+ }
+
+ return ddpi != 0.0f ? 0 : SDL_SetError("Couldn't get DPI");
+}
+
+int
+WIN_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
+{
+ const SDL_DisplayData *data = (const SDL_DisplayData *)display->driverdata;
+ MONITORINFO minfo;
+ BOOL rc;
+
+ SDL_zero(minfo);
+ minfo.cbSize = sizeof(MONITORINFO);
+ rc = GetMonitorInfo(data->MonitorHandle, &minfo);
+
+ if (!rc) {
+ return SDL_SetError("Couldn't find monitor data");
+ }
+
+ rect->x = minfo.rcWork.left;
+ rect->y = minfo.rcWork.top;
+ rect->w = minfo.rcWork.right - minfo.rcWork.left;
+ rect->h = minfo.rcWork.bottom - minfo.rcWork.top;
+
+ return 0;
+}
+
+void
+WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
+{
+ SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
+ DWORD i;
+ SDL_DisplayMode mode;
+
+ for (i = 0;; ++i) {
+ if (!WIN_GetDisplayMode(_this, data->DeviceName, i, &mode)) {
+ break;
+ }
+ if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {
+ /* We don't support palettized modes now */
+ SDL_free(mode.driverdata);
+ continue;
+ }
+ if (mode.format != SDL_PIXELFORMAT_UNKNOWN) {
+ if (!SDL_AddDisplayMode(display, &mode)) {
+ SDL_free(mode.driverdata);
+ }
+ } else {
+ SDL_free(mode.driverdata);
+ }
+ }
+}
+
+int
+WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
+{
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
+ SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
+ LONG status;
+
+ if (mode->driverdata == display->desktop_mode.driverdata) {
+ status = ChangeDisplaySettingsEx(displaydata->DeviceName, NULL, NULL, CDS_FULLSCREEN, NULL);
+ } else {
+ status = ChangeDisplaySettingsEx(displaydata->DeviceName, &data->DeviceMode, NULL, CDS_FULLSCREEN, NULL);
+ }
+ if (status != DISP_CHANGE_SUCCESSFUL) {
+ const char *reason = "Unknown reason";
+ switch (status) {
+ case DISP_CHANGE_BADFLAGS:
+ reason = "DISP_CHANGE_BADFLAGS";
+ break;
+ case DISP_CHANGE_BADMODE:
+ reason = "DISP_CHANGE_BADMODE";
+ break;
+ case DISP_CHANGE_BADPARAM:
+ reason = "DISP_CHANGE_BADPARAM";
+ break;
+ case DISP_CHANGE_FAILED:
+ reason = "DISP_CHANGE_FAILED";
+ break;
+ }
+ return SDL_SetError("ChangeDisplaySettingsEx() failed: %s", reason);
+ }
+ EnumDisplaySettings(displaydata->DeviceName, ENUM_CURRENT_SETTINGS, &data->DeviceMode);
+ WIN_UpdateDisplayMode(_this, displaydata->DeviceName, ENUM_CURRENT_SETTINGS, mode);
+ return 0;
+}
+
+void
+WIN_QuitModes(_THIS)
+{
+ /* All fullscreen windows should have restored modes by now */
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */