From 30f41c02aec763d32e62351452da9ef582bc3472 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 6 Mar 2026 13:30:59 -0800 Subject: Move contrib libraries to contrib repo --- .../SDL-3.2.8/src/video/windows/SDL_windowsmodes.c | 927 --------------------- 1 file changed, 927 deletions(-) delete mode 100644 contrib/SDL-3.2.8/src/video/windows/SDL_windowsmodes.c (limited to 'contrib/SDL-3.2.8/src/video/windows/SDL_windowsmodes.c') diff --git a/contrib/SDL-3.2.8/src/video/windows/SDL_windowsmodes.c b/contrib/SDL-3.2.8/src/video/windows/SDL_windowsmodes.c deleted file mode 100644 index 77ebab2..0000000 --- a/contrib/SDL-3.2.8/src/video/windows/SDL_windowsmodes.c +++ /dev/null @@ -1,927 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 defined(SDL_VIDEO_DRIVER_WINDOWS) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) - -#include "SDL_windowsvideo.h" -#include "../../events/SDL_displayevents_c.h" - -#ifdef HAVE_DXGI1_6_H -#define COBJMACROS -#include -#endif - -// Windows CE compatibility -#ifndef CDS_FULLSCREEN -#define CDS_FULLSCREEN 0 -#endif - -// #define DEBUG_MODES -// #define HIGHDPI_DEBUG_VERBOSE - -static void WIN_UpdateDisplayMode(SDL_VideoDevice *_this, LPCWSTR deviceName, DWORD index, SDL_DisplayMode *mode) -{ - SDL_DisplayModeData *data = (SDL_DisplayModeData *)mode->internal; - HDC hdc; - - data->DeviceMode.dmFields = (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS); - - // NOLINTNEXTLINE(bugprone-assignment-in-if-condition): No simple way to extract the assignment - if (index == ENUM_CURRENT_SETTINGS && (hdc = CreateDC(deviceName, NULL, NULL, NULL)) != NULL) { - char bmi_data[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)]; - LPBITMAPINFO bmi; - HBITMAP hbm; - - SDL_zeroa(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_XRGB8888; - break; - case 0x000000FF: - mode->format = SDL_PIXELFORMAT_XBGR8888; - break; - case 0xF800: - mode->format = SDL_PIXELFORMAT_RGB565; - break; - case 0x7C00: - mode->format = SDL_PIXELFORMAT_XRGB1555; - break; - } - } else if (bmi->bmiHeader.biCompression == BI_RGB) { - if (bmi->bmiHeader.biBitCount == 24) { - mode->format = SDL_PIXELFORMAT_RGB24; - } 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_XRGB8888; - break; - case 24: - mode->format = SDL_PIXELFORMAT_RGB24; - break; - case 16: - mode->format = SDL_PIXELFORMAT_RGB565; - break; - case 15: - mode->format = SDL_PIXELFORMAT_XRGB1555; - break; - case 8: - mode->format = SDL_PIXELFORMAT_INDEX8; - break; - case 4: - mode->format = SDL_PIXELFORMAT_INDEX4LSB; - break; - } - } - } -} - -static void *WIN_GetDXGIOutput(SDL_VideoDevice *_this, const WCHAR *DeviceName) -{ - void *result = NULL; - -#ifdef HAVE_DXGI_H - const SDL_VideoData *videodata = (const SDL_VideoData *)_this->internal; - int nAdapter, nOutput; - IDXGIAdapter *pDXGIAdapter; - IDXGIOutput *pDXGIOutput; - - if (!videodata->pDXGIFactory) { - return NULL; - } - - nAdapter = 0; - while (!result && SUCCEEDED(IDXGIFactory_EnumAdapters(videodata->pDXGIFactory, nAdapter, &pDXGIAdapter))) { - nOutput = 0; - while (!result && SUCCEEDED(IDXGIAdapter_EnumOutputs(pDXGIAdapter, nOutput, &pDXGIOutput))) { - DXGI_OUTPUT_DESC outputDesc; - if (SUCCEEDED(IDXGIOutput_GetDesc(pDXGIOutput, &outputDesc))) { - if (SDL_wcscmp(outputDesc.DeviceName, DeviceName) == 0) { - result = pDXGIOutput; - } - } - if (pDXGIOutput != result) { - IDXGIOutput_Release(pDXGIOutput); - } - nOutput++; - } - IDXGIAdapter_Release(pDXGIAdapter); - nAdapter++; - } -#endif - return result; -} - -static void WIN_ReleaseDXGIOutput(void *dxgi_output) -{ -#ifdef HAVE_DXGI_H - IDXGIOutput *pDXGIOutput = (IDXGIOutput *)dxgi_output; - - if (pDXGIOutput) { - IDXGIOutput_Release(pDXGIOutput); - } -#endif -} - -static SDL_DisplayOrientation WIN_GetNaturalOrientation(DEVMODE *mode) -{ - int width = mode->dmPelsWidth; - int height = mode->dmPelsHeight; - - // Use unrotated width/height to guess orientation - if (mode->dmDisplayOrientation == DMDO_90 || mode->dmDisplayOrientation == DMDO_270) { - int temp = width; - width = height; - height = temp; - } - - if (width >= height) { - return SDL_ORIENTATION_LANDSCAPE; - } else { - return SDL_ORIENTATION_PORTRAIT; - } -} - -static SDL_DisplayOrientation WIN_GetDisplayOrientation(DEVMODE *mode) -{ - if (WIN_GetNaturalOrientation(mode) == SDL_ORIENTATION_LANDSCAPE) { - switch (mode->dmDisplayOrientation) { - case DMDO_DEFAULT: - return SDL_ORIENTATION_LANDSCAPE; - case DMDO_90: - return SDL_ORIENTATION_PORTRAIT; - case DMDO_180: - return SDL_ORIENTATION_LANDSCAPE_FLIPPED; - case DMDO_270: - return SDL_ORIENTATION_PORTRAIT_FLIPPED; - default: - return SDL_ORIENTATION_UNKNOWN; - } - } else { - switch (mode->dmDisplayOrientation) { - case DMDO_DEFAULT: - return SDL_ORIENTATION_PORTRAIT; - case DMDO_90: - return SDL_ORIENTATION_LANDSCAPE_FLIPPED; - case DMDO_180: - return SDL_ORIENTATION_PORTRAIT_FLIPPED; - case DMDO_270: - return SDL_ORIENTATION_LANDSCAPE; - default: - return SDL_ORIENTATION_UNKNOWN; - } - } -} - -static void WIN_GetRefreshRate(void *dxgi_output, DEVMODE *mode, int *numerator, int *denominator) -{ - // We're not currently using DXGI to query display modes, so fake NTSC timings - switch (mode->dmDisplayFrequency) { - case 119: - case 59: - case 29: - *numerator = (mode->dmDisplayFrequency + 1) * 1000; - *denominator = 1001; - break; - default: - *numerator = mode->dmDisplayFrequency; - *denominator = 1; - break; - } - -#ifdef HAVE_DXGI_H - if (dxgi_output) { - IDXGIOutput *pDXGIOutput = (IDXGIOutput *)dxgi_output; - DXGI_MODE_DESC modeToMatch; - DXGI_MODE_DESC closestMatch; - - SDL_zero(modeToMatch); - modeToMatch.Width = mode->dmPelsWidth; - modeToMatch.Height = mode->dmPelsHeight; - modeToMatch.RefreshRate.Numerator = *numerator; - modeToMatch.RefreshRate.Denominator = *denominator; - modeToMatch.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - - if (SUCCEEDED(IDXGIOutput_FindClosestMatchingMode(pDXGIOutput, &modeToMatch, &closestMatch, NULL))) { - *numerator = closestMatch.RefreshRate.Numerator; - *denominator = closestMatch.RefreshRate.Denominator; - } - } -#endif // HAVE_DXGI_H -} - -static float WIN_GetContentScale(SDL_VideoDevice *_this, HMONITOR hMonitor) -{ - const SDL_VideoData *videodata = (const SDL_VideoData *)_this->internal; - int dpi = 0; - - if (videodata->GetDpiForMonitor) { - UINT hdpi_uint, vdpi_uint; - if (videodata->GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &hdpi_uint, &vdpi_uint) == S_OK) { - dpi = (int)hdpi_uint; - } - } - if (dpi == 0) { - // Window 8.0 and below: same DPI for all monitors - HDC hdc = GetDC(NULL); - if (hdc) { - dpi = GetDeviceCaps(hdc, LOGPIXELSX); - ReleaseDC(NULL, hdc); - } - } - if (dpi == 0) { - // Safe default - dpi = USER_DEFAULT_SCREEN_DPI; - } - return dpi / (float)USER_DEFAULT_SCREEN_DPI; -} - -static bool WIN_GetDisplayMode(SDL_VideoDevice *_this, void *dxgi_output, HMONITOR hMonitor, LPCWSTR deviceName, DWORD index, SDL_DisplayMode *mode, SDL_DisplayOrientation *natural_orientation, SDL_DisplayOrientation *current_orientation) -{ - SDL_DisplayModeData *data; - DEVMODE devmode; - - devmode.dmSize = sizeof(devmode); - devmode.dmDriverExtra = 0; - if (!EnumDisplaySettingsW(deviceName, index, &devmode)) { - return false; - } - - data = (SDL_DisplayModeData *)SDL_malloc(sizeof(*data)); - if (!data) { - return false; - } - - SDL_zerop(mode); - mode->internal = data; - data->DeviceMode = devmode; - - mode->format = SDL_PIXELFORMAT_UNKNOWN; - mode->w = data->DeviceMode.dmPelsWidth; - mode->h = data->DeviceMode.dmPelsHeight; - WIN_GetRefreshRate(dxgi_output, &data->DeviceMode, &mode->refresh_rate_numerator, &mode->refresh_rate_denominator); - - // Fill in the mode information - WIN_UpdateDisplayMode(_this, deviceName, index, mode); - - if (natural_orientation) { - *natural_orientation = WIN_GetNaturalOrientation(&devmode); - } - if (current_orientation) { - *current_orientation = WIN_GetDisplayOrientation(&devmode); - } - - return true; -} - -static char *WIN_GetDisplayNameVista(SDL_VideoData *videodata, const WCHAR *deviceName) -{ - DISPLAYCONFIG_PATH_INFO *paths = NULL; - DISPLAYCONFIG_MODE_INFO *modes = NULL; - char *result = NULL; - UINT32 pathCount = 0; - UINT32 modeCount = 0; - UINT32 i; - LONG rc; - - if (!videodata->GetDisplayConfigBufferSizes || !videodata->QueryDisplayConfig || !videodata->DisplayConfigGetDeviceInfo) { - return NULL; - } - - do { - rc = videodata->GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); - if (rc != ERROR_SUCCESS) { - goto WIN_GetDisplayNameVista_failed; - } - - SDL_free(paths); - SDL_free(modes); - - paths = (DISPLAYCONFIG_PATH_INFO *)SDL_malloc(sizeof(DISPLAYCONFIG_PATH_INFO) * pathCount); - modes = (DISPLAYCONFIG_MODE_INFO *)SDL_malloc(sizeof(DISPLAYCONFIG_MODE_INFO) * modeCount); - if ((!paths) || (!modes)) { - goto WIN_GetDisplayNameVista_failed; - } - - rc = videodata->QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths, &modeCount, modes, 0); - } while (rc == ERROR_INSUFFICIENT_BUFFER); - - if (rc == ERROR_SUCCESS) { - for (i = 0; i < pathCount; i++) { - DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName; - DISPLAYCONFIG_TARGET_DEVICE_NAME targetName; - - SDL_zero(sourceName); - sourceName.header.adapterId = paths[i].targetInfo.adapterId; - sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; - sourceName.header.size = sizeof(sourceName); - sourceName.header.id = paths[i].sourceInfo.id; - rc = videodata->DisplayConfigGetDeviceInfo(&sourceName.header); - if (rc != ERROR_SUCCESS) { - break; - } else if (SDL_wcscmp(deviceName, sourceName.viewGdiDeviceName) != 0) { - continue; - } - - SDL_zero(targetName); - targetName.header.adapterId = paths[i].targetInfo.adapterId; - targetName.header.id = paths[i].targetInfo.id; - targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; - targetName.header.size = sizeof(targetName); - rc = videodata->DisplayConfigGetDeviceInfo(&targetName.header); - if (rc == ERROR_SUCCESS) { - result = WIN_StringToUTF8W(targetName.monitorFriendlyDeviceName); - /* if we got an empty string, treat it as failure so we'll fallback - to getting the generic name. */ - if (result && (*result == '\0')) { - SDL_free(result); - result = NULL; - } - } - break; - } - } - - SDL_free(paths); - SDL_free(modes); - return result; - -WIN_GetDisplayNameVista_failed: - SDL_free(result); - SDL_free(paths); - SDL_free(modes); - return NULL; -} - -#ifdef HAVE_DXGI1_6_H -static bool WIN_GetMonitorDESC1(HMONITOR hMonitor, DXGI_OUTPUT_DESC1 *desc) -{ - typedef HRESULT (WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory); - PFN_CREATE_DXGI_FACTORY CreateDXGIFactoryFunc = NULL; - SDL_SharedObject *hDXGIMod = NULL; - bool found = false; - - hDXGIMod = SDL_LoadObject("dxgi.dll"); - if (hDXGIMod) { - CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY)SDL_LoadFunction(hDXGIMod, "CreateDXGIFactory1"); - } - if (CreateDXGIFactoryFunc) { - static const GUID SDL_IID_IDXGIFactory1 = { 0x770aae78, 0xf26f, 0x4dba, { 0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87 } }; - static const GUID SDL_IID_IDXGIOutput6 = { 0x068346e8, 0xaaec, 0x4b84, { 0xad, 0xd7, 0x13, 0x7f, 0x51, 0x3f, 0x77, 0xa1 } }; - IDXGIFactory1 *dxgiFactory; - - if (SUCCEEDED(CreateDXGIFactoryFunc(&SDL_IID_IDXGIFactory1, (void **)&dxgiFactory))) { - IDXGIAdapter1 *dxgiAdapter; - UINT adapter = 0; - while (!found && SUCCEEDED(IDXGIFactory1_EnumAdapters1(dxgiFactory, adapter, &dxgiAdapter))) { - IDXGIOutput *dxgiOutput; - UINT output = 0; - while (!found && SUCCEEDED(IDXGIAdapter1_EnumOutputs(dxgiAdapter, output, &dxgiOutput))) { - IDXGIOutput6 *dxgiOutput6; - if (SUCCEEDED(IDXGIOutput_QueryInterface(dxgiOutput, &SDL_IID_IDXGIOutput6, (void **)&dxgiOutput6))) { - if (SUCCEEDED(IDXGIOutput6_GetDesc1(dxgiOutput6, desc))) { - if (desc->Monitor == hMonitor) { - found = true; - } - } - IDXGIOutput6_Release(dxgiOutput6); - } - IDXGIOutput_Release(dxgiOutput); - ++output; - } - IDXGIAdapter1_Release(dxgiAdapter); - ++adapter; - } - IDXGIFactory2_Release(dxgiFactory); - } - } - if (hDXGIMod) { - SDL_UnloadObject(hDXGIMod); - } - return found; -} - -static bool WIN_GetMonitorPathInfo(SDL_VideoData *videodata, HMONITOR hMonitor, DISPLAYCONFIG_PATH_INFO *path_info) -{ - LONG result; - MONITORINFOEXW view_info; - UINT32 i; - UINT32 num_path_array_elements = 0; - UINT32 num_mode_info_array_elements = 0; - DISPLAYCONFIG_PATH_INFO *path_infos = NULL, *new_path_infos; - DISPLAYCONFIG_MODE_INFO *mode_infos = NULL, *new_mode_infos; - bool found = false; - - if (!videodata->GetDisplayConfigBufferSizes || !videodata->QueryDisplayConfig || !videodata->DisplayConfigGetDeviceInfo) { - return false; - } - - SDL_zero(view_info); - view_info.cbSize = sizeof(view_info); - if (!GetMonitorInfoW(hMonitor, (MONITORINFO *)&view_info)) { - goto done; - } - - do { - if (videodata->GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &num_path_array_elements, &num_mode_info_array_elements) != ERROR_SUCCESS) { - SDL_free(path_infos); - SDL_free(mode_infos); - return false; - } - - new_path_infos = (DISPLAYCONFIG_PATH_INFO *)SDL_realloc(path_infos, num_path_array_elements * sizeof(*path_infos)); - if (!new_path_infos) { - goto done; - } - path_infos = new_path_infos; - - new_mode_infos = (DISPLAYCONFIG_MODE_INFO *)SDL_realloc(mode_infos, num_mode_info_array_elements * sizeof(*mode_infos)); - if (!new_mode_infos) { - goto done; - } - mode_infos = new_mode_infos; - - result = videodata->QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &num_path_array_elements, path_infos, &num_mode_info_array_elements, mode_infos, NULL); - - } while (result == ERROR_INSUFFICIENT_BUFFER); - - if (result == ERROR_SUCCESS) { - for (i = 0; i < num_path_array_elements; ++i) { - DISPLAYCONFIG_SOURCE_DEVICE_NAME device_name; - - SDL_zero(device_name); - device_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; - device_name.header.size = sizeof(device_name); - device_name.header.adapterId = path_infos[i].sourceInfo.adapterId; - device_name.header.id = path_infos[i].sourceInfo.id; - if (videodata->DisplayConfigGetDeviceInfo(&device_name.header) == ERROR_SUCCESS) { - if (SDL_wcscmp(view_info.szDevice, device_name.viewGdiDeviceName) == 0) { - SDL_copyp(path_info, &path_infos[i]); - found = true; - break; - } - } - } - } - -done: - SDL_free(path_infos); - SDL_free(mode_infos); - - return found; -} - -static float WIN_GetSDRWhitePoint(SDL_VideoDevice *_this, HMONITOR hMonitor) -{ - DISPLAYCONFIG_PATH_INFO path_info; - SDL_VideoData *videodata = _this->internal; - float SDR_white_level = 1.0f; - - if (WIN_GetMonitorPathInfo(videodata, hMonitor, &path_info)) { - /* workarounds for https://github.com/libsdl-org/SDL/issues/11193 */ - struct SDL_DISPLAYCONFIG_SDR_WHITE_LEVEL { - DISPLAYCONFIG_DEVICE_INFO_HEADER header; - ULONG SDRWhiteLevel; - } white_level; - #define DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL 11 - - SDL_zero(white_level); - white_level.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL; - white_level.header.size = sizeof(white_level); - white_level.header.adapterId = path_info.targetInfo.adapterId; - white_level.header.id = path_info.targetInfo.id; - // WIN_GetMonitorPathInfo() succeeded: DisplayConfigGetDeviceInfo is not NULL - if (videodata->DisplayConfigGetDeviceInfo(&white_level.header) == ERROR_SUCCESS && - white_level.SDRWhiteLevel > 0) { - SDR_white_level = (white_level.SDRWhiteLevel / 1000.0f); - } - } - return SDR_white_level; -} - -static void WIN_GetHDRProperties(SDL_VideoDevice *_this, HMONITOR hMonitor, SDL_HDROutputProperties *HDR) -{ - DXGI_OUTPUT_DESC1 desc; - - SDL_zerop(HDR); - - if (WIN_GetMonitorDESC1(hMonitor, &desc)) { - if (desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) { - HDR->SDR_white_level = WIN_GetSDRWhitePoint(_this, hMonitor); - HDR->HDR_headroom = (desc.MaxLuminance / 80.0f) / HDR->SDR_white_level; - } - } -} -#endif // HAVE_DXGI1_6_H - -static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONITORINFOEXW *info, int *display_index) -{ - int i, index = *display_index; - SDL_VideoDisplay display; - SDL_DisplayData *displaydata; - void *dxgi_output = NULL; - SDL_DisplayMode mode; - SDL_DisplayOrientation natural_orientation; - SDL_DisplayOrientation current_orientation; - float content_scale = WIN_GetContentScale(_this, hMonitor); - -#ifdef DEBUG_MODES - SDL_Log("Display: %s", WIN_StringToUTF8W(info->szDevice)); -#endif - - dxgi_output = WIN_GetDXGIOutput(_this, info->szDevice); - bool found = WIN_GetDisplayMode(_this, dxgi_output, hMonitor, info->szDevice, ENUM_CURRENT_SETTINGS, &mode, &natural_orientation, ¤t_orientation); - WIN_ReleaseDXGIOutput(dxgi_output); - if (!found) { - return; - } - - // Prevent adding duplicate displays. Do this after we know the display is - // ready to be added to allow any displays that we can't fully query to be - // removed - for (i = 0; i < _this->num_displays; ++i) { - SDL_DisplayData *internal = _this->displays[i]->internal; - if (SDL_wcscmp(internal->DeviceName, info->szDevice) == 0) { - bool moved = (index != i); - bool changed_bounds = false; - - if (internal->state != DisplayRemoved) { - // We've already enumerated this display, don't move it - return; - } - - if (index >= _this->num_displays) { - // This should never happen due to the check above, but just in case... - return; - } - - if (moved) { - SDL_VideoDisplay *tmp; - - tmp = _this->displays[index]; - _this->displays[index] = _this->displays[i]; - _this->displays[i] = tmp; - i = index; - } - - internal->MonitorHandle = hMonitor; - internal->state = DisplayUnchanged; - - if (!_this->setting_display_mode) { - SDL_VideoDisplay *existing_display = _this->displays[i]; - SDL_Rect bounds; - - SDL_ResetFullscreenDisplayModes(existing_display); - SDL_SetDesktopDisplayMode(existing_display, &mode); - if (WIN_GetDisplayBounds(_this, existing_display, &bounds) && - SDL_memcmp(&internal->bounds, &bounds, sizeof(bounds)) != 0) { - changed_bounds = true; - SDL_copyp(&internal->bounds, &bounds); - } - if (moved || changed_bounds) { - SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_MOVED, 0, 0); - } - SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_ORIENTATION, current_orientation, 0); - SDL_SetDisplayContentScale(existing_display, content_scale); -#ifdef HAVE_DXGI1_6_H - SDL_HDROutputProperties HDR; - WIN_GetHDRProperties(_this, hMonitor, &HDR); - SDL_SetDisplayHDRProperties(existing_display, &HDR); -#endif - } - goto done; - } - } - - displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata)); - if (!displaydata) { - return; - } - SDL_memcpy(displaydata->DeviceName, info->szDevice, sizeof(displaydata->DeviceName)); - displaydata->MonitorHandle = hMonitor; - displaydata->state = DisplayAdded; - - SDL_zero(display); - display.name = WIN_GetDisplayNameVista(_this->internal, info->szDevice); - if (!display.name) { - DISPLAY_DEVICEW device; - SDL_zero(device); - device.cb = sizeof(device); - if (EnumDisplayDevicesW(info->szDevice, 0, &device, 0)) { - display.name = WIN_StringToUTF8W(device.DeviceString); - } - } - - display.desktop_mode = mode; - display.natural_orientation = natural_orientation; - display.current_orientation = current_orientation; - display.content_scale = content_scale; - display.device = _this; - display.internal = displaydata; - WIN_GetDisplayBounds(_this, &display, &displaydata->bounds); -#ifdef HAVE_DXGI1_6_H - WIN_GetHDRProperties(_this, hMonitor, &display.HDR); -#endif - SDL_AddVideoDisplay(&display, false); - SDL_free(display.name); - -done: - *display_index += 1; -} - -typedef struct _WIN_AddDisplaysData -{ - SDL_VideoDevice *video_device; - int display_index; - bool want_primary; -} WIN_AddDisplaysData; - -static BOOL CALLBACK WIN_AddDisplaysCallback(HMONITOR hMonitor, - HDC hdcMonitor, - LPRECT lprcMonitor, - LPARAM dwData) -{ - WIN_AddDisplaysData *data = (WIN_AddDisplaysData *)dwData; - MONITORINFOEXW info; - - SDL_zero(info); - info.cbSize = sizeof(info); - - if (GetMonitorInfoW(hMonitor, (LPMONITORINFO)&info) != 0) { - const bool is_primary = ((info.dwFlags & MONITORINFOF_PRIMARY) == MONITORINFOF_PRIMARY); - - if (is_primary == data->want_primary) { - WIN_AddDisplay(data->video_device, hMonitor, &info, &data->display_index); - } - } - - // continue enumeration - return TRUE; -} - -static void WIN_AddDisplays(SDL_VideoDevice *_this) -{ - WIN_AddDisplaysData callback_data; - callback_data.video_device = _this; - callback_data.display_index = 0; - - callback_data.want_primary = true; - EnumDisplayMonitors(NULL, NULL, WIN_AddDisplaysCallback, (LPARAM)&callback_data); - - callback_data.want_primary = false; - EnumDisplayMonitors(NULL, NULL, WIN_AddDisplaysCallback, (LPARAM)&callback_data); -} - -bool WIN_InitModes(SDL_VideoDevice *_this) -{ - WIN_AddDisplays(_this); - - if (_this->num_displays == 0) { - return SDL_SetError("No displays available"); - } - return true; -} - -bool WIN_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect) -{ - const SDL_DisplayData *data = display->internal; - 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 true; -} - -bool WIN_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect) -{ - const SDL_DisplayData *data = display->internal; - 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 true; -} - -bool WIN_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display) -{ - SDL_DisplayData *data = display->internal; - void *dxgi_output; - DWORD i; - SDL_DisplayMode mode; - - dxgi_output = WIN_GetDXGIOutput(_this, data->DeviceName); - - for (i = 0;; ++i) { - if (!WIN_GetDisplayMode(_this, dxgi_output, data->MonitorHandle, data->DeviceName, i, &mode, NULL, NULL)) { - break; - } - if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) { - // We don't support palettized modes now - SDL_free(mode.internal); - continue; - } - if (mode.format != SDL_PIXELFORMAT_UNKNOWN) { - if (!SDL_AddFullscreenDisplayMode(display, &mode)) { - SDL_free(mode.internal); - } - } else { - SDL_free(mode.internal); - } - } - - WIN_ReleaseDXGIOutput(dxgi_output); - - return true; -} - -#ifdef DEBUG_MODES -static void WIN_LogMonitor(SDL_VideoDevice *_this, HMONITOR mon) -{ - const SDL_VideoData *vid_data = (const SDL_VideoData *)_this->internal; - MONITORINFOEX minfo; - UINT xdpi = 0, ydpi = 0; - char *name_utf8; - - if (vid_data->GetDpiForMonitor) { - vid_data->GetDpiForMonitor(mon, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); - } - - SDL_zero(minfo); - minfo.cbSize = sizeof(minfo); - GetMonitorInfo(mon, (LPMONITORINFO)&minfo); - - name_utf8 = WIN_StringToUTF8(minfo.szDevice); - - SDL_Log("WIN_LogMonitor: monitor \"%s\": dpi: %d windows screen coordinates: %d, %d, %dx%d", - name_utf8, - xdpi, - minfo.rcMonitor.left, - minfo.rcMonitor.top, - minfo.rcMonitor.right - minfo.rcMonitor.left, - minfo.rcMonitor.bottom - minfo.rcMonitor.top); - - SDL_free(name_utf8); -} -#endif - -bool WIN_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode) -{ - SDL_DisplayData *displaydata = display->internal; - SDL_DisplayModeData *data = (SDL_DisplayModeData *)mode->internal; - LONG status; - -#ifdef DEBUG_MODES - SDL_Log("WIN_SetDisplayMode: monitor state before mode change:"); - WIN_LogMonitor(_this, displaydata->MonitorHandle); -#endif - - /* High-DPI notes: - - - ChangeDisplaySettingsEx always takes pixels. - - e.g. if the display is set to 2880x1800 with 200% scaling in Display Settings - - calling ChangeDisplaySettingsEx with a dmPelsWidth/Height other than 2880x1800 will - change the monitor DPI to 96. (100% scaling) - - calling ChangeDisplaySettingsEx with a dmPelsWidth/Height of 2880x1800 (or a NULL DEVMODE*) will - reset the monitor DPI to 192. (200% scaling) - - NOTE: these are temporary changes in DPI, not modifications to the Control Panel setting. */ - if (mode->internal == display->desktop_mode.internal) { -#ifdef DEBUG_MODES - SDL_Log("WIN_SetDisplayMode: resetting to original resolution"); -#endif - status = ChangeDisplaySettingsExW(displaydata->DeviceName, NULL, NULL, CDS_FULLSCREEN, NULL); - } else { -#ifdef DEBUG_MODES - SDL_Log("WIN_SetDisplayMode: changing to %dx%d pixels", data->DeviceMode.dmPelsWidth, data->DeviceMode.dmPelsHeight); -#endif - status = ChangeDisplaySettingsExW(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); - } - -#ifdef DEBUG_MODES - SDL_Log("WIN_SetDisplayMode: monitor state after mode change:"); - WIN_LogMonitor(_this, displaydata->MonitorHandle); -#endif - - EnumDisplaySettingsW(displaydata->DeviceName, ENUM_CURRENT_SETTINGS, &data->DeviceMode); - WIN_UpdateDisplayMode(_this, displaydata->DeviceName, ENUM_CURRENT_SETTINGS, mode); - return true; -} - -void WIN_RefreshDisplays(SDL_VideoDevice *_this) -{ - int i; - - // Mark all displays as potentially invalid to detect - // entries that have actually been removed - for (i = 0; i < _this->num_displays; ++i) { - SDL_DisplayData *internal = _this->displays[i]->internal; - internal->state = DisplayRemoved; - } - - // Enumerate displays to add any new ones and mark still - // connected entries as valid - WIN_AddDisplays(_this); - - // Delete any entries still marked as invalid, iterate - // in reverse as each delete takes effect immediately - for (i = _this->num_displays - 1; i >= 0; --i) { - SDL_VideoDisplay *display = _this->displays[i]; - SDL_DisplayData *internal = display->internal; - if (internal->state == DisplayRemoved) { - SDL_DelVideoDisplay(display->id, true); - } - } - - // Send events for any newly added displays - for (i = 0; i < _this->num_displays; ++i) { - SDL_VideoDisplay *display = _this->displays[i]; - SDL_DisplayData *internal = display->internal; - if (internal->state == DisplayAdded) { - SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ADDED, 0, 0); - } - } -} - -void WIN_QuitModes(SDL_VideoDevice *_this) -{ - // All fullscreen windows should have restored modes by now -} - -#endif // SDL_VIDEO_DRIVER_WINDOWS -- cgit v1.2.3