winemac.drv: Use UpdateDisplayDevices driver entry point for registering devices.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2021-12-01 18:58:18 +01:00 committed by Alexandre Julliard
parent b5e3419dd1
commit 95a106bc93
5 changed files with 73 additions and 546 deletions

View File

@ -1,5 +1,5 @@
MODULE = winemac.drv
IMPORTS = uuid setupapi rpcrt4 user32 gdi32 advapi32
IMPORTS = uuid rpcrt4 user32 gdi32 advapi32 win32u
DELAYIMPORTS = ole32 shell32 imm32
EXTRALIBS = -framework AppKit -framework Carbon -framework Security -framework OpenGL -framework IOKit -framework CoreVideo $(METAL_LIBS)

View File

@ -25,13 +25,6 @@
#include "winuser.h"
#include "winreg.h"
#include "ddrawi.h"
#include "rpc.h"
#include "cfgmgr32.h"
#include "initguid.h"
#include "devguid.h"
#include "devpkey.h"
#include "ntddvdeo.h"
#include "setupapi.h"
#define WIN32_NO_STATUS
#include "winternl.h"
#include "wine/unicode.h"
@ -53,76 +46,16 @@ struct display_mode_descriptor
BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmode, DWORD flags);
DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_GPU_LUID, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 1);
DEFINE_DEVPROPKEY(DEVPROPKEY_MONITOR_OUTPUT_ID, 0xca085853, 0x16ce, 0x48aa, 0xb1, 0x14, 0xde, 0x9c, 0x72, 0x33, 0x42, 0x23, 2);
/* 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};
static const WCHAR driver_date_dataW[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0};
static const WCHAR displayW[] = {'D','I','S','P','L','A','Y',0};
static const WCHAR pciW[] = {'P','C','I',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 monitor_id_fmtW[] = {'M','o','n','i','t','o','r','I','D','%','d',0};
static const WCHAR adapter_prefixW[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y'};
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','-',
'%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0};
static const WCHAR gpu_instance_fmtW[] = {
'P','C','I','\\',
'V','E','N','_','%','0','4','X','&',
'D','E','V','_','%','0','4','X','&',
'S','U','B','S','Y','S','_','%','0','8','X','&',
'R','E','V','_','%','0','2','X','\\',
'%','0','8','X',0};
static const WCHAR gpu_hardware_id_fmtW[] = {
'P','C','I','\\',
'V','E','N','_','%','0','4','X','&',
'D','E','V','_','%','0','4','X','&',
'S','U','B','S','Y','S','_','0','0','0','0','0','0','0','0','&',
'R','E','V','_','0','0',0};
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 const WCHAR nt_classW[] = {
'\\','R','e','g','i','s','t','r','y','\\',
'M','a','c','h','i','n','e','\\',
'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','\\',
'C','l','a','s','s','\\',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;
@ -1441,403 +1374,79 @@ void macdrv_displays_changed(const macdrv_event *event)
}
}
/***********************************************************************
* link_device
*
* Set device interface link state to enabled. The link state should be set via
* IoSetDeviceInterfaceState(). However, IoSetDeviceInterfaceState() requires a PnP driver, which
* currently doesn't exist for display devices.
*
* Return FALSE on failure and TRUE on success.
*/
static BOOL link_device(const WCHAR *instance, const GUID *guid)
static BOOL force_display_devices_refresh;
void CDECL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manager,
BOOL force, void *param )
{
static const WCHAR device_instanceW[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
static const WCHAR hash_controlW[] = {'#','\\','C','o','n','t','r','o','l',0};
static const WCHAR linkedW[] = {'L','i','n','k','e','d',0};
static const DWORD enabled = 1;
WCHAR device_key_name[MAX_PATH], device_instance[MAX_PATH];
HKEY iface_key, device_key, control_key;
DWORD length, index = 0;
BOOL ret = FALSE;
LSTATUS lr;
struct macdrv_adapter *adapters, *adapter;
struct macdrv_monitor *monitors, *monitor;
struct macdrv_gpu *gpus, *gpu;
INT gpu_count, adapter_count, monitor_count;
DWORD len;
iface_key = SetupDiOpenClassRegKeyExW(guid, KEY_ALL_ACCESS, DIOCR_INTERFACE, NULL, NULL);
while (1)
if (!force && !force_display_devices_refresh) return;
force_display_devices_refresh = FALSE;
/* Initialize GPUs */
if (macdrv_get_gpus(&gpus, &gpu_count))
{
length = ARRAY_SIZE(device_key_name);
lr = RegEnumKeyExW(iface_key, index++, device_key_name, &length, NULL, NULL, NULL, NULL);
if (lr)
break;
ERR("could not get GPUs\n");
return;
}
TRACE("GPU count: %d\n", gpu_count);
lr = RegOpenKeyExW(iface_key, device_key_name, 0, KEY_ALL_ACCESS, &device_key);
if (lr)
continue;
length = sizeof(device_instance);
lr = RegQueryValueExW(device_key, device_instanceW, NULL, NULL, (BYTE *)device_instance, &length);
if (lr || lstrcmpiW(device_instance, instance))
for (gpu = gpus; gpu < gpus + gpu_count; gpu++)
{
struct gdi_gpu gdi_gpu =
{
RegCloseKey(device_key);
continue;
.id = gpu->id,
.vendor_id = gpu->vendor_id,
.device_id = gpu->device_id,
.subsys_id = gpu->subsys_id,
.revision_id = gpu->revision_id,
};
RtlUTF8ToUnicodeN(gdi_gpu.name, sizeof(gdi_gpu.name), &len, gpu->name, strlen(gpu->name));
device_manager->add_gpu(&gdi_gpu, param);
/* Initialize adapters */
if (macdrv_get_adapters(gpu->id, &adapters, &adapter_count)) break;
TRACE("GPU: %llx %s, adapter count: %d\n", gpu->id, debugstr_a(gpu->name), adapter_count);
for (adapter = adapters; adapter < adapters + adapter_count; adapter++)
{
struct gdi_adapter gdi_adapter =
{
.id = adapter->id,
.state_flags = adapter->state_flags,
};
device_manager->add_adapter( &gdi_adapter, param );
if (macdrv_get_monitors(adapter->id, &monitors, &monitor_count)) break;
TRACE("adapter: %#x, monitor count: %d\n", adapter->id, monitor_count);
/* Initialize monitors */
for (monitor = monitors; monitor < monitors + monitor_count; monitor++)
{
struct gdi_monitor gdi_monitor =
{
.rc_monitor = rect_from_cgrect(monitor->rc_monitor),
.rc_work = rect_from_cgrect(monitor->rc_work),
.state_flags = monitor->state_flags,
};
RtlUTF8ToUnicodeN(gdi_monitor.name, sizeof(gdi_monitor.name), &len,
monitor->name, strlen(monitor->name));
TRACE("monitor: %s\n", debugstr_a(monitor->name));
device_manager->add_monitor( &gdi_monitor, param );
}
macdrv_free_monitors(monitors);
}
lr = RegCreateKeyExW(device_key, hash_controlW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &control_key, NULL);
RegCloseKey(device_key);
if (lr)
break;
lr = RegSetValueExW(control_key, linkedW, 0, REG_DWORD, (const BYTE *)&enabled, sizeof(enabled));
if (!lr)
ret = TRUE;
RegCloseKey(control_key);
break;
}
RegCloseKey(iface_key);
return ret;
}
/***********************************************************************
* macdrv_init_gpu
*
* Initialize a GPU instance.
* Return its GUID string in guid_string, driver value in driver parameter and LUID in gpu_luid.
*
* Return FALSE on failure and TRUE on success.
*/
static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int gpu_index, WCHAR *guid_string,
WCHAR *driver, LUID *gpu_luid)
{
static const WCHAR adapter_stringW[] = {'H','a','r','d','w','a','r','e','I','n','f','o','r','m','a','t','i','o','n','.','A','d','a','p','t','e','r','S','t','r','i','n','g',0};
static const WCHAR bios_stringW[] = {'H','a','r','d','w','a','r','e','I','n','f','o','r','m','a','t','i','o','n','.','B','i','o','s','S','t','r','i','n','g',0};
static const WCHAR chip_typeW[] = {'H','a','r','d','w','a','r','e','I','n','f','o','r','m','a','t','i','o','n','.','C','h','i','p','T','y','p','e',0};
static const WCHAR dac_typeW[] = {'H','a','r','d','w','a','r','e','I','n','f','o','r','m','a','t','i','o','n','.','D','a','c','T','y','p','e',0};
static const WCHAR ramdacW[] = {'I','n','t','e','r','g','r','a','t','e','d',' ','R','A','M','D','A','C',0};
static const BOOL present = TRUE;
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
WCHAR instanceW[MAX_PATH];
DEVPROPTYPE property_type;
WCHAR nameW[MAX_PATH];
WCHAR bufferW[1024];
FILETIME filetime;
HKEY hkey = NULL;
GUID guid;
LUID luid;
INT written;
DWORD size;
BOOL ret = FALSE;
sprintfW(instanceW, gpu_instance_fmtW, gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id, gpu_index);
MultiByteToWideChar(CP_UTF8, 0, gpu->name, -1, nameW, ARRAY_SIZE(nameW));
if (!SetupDiOpenDeviceInfoW(devinfo, instanceW, NULL, 0, &device_data))
{
SetupDiCreateDeviceInfoW(devinfo, instanceW, &GUID_DEVCLASS_DISPLAY, nameW, NULL, 0, &device_data);
if (!SetupDiRegisterDeviceInfo(devinfo, &device_data, 0, NULL, NULL, NULL))
goto done;
macdrv_free_adapters(adapters);
}
/* Register GUID_DEVINTERFACE_DISPLAY_ADAPTER */
if (!SetupDiCreateDeviceInterfaceW(devinfo, &device_data, &GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, 0, NULL))
goto done;
if (!link_device(instanceW, &GUID_DEVINTERFACE_DISPLAY_ADAPTER))
goto done;
/* Register GUID_DISPLAY_DEVICE_ARRIVAL */
if (!SetupDiCreateDeviceInterfaceW(devinfo, &device_data, &GUID_DISPLAY_DEVICE_ARRIVAL, NULL, 0, NULL))
goto done;
if (!link_device(instanceW, &GUID_DISPLAY_DEVICE_ARRIVAL))
goto done;
/* Write HardwareID registry property, REG_MULTI_SZ */
written = sprintfW(bufferW, gpu_hardware_id_fmtW, gpu->vendor_id, gpu->device_id);
bufferW[written + 1] = 0;
if (!SetupDiSetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_HARDWAREID, (const BYTE *)bufferW,
(written + 2) * sizeof(WCHAR)))
goto done;
/* Write DEVPKEY_Device_IsPresent property */
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, DEVPROP_TYPE_BOOLEAN,
(const BYTE *)&present, sizeof(present), 0))
goto done;
/* Write DEVPROPKEY_GPU_LUID property */
if (!SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_GPU_LUID, &property_type,
(BYTE *)&luid, sizeof(luid), NULL, 0))
{
if (!AllocateLocallyUniqueId(&luid))
goto done;
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_GPU_LUID,
DEVPROP_TYPE_UINT64, (const BYTE *)&luid, sizeof(luid), 0))
goto done;
}
*gpu_luid = luid;
TRACE("GPU id:0x%s name:%s LUID:%08x:%08x.\n", wine_dbgstr_longlong(gpu->id), gpu->name,
luid.HighPart, luid.LowPart);
/* Open driver key.
* This is where HKLM\System\CurrentControlSet\Control\Video\{GPU GUID}\{Adapter Index} links to */
hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
size = (lstrlenW(nameW) + 1) * sizeof(WCHAR);
/* Write DriverDesc value */
if (RegSetValueExW(hkey, driver_descW, 0, REG_SZ, (const BYTE *)nameW, size))
goto done;
/* Write DriverDateData value, using current time as driver date, needed by Evoland */
GetSystemTimeAsFileTime(&filetime);
if (RegSetValueExW(hkey, driver_date_dataW, 0, REG_BINARY, (BYTE *)&filetime, sizeof(filetime)))
goto done;
/* The following hardware information value type may be REG_BINARY or REG_SZ */
if (RegSetValueExW(hkey, adapter_stringW, 0, REG_BINARY, (const BYTE *)nameW, size))
goto done;
if (RegSetValueExW(hkey, bios_stringW, 0, REG_BINARY, (const BYTE *)nameW, size))
goto done;
if (RegSetValueExW(hkey, chip_typeW, 0, REG_BINARY, (const BYTE *)nameW, size))
goto done;
if (RegSetValueExW(hkey, dac_typeW, 0, REG_BINARY, (const BYTE *)ramdacW, sizeof(ramdacW)))
goto done;
RegCloseKey(hkey);
hkey = NULL;
/* Retrieve driver value for adapters */
if (!SetupDiGetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_DRIVER, NULL, (BYTE *)bufferW, sizeof(bufferW),
NULL))
goto done;
lstrcpyW(driver, nt_classW);
lstrcatW(driver, bufferW);
/* Write GUID in VideoID in .../instance/Device Parameters, reuse the GUID if it's existent */
hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL);
size = sizeof(bufferW);
if (RegQueryValueExW(hkey, video_idW, 0, NULL, (BYTE *)bufferW, &size))
{
UuidCreate(&guid);
sprintfW(bufferW, guid_fmtW, guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2],
guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
if (RegSetValueExW(hkey, video_idW, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
goto done;
}
lstrcpyW(guid_string, bufferW);
ret = TRUE;
done:
RegCloseKey(hkey);
if (!ret)
ERR("Failed to initialize GPU\n");
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, int monitor_count,
const struct macdrv_gpu *gpu, const WCHAR *guid_string, const WCHAR *gpu_driver,
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;
INT i;
sprintfW(key_nameW, device_video_fmtW, video_index);
lstrcpyW(bufferW, machine_prefixW);
sprintfW(adapter_keyW, adapter_key_fmtW, guid_string, adapter_index);
lstrcatW(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, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
goto done;
/* 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,
lstrlenW(gpu_driver) * sizeof(WCHAR)))
goto done;
RegCloseKey(hkey);
hkey = NULL;
/* FIXME:
* Following information is Wine specific, it doesn't really exist on Windows. It is used so that we can
* implement EnumDisplayDevices etc by querying registry only. This information is 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 Parameters/VideoID, but it would require enumerating 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, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
goto done;
/* Write all monitor instance paths under this adapter */
for (i = 0; i < monitor_count; i++)
{
sprintfW(key_nameW, monitor_id_fmtW, i);
sprintfW(bufferW, monitor_instance_fmtW, video_index, i);
if (RegSetValueExW(hkey, key_nameW, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
goto done;
}
/* Write StateFlags */
if (RegSetValueExW(hkey, state_flagsW, 0, REG_DWORD, (const BYTE *)&adapter->state_flags,
sizeof(adapter->state_flags)))
goto done;
ret = TRUE;
done:
RegCloseKey(hkey);
if (!ret)
ERR("Failed to initialize adapter\n");
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, const LUID *gpu_luid, UINT output_id)
{
SP_DEVINFO_DATA device_data = {sizeof(SP_DEVINFO_DATA)};
WCHAR nameW[MAX_PATH];
WCHAR bufferW[MAX_PATH];
DWORD length;
HKEY hkey;
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 done;
/* Register GUID_DEVINTERFACE_MONITOR */
if (!SetupDiCreateDeviceInterfaceW(devinfo, &device_data, &GUID_DEVINTERFACE_MONITOR, NULL, 0, NULL))
goto done;
if (!link_device(bufferW, &GUID_DEVINTERFACE_MONITOR))
goto done;
/* Write HardwareID registry property */
if (!SetupDiSetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_HARDWAREID,
(const BYTE *)monitor_hardware_idW, sizeof(monitor_hardware_idW)))
goto done;
/* Write DEVPROPKEY_MONITOR_GPU_LUID */
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_GPU_LUID,
DEVPROP_TYPE_INT64, (const BYTE *)gpu_luid, sizeof(*gpu_luid), 0))
goto done;
/* Write DEVPROPKEY_MONITOR_OUTPUT_ID */
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPROPKEY_MONITOR_OUTPUT_ID,
DEVPROP_TYPE_UINT32, (const BYTE *)&output_id, sizeof(output_id), 0))
goto done;
/* Create driver key */
hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
RegCloseKey(hkey);
/* 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 done;
/* 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 done;
/* 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 done;
/* Adapter name */
length = sprintfW(bufferW, adapter_name_fmtW, video_index + 1);
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, DEVPROP_TYPE_STRING,
(const BYTE *)bufferW, (length + 1) * sizeof(WCHAR), 0))
goto done;
ret = TRUE;
done:
if (!ret)
ERR("Failed to initialize monitor\n");
return ret;
}
static void prepare_devices(HKEY video_hkey)
{
static const BOOL not_present = FALSE;
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
HDEVINFO devinfo;
DWORD i = 0;
/* Remove all monitors */
devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR, displayW, NULL, 0);
while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
{
if (!SetupDiRemoveDevice(devinfo, &device_data))
ERR("Failed to remove monitor\n");
}
SetupDiDestroyDeviceInfoList(devinfo);
/* Clean up old adapter keys for reinitialization */
RegDeleteTreeW(video_hkey, NULL);
/* FIXME:
* Currently SetupDiGetClassDevsW with DIGCF_PRESENT is unsupported, So we need to clean up not present devices in
* case application uses SetupDiGetClassDevsW to enumerate devices. Wrong devices could exist in registry as a result
* of prefix copying or having devices unplugged. But then we couldn't simply delete GPUs because we need to retain
* the same GUID for the same GPU. */
i = 0;
devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, pciW, NULL, 0);
while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
{
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, DEVPROP_TYPE_BOOLEAN,
(const BYTE *)&not_present, sizeof(not_present), 0))
ERR("Failed to set GPU present property\n");
}
SetupDiDestroyDeviceInfoList(devinfo);
}
static void cleanup_devices(void)
{
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
HDEVINFO devinfo;
DWORD type;
DWORD i = 0;
BOOL present;
devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, pciW, NULL, 0);
while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
{
present = FALSE;
SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, &type, (BYTE *)&present,
sizeof(present), NULL, 0);
if (!present && !SetupDiRemoveDevice(devinfo, &device_data))
ERR("Failed to remove GPU\n");
}
SetupDiDestroyDeviceInfoList(devinfo);
macdrv_free_gpus(gpus);
}
/***********************************************************************
@ -1847,94 +1456,9 @@ static void cleanup_devices(void)
*/
void macdrv_init_display_devices(BOOL force)
{
HANDLE mutex;
struct macdrv_gpu *gpus = NULL;
struct macdrv_adapter *adapters = 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;
WCHAR guidW[40];
WCHAR driverW[1024];
LUID gpu_luid;
UINT output_id = 0;
UINT32 num_path, num_mode;
mutex = get_display_device_init_mutex();
if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, video_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &video_hkey,
&disposition))
{
ERR("Failed to create video device key\n");
goto done;
}
/* Avoid unnecessary reinit */
if (!force && disposition != REG_CREATED_NEW_KEY)
goto done;
TRACE("\n");
prepare_devices(video_hkey);
gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL);
monitor_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_MONITOR, NULL);
/* Initialize GPUs */
if (macdrv_get_gpus(&gpus, &gpu_count))
goto done;
TRACE("GPU count: %d\n", gpu_count);
if (!gpu_count)
ERR("No GPUs detected\n");
for (gpu = 0; gpu < gpu_count; gpu++)
{
if (!macdrv_init_gpu(gpu_devinfo, &gpus[gpu], gpu, guidW, driverW, &gpu_luid))
goto done;
/* Initialize adapters */
if (macdrv_get_adapters(gpus[gpu].id, &adapters, &adapter_count))
goto done;
TRACE("GPU: %#llx %s, adapter count: %d\n", gpus[gpu].id, gpus[gpu].name, adapter_count);
for (adapter = 0; adapter < adapter_count; adapter++)
{
if (macdrv_get_monitors(adapters[adapter].id, &monitors, &monitor_count))
goto done;
TRACE("adapter: %#x, monitor count: %d\n", adapters[adapter].id, monitor_count);
if (!macdrv_init_adapter(video_hkey, video_index, gpu, adapter, monitor_count, &gpus[gpu], guidW, driverW,
&adapters[adapter]))
goto done;
/* Initialize monitors */
for (monitor = 0; monitor < monitor_count; monitor++)
{
TRACE("monitor: %#x %s\n", monitor, monitors[monitor].name);
if (!macdrv_init_monitor(monitor_devinfo, &monitors[monitor], monitor, video_index, &gpu_luid, output_id++))
goto done;
}
macdrv_free_monitors(monitors);
monitors = NULL;
video_index++;
}
macdrv_free_adapters(adapters);
adapters = NULL;
}
done:
cleanup_devices();
SetupDiDestroyDeviceInfoList(monitor_devinfo);
SetupDiDestroyDeviceInfoList(gpu_devinfo);
RegCloseKey(video_hkey);
release_display_device_init_mutex(mutex);
macdrv_free_gpus(gpus);
macdrv_free_adapters(adapters);
macdrv_free_monitors(monitors);
if (force) force_display_devices_refresh = TRUE;
/* trigger refresh in win32u */
NtUserGetDisplayConfigBufferSizes( QDC_ONLY_ACTIVE_PATHS, &num_path, &num_mode );
}

View File

@ -281,6 +281,7 @@ static const struct user_driver_funcs macdrv_funcs =
.pDestroyCursorIcon = macdrv_DestroyCursorIcon,
.pDestroyWindow = macdrv_DestroyWindow,
.pEnumDisplaySettingsEx = macdrv_EnumDisplaySettingsEx,
.pUpdateDisplayDevices = macdrv_UpdateDisplayDevices,
.pGetCursorPos = macdrv_GetCursorPos,
.pGetKeyboardLayoutList = macdrv_GetKeyboardLayoutList,
.pGetKeyNameText = macdrv_GetKeyNameText,

View File

@ -130,6 +130,8 @@ extern LONG CDECL macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW dev
HWND hwnd, DWORD flags, LPVOID lpvoid) DECLSPEC_HIDDEN;
extern BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode,
LPDEVMODEW devmode, DWORD flags) DECLSPEC_HIDDEN;
extern void CDECL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device_manager,
BOOL force, void *param ) DECLSPEC_HIDDEN;
extern BOOL CDECL macdrv_GetDeviceGammaRamp(PHYSDEV dev, LPVOID ramp) DECLSPEC_HIDDEN;
extern BOOL CDECL macdrv_SetDeviceGammaRamp(PHYSDEV dev, LPVOID ramp) DECLSPEC_HIDDEN;
extern BOOL CDECL macdrv_ClipCursor(LPCRECT clip) DECLSPEC_HIDDEN;

View File

@ -299,8 +299,8 @@ static BOOL process_attach(void)
return FALSE;
}
macdrv_init_display_devices(FALSE);
init_user_driver();
macdrv_init_display_devices(FALSE);
return TRUE;
}