Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/winemac.drv/display.c | 133 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 6 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 842a979fd2..8b1ae523ee 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -51,6 +51,12 @@ struct display_mode_descriptor
BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmode, DWORD flags);
+/* Wine specific monitor properties */ +DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_STATEFLAGS, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 2); +DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_RCMONITOR, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 3); +DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_RCWORK, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 4); +DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 5); +
static const char initial_mode_key[] = "Initial Display Mode"; static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d','i','n','g',0}; @@ -59,6 +65,8 @@ static const WCHAR graphics_driverW[] = {'G','r','a','p','h','i','c','s','D','r' static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',0}; static const WCHAR symbolic_link_valueW[]= {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',0}; static const WCHAR gpu_idW[] = {'G','P','U','I','D',0}; +static const WCHAR mointor_id_fmtW[] = {'M','o','n','i','t','o','r','I','D','%','d',0}; +static const WCHAR adapter_name_fmtW[] = {'\','\','.','\','D','I','S','P','L','A','Y','%','d',0}; static const WCHAR state_flagsW[] = {'S','t','a','t','e','F','l','a','g','s',0}; static const WCHAR guid_fmtW[] = { '{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-', @@ -105,6 +113,13 @@ static const WCHAR device_video_fmtW[] = { static const WCHAR machine_prefixW[] = { '\','R','e','g','i','s','t','r','y','\', 'M','a','c','h','i','n','e','\',0}; +static const WCHAR monitor_instance_fmtW[] = { + 'D','I','S','P','L','A','Y','\', + 'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r','\', + '%','0','4','X','&','%','0','4','X',0}; +static const WCHAR monitor_hardware_idW[] = { + 'M','O','N','I','T','O','R','\', + 'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r',0,0};
static CFArrayRef modes; @@ -1552,7 +1567,7 @@ fail: * * Return FALSE on failure and TRUE on success. */ -static BOOL macdrv_init_adapter(HKEY video_hkey, int video_index, int gpu_index, int adapter_index, +static BOOL macdrv_init_adapter(HKEY video_hkey, int video_index, int gpu_index, int adapter_index, int monitor_count, const WCHAR *guid_string, const WCHAR *gpu_driver, const struct macdrv_gpu *gpu, const struct macdrv_adapter *adapter) { @@ -1562,6 +1577,7 @@ static BOOL macdrv_init_adapter(HKEY video_hkey, int video_index, int gpu_index, HKEY hkey = NULL; BOOL ret = FALSE; LSTATUS ls; + INT i;
sprintfW(key_nameW, device_video_fmtW, video_index); strcpyW(bufferW, machine_prefixW); @@ -1596,6 +1612,15 @@ static BOOL macdrv_init_adapter(HKEY video_hkey, int video_index, int gpu_index, if (RegSetValueExW(hkey, gpu_idW, 0, REG_SZ, (const BYTE *)bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR))) goto fail;
+ /* Write all monitor instances paths under this adapter */ + for (i = 0; i < monitor_count; i++) + { + sprintfW(key_nameW, mointor_id_fmtW, i); + sprintfW(bufferW, monitor_instance_fmtW, video_index, i); + if (RegSetValueExW(hkey, key_nameW, 0, REG_SZ, (const BYTE *)bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR))) + goto fail; + } + /* Write StateFlags */ if (RegSetValueExW(hkey, state_flagsW, 0, REG_DWORD, (const BYTE *)&adapter->state_flags, sizeof(adapter->state_flags))) @@ -1609,6 +1634,75 @@ fail: return ret; }
+/*********************************************************************** + * macdrv_init_monitor + * + * Initialize an monitor. + * + * Return FALSE on failure and TRUE on success. + */ +static BOOL macdrv_init_monitor(HDEVINFO devinfo, const struct macdrv_monitor *monitor, int monitor_index, + int video_index) +{ + WCHAR nameW[MAX_PATH]; + WCHAR bufferW[MAX_PATH]; + SP_DEVINFO_DATA device_data = {sizeof(SP_DEVINFO_DATA)}; + HKEY hkey = NULL; + RECT rect; + BOOL ret = FALSE; + + /* Create GUID_DEVCLASS_MONITOR instance */ + sprintfW(bufferW, monitor_instance_fmtW, video_index, monitor_index); + MultiByteToWideChar(CP_UTF8, 0, monitor->name, -1, nameW, ARRAY_SIZE(nameW)); + SetupDiCreateDeviceInfoW(devinfo, bufferW, &GUID_DEVCLASS_MONITOR, nameW, NULL, 0, &device_data); + if (!SetupDiRegisterDeviceInfo(devinfo, &device_data, 0, NULL, NULL, NULL)) + goto fail; + + /* Write HaredwareID registry property */ + if (!SetupDiSetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_HARDWAREID, + (const BYTE *)monitor_hardware_idW, sizeof(monitor_hardware_idW))) + goto fail; + + /* Open driver key */ + hkey = SetupDiOpenDevRegKey(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS); + if (hkey == INVALID_HANDLE_VALUE) + hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); + + /* Write DriverDesc value */ + if (RegSetValueExW(hkey, driver_descW, 0, REG_SZ, (const BYTE *)nameW, (strlenW(nameW) + 1) * sizeof(WCHAR))) + goto fail; + + /* FIXME: + * Following properties are Wine specific, see comments in macdrv_init_adapter for details */ + /* StateFlags */ + if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS, DEVPROP_TYPE_UINT32, + (const BYTE *)&monitor->state_flags, sizeof(monitor->state_flags), 0)) + goto fail; + /* RcMonitor */ + rect = rect_from_cgrect(monitor->rc_monitor); + if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCMONITOR, DEVPROP_TYPE_BINARY, + (const BYTE *)&rect, sizeof(rect), 0)) + goto fail; + /* RcWork */ + rect = rect_from_cgrect(monitor->rc_work); + if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCWORK, DEVPROP_TYPE_BINARY, + (const BYTE *)&rect, sizeof(rect), 0)) + goto fail; + + sprintfW(bufferW, adapter_name_fmtW, video_index + 1); + /* Adapter name */ + if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, DEVPROP_TYPE_STRING, + (const BYTE *)bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR), 0)) + goto fail; + + ret = TRUE; +fail: + RegCloseKey(hkey); + if (!ret) + ERR("Failed to initialize monitor\n"); + return ret; +} + static void prepare_devices(void) { static const BOOL not_present = FALSE; @@ -1616,8 +1710,18 @@ static void prepare_devices(void) HDEVINFO devinfo; DWORD i = 0;
+ /* Remove all monitors */ + devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR, NULL, NULL, 0); + while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data)) + { + if (!SetupDiRemoveDevice(devinfo, &device_data)) + ERR("Failed to remove monitor\n"); + } + SetupDiDestroyDeviceInfoList(devinfo); + /* Set all GPUs as not present. We can't simply delete them because we need to keep the GUID consistent with * each initialization run. We clean up non present GPUs at the end of initialization */ + i = 0; devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, 0); while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data)) { @@ -1659,9 +1763,10 @@ BOOL macdrv_init_display_devices(void) { struct macdrv_gpu *gpus = NULL; struct macdrv_adapter *adapters = NULL; - INT gpu_count, adapter_count; - INT gpu, adapter; - HDEVINFO gpu_devinfo = NULL; + struct macdrv_monitor *monitors = NULL; + INT gpu_count, adapter_count, monitor_count; + INT gpu, adapter, monitor; + HDEVINFO gpu_devinfo = NULL, monitor_devinfo = NULL; HKEY video_hkey = NULL; INT video_index = 0; DWORD disposition = 0; @@ -1690,6 +1795,7 @@ BOOL macdrv_init_display_devices(void) prepare_devices();
gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL); + monitor_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_MONITOR, NULL);
/* Initialize GPUs */ if (macdrv_get_gpus(&gpus, &gpu_count)) @@ -1706,10 +1812,22 @@ BOOL macdrv_init_display_devices(void)
for (adapter = 0; adapter < adapter_count; adapter++) { - if (!macdrv_init_adapter(video_hkey, video_index, gpu, adapter, guidW, driverW, &gpus[gpu], - &adapters[adapter])) + if (macdrv_get_monitors(adapters[adapter].id, &monitors, &monitor_count)) + goto fail; + + if (!macdrv_init_adapter(video_hkey, video_index, gpu, adapter, monitor_count, guidW, driverW, &gpus[gpu], + &adapters[adapter])) goto fail;
+ /* Initialize monitors */ + for (monitor = 0; monitor < monitor_count; monitor++) + { + if (!macdrv_init_monitor(monitor_devinfo, &monitors[monitor], monitor, video_index)) + goto fail; + } + + macdrv_free_monitors(monitors); + monitors = NULL; video_index++; }
@@ -1720,12 +1838,15 @@ BOOL macdrv_init_display_devices(void) ret = TRUE; fail: cleanup_devices(); + SetupDiDestroyDeviceInfoList(monitor_devinfo); SetupDiDestroyDeviceInfoList(gpu_devinfo); RegCloseKey(video_hkey); if (gpus) macdrv_free_gpus(gpus); if (adapters) macdrv_free_adapters(adapters); + if (monitors) + macdrv_free_monitors(monitors); if (!ret) ERR("Failed to initialize display devices\n"); return ret;