Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/winemac.drv/display.c | 104 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index b756510875..842a979fd2 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -57,6 +57,9 @@ static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d',' static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0}; static const WCHAR graphics_driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0}; 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 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','-', '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0}; @@ -89,6 +92,19 @@ static const WCHAR video_keyW[] = { 'H','A','R','D','W','A','R','E','\', 'D','E','V','I','C','E','M','A','P','\', 'V','I','D','E','O',0}; +static const WCHAR adapter_key_fmtW[] = { + 'S','y','s','t','e','m','\', + 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\', + 'C','o','n','t','r','o','l','\', + 'V','i','d','e','o','\', + '%','s','\', + '%','0','4','x',0}; +static const WCHAR device_video_fmtW[] = { + '\','D','e','v','i','c','e','\', + 'V','i','d','e','o','%','d',0}; +static const WCHAR machine_prefixW[] = { + '\','R','e','g','i','s','t','r','y','\', + 'M','a','c','h','i','n','e','\',0};
static CFArrayRef modes; @@ -1529,6 +1545,70 @@ fail: return ret; }
+/*********************************************************************** + * macdrv_init_adapter + * + * Initialize an adapter. + * + * 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, + const WCHAR *guid_string, const WCHAR *gpu_driver, const struct macdrv_gpu *gpu, + const struct macdrv_adapter *adapter) +{ + WCHAR adapter_keyW[MAX_PATH]; + WCHAR key_nameW[MAX_PATH]; + WCHAR bufferW[1024]; + HKEY hkey = NULL; + BOOL ret = FALSE; + LSTATUS ls; + + sprintfW(key_nameW, device_video_fmtW, video_index); + strcpyW(bufferW, machine_prefixW); + sprintfW(adapter_keyW, adapter_key_fmtW, guid_string, adapter_index); + strcatW(bufferW, adapter_keyW); + + /* Write value of \Device\Video? (adapter key) in HKLM\HARDWARE\DEVICEMAP\VIDEO\ */ + if (RegSetValueExW(video_hkey, key_nameW, 0, REG_SZ, (const BYTE *)bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR))) + goto fail; + + /* Create HKLM\System\CurrentControlSet\Control\Video{GPU GUID}{Adapter Index} link to GPU driver */ + ls = RegCreateKeyExW(HKEY_LOCAL_MACHINE, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK, + KEY_ALL_ACCESS, NULL, &hkey, NULL); + if (ls == ERROR_ALREADY_EXISTS) + RegCreateKeyExW(HKEY_LOCAL_MACHINE, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE | REG_OPTION_OPEN_LINK, + KEY_ALL_ACCESS, NULL, &hkey, NULL); + if (RegSetValueExW(hkey, symbolic_link_valueW, 0, REG_LINK, (const BYTE *)gpu_driver, + strlenW(gpu_driver) * sizeof(WCHAR))) + goto fail; + RegCloseKey(hkey); + hkey = NULL; + + /* FIXME: + * Following information are Wine specific, they don't really exist on Windows. They are used so that we can + * implement EnumDisplayDevices etc by querying registry only. These information are most likely reported by the + * device driver on Windows */ + RegCreateKeyExW(HKEY_CURRENT_CONFIG, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, NULL); + + /* Write GPU instance path so that we can find the GPU instance via adapters quickly. Another way is trying to match + * them via the GUID in Device Paramters/VideoID, but it would required enumrating all GPU instances */ + sprintfW(bufferW, gpu_instance_fmtW, gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id, gpu_index); + if (RegSetValueExW(hkey, gpu_idW, 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))) + goto fail; + + ret = TRUE; +fail: + RegCloseKey(hkey); + if (!ret) + ERR("Failed to initialize adapter\n"); + return ret; +} + static void prepare_devices(void) { static const BOOL not_present = FALSE; @@ -1578,10 +1658,12 @@ static void cleanup_devices(void) BOOL macdrv_init_display_devices(void) { struct macdrv_gpu *gpus = NULL; - INT gpu_count; - INT gpu; + struct macdrv_adapter *adapters = NULL; + INT gpu_count, adapter_count; + INT gpu, adapter; HDEVINFO gpu_devinfo = NULL; HKEY video_hkey = NULL; + INT video_index = 0; DWORD disposition = 0; WCHAR guidW[40]; WCHAR driverW[1024]; @@ -1617,6 +1699,22 @@ BOOL macdrv_init_display_devices(void) { if (!macdrv_init_gpu(gpu_devinfo, &gpus[gpu], gpu, guidW, driverW)) goto fail; + + /* Initialize adapters */ + if (macdrv_get_adapters(gpus[gpu].id, &adapters, &adapter_count)) + goto fail; + + for (adapter = 0; adapter < adapter_count; adapter++) + { + if (!macdrv_init_adapter(video_hkey, video_index, gpu, adapter, guidW, driverW, &gpus[gpu], + &adapters[adapter])) + goto fail; + + video_index++; + } + + macdrv_free_adapters(adapters); + adapters = NULL; }
ret = TRUE; @@ -1626,6 +1724,8 @@ fail: RegCloseKey(video_hkey); if (gpus) macdrv_free_gpus(gpus); + if (adapters) + macdrv_free_adapters(adapters); if (!ret) ERR("Failed to initialize display devices\n"); return ret;