winex11.drv: Initialize monitor registry data.
Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
eada617881
commit
31445c3264
|
@ -39,10 +39,14 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
|
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
|
||||||
|
|
||||||
|
/* Wine specific monitor properties */
|
||||||
|
DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_STATEFLAGS, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 2);
|
||||||
|
|
||||||
static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0};
|
static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0};
|
||||||
static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',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 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 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 state_flagsW[] = {'S','t','a','t','e','F','l','a','g','s',0};
|
static const WCHAR state_flagsW[] = {'S','t','a','t','e','F','l','a','g','s',0};
|
||||||
static const WCHAR guid_fmtW[] = {
|
static const WCHAR guid_fmtW[] = {
|
||||||
'{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
|
'{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
|
||||||
|
@ -84,6 +88,13 @@ static const WCHAR nt_classW[] = {
|
||||||
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
|
'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','o','n','t','r','o','l','\\',
|
||||||
'C','l','a','s','s','\\',0};
|
'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 struct x11drv_display_device_handler handler;
|
static struct x11drv_display_device_handler handler;
|
||||||
|
|
||||||
|
@ -169,7 +180,7 @@ done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL X11DRV_InitAdapter(HKEY video_hkey, INT video_index, INT gpu_index, INT adapter_index,
|
static BOOL X11DRV_InitAdapter(HKEY video_hkey, INT video_index, INT gpu_index, INT adapter_index, INT monitor_count,
|
||||||
const struct x11drv_gpu *gpu, const WCHAR *guid_string,
|
const struct x11drv_gpu *gpu, const WCHAR *guid_string,
|
||||||
const WCHAR *gpu_driver, const struct x11drv_adapter *adapter)
|
const WCHAR *gpu_driver, const struct x11drv_adapter *adapter)
|
||||||
{
|
{
|
||||||
|
@ -179,6 +190,7 @@ static BOOL X11DRV_InitAdapter(HKEY video_hkey, INT video_index, INT gpu_index,
|
||||||
HKEY hkey = NULL;
|
HKEY hkey = NULL;
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
LSTATUS ls;
|
LSTATUS ls;
|
||||||
|
INT i;
|
||||||
|
|
||||||
sprintfW(key_nameW, device_video_fmtW, video_index);
|
sprintfW(key_nameW, device_video_fmtW, video_index);
|
||||||
lstrcpyW(bufferW, machine_prefixW);
|
lstrcpyW(bufferW, machine_prefixW);
|
||||||
|
@ -213,6 +225,15 @@ static BOOL X11DRV_InitAdapter(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)))
|
if (RegSetValueExW(hkey, gpu_idW, 0, REG_SZ, (const BYTE *)bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR)))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
/* 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 done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write StateFlags */
|
/* Write StateFlags */
|
||||||
if (RegSetValueExW(hkey, state_flagsW, 0, REG_DWORD, (const BYTE *)&adapter->state_flags,
|
if (RegSetValueExW(hkey, state_flagsW, 0, REG_DWORD, (const BYTE *)&adapter->state_flags,
|
||||||
sizeof(adapter->state_flags)))
|
sizeof(adapter->state_flags)))
|
||||||
|
@ -226,6 +247,43 @@ done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL X11DRV_InitMonitor(HDEVINFO devinfo, const struct x11drv_monitor *monitor, int monitor_index,
|
||||||
|
int video_index)
|
||||||
|
{
|
||||||
|
SP_DEVINFO_DATA device_data = {sizeof(SP_DEVINFO_DATA)};
|
||||||
|
WCHAR bufferW[MAX_PATH];
|
||||||
|
HKEY hkey;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
|
/* Create GUID_DEVCLASS_MONITOR instance */
|
||||||
|
sprintfW(bufferW, monitor_instance_fmtW, video_index, monitor_index);
|
||||||
|
SetupDiCreateDeviceInfoW(devinfo, bufferW, &GUID_DEVCLASS_MONITOR, monitor->name, NULL, 0, &device_data);
|
||||||
|
if (!SetupDiRegisterDeviceInfo(devinfo, &device_data, 0, NULL, NULL, NULL))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Write HardwareID registry property */
|
||||||
|
if (!SetupDiSetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_HARDWAREID,
|
||||||
|
(const BYTE *)monitor_hardware_idW, sizeof(monitor_hardware_idW)))
|
||||||
|
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 X11DRV_InitAdapter 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;
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
done:
|
||||||
|
if (!ret)
|
||||||
|
ERR("Failed to initialize monitor\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void prepare_devices(HKEY video_hkey)
|
static void prepare_devices(HKEY video_hkey)
|
||||||
{
|
{
|
||||||
static const BOOL not_present = FALSE;
|
static const BOOL not_present = FALSE;
|
||||||
|
@ -233,6 +291,15 @@ static void prepare_devices(HKEY video_hkey)
|
||||||
HDEVINFO devinfo;
|
HDEVINFO devinfo;
|
||||||
DWORD i = 0;
|
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);
|
||||||
|
|
||||||
/* Clean up old adapter keys for reinitialization */
|
/* Clean up old adapter keys for reinitialization */
|
||||||
RegDeleteTreeW(video_hkey, NULL);
|
RegDeleteTreeW(video_hkey, NULL);
|
||||||
|
|
||||||
|
@ -241,6 +308,7 @@ static void prepare_devices(HKEY video_hkey)
|
||||||
* case application uses SetupDiGetClassDevsW to enumerate devices. Wrong devices could exist in registry as a result
|
* 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
|
* 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. */
|
* the same GUID for the same GPU. */
|
||||||
|
i = 0;
|
||||||
devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, 0);
|
devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, 0);
|
||||||
while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
|
while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
|
||||||
{
|
{
|
||||||
|
@ -277,9 +345,10 @@ void X11DRV_DisplayDevices_Init(void)
|
||||||
HANDLE mutex;
|
HANDLE mutex;
|
||||||
struct x11drv_gpu *gpus = NULL;
|
struct x11drv_gpu *gpus = NULL;
|
||||||
struct x11drv_adapter *adapters = NULL;
|
struct x11drv_adapter *adapters = NULL;
|
||||||
INT gpu_count, adapter_count;
|
struct x11drv_monitor *monitors = NULL;
|
||||||
INT gpu, adapter;
|
INT gpu_count, adapter_count, monitor_count;
|
||||||
HDEVINFO gpu_devinfo = NULL;
|
INT gpu, adapter, monitor;
|
||||||
|
HDEVINFO gpu_devinfo = NULL, monitor_devinfo = NULL;
|
||||||
HKEY video_hkey = NULL;
|
HKEY video_hkey = NULL;
|
||||||
INT video_index = 0;
|
INT video_index = 0;
|
||||||
DWORD disposition = 0;
|
DWORD disposition = 0;
|
||||||
|
@ -305,6 +374,7 @@ void X11DRV_DisplayDevices_Init(void)
|
||||||
prepare_devices(video_hkey);
|
prepare_devices(video_hkey);
|
||||||
|
|
||||||
gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL);
|
gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL);
|
||||||
|
monitor_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_MONITOR, NULL);
|
||||||
|
|
||||||
/* Initialize GPUs */
|
/* Initialize GPUs */
|
||||||
if (!handler.pGetGpus(&gpus, &gpu_count))
|
if (!handler.pGetGpus(&gpus, &gpu_count))
|
||||||
|
@ -321,10 +391,22 @@ void X11DRV_DisplayDevices_Init(void)
|
||||||
|
|
||||||
for (adapter = 0; adapter < adapter_count; adapter++)
|
for (adapter = 0; adapter < adapter_count; adapter++)
|
||||||
{
|
{
|
||||||
if (!X11DRV_InitAdapter(video_hkey, video_index, gpu, adapter,
|
if (!handler.pGetMonitors(adapters[adapter].id, &monitors, &monitor_count))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (!X11DRV_InitAdapter(video_hkey, video_index, gpu, adapter, monitor_count,
|
||||||
&gpus[gpu], guidW, driverW, &adapters[adapter]))
|
&gpus[gpu], guidW, driverW, &adapters[adapter]))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
/* Initialize monitors */
|
||||||
|
for (monitor = 0; monitor < monitor_count; monitor++)
|
||||||
|
{
|
||||||
|
if (!X11DRV_InitMonitor(monitor_devinfo, &monitors[monitor], monitor, video_index))
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.pFreeMonitors(monitors);
|
||||||
|
monitors = NULL;
|
||||||
video_index++;
|
video_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +416,7 @@ void X11DRV_DisplayDevices_Init(void)
|
||||||
|
|
||||||
done:
|
done:
|
||||||
cleanup_devices();
|
cleanup_devices();
|
||||||
|
SetupDiDestroyDeviceInfoList(monitor_devinfo);
|
||||||
SetupDiDestroyDeviceInfoList(gpu_devinfo);
|
SetupDiDestroyDeviceInfoList(gpu_devinfo);
|
||||||
RegCloseKey(video_hkey);
|
RegCloseKey(video_hkey);
|
||||||
ReleaseMutex(mutex);
|
ReleaseMutex(mutex);
|
||||||
|
@ -342,4 +425,6 @@ done:
|
||||||
handler.pFreeGpus(gpus);
|
handler.pFreeGpus(gpus);
|
||||||
if (adapters)
|
if (adapters)
|
||||||
handler.pFreeAdapters(adapters);
|
handler.pFreeAdapters(adapters);
|
||||||
|
if (monitors)
|
||||||
|
handler.pFreeMonitors(monitors);
|
||||||
}
|
}
|
||||||
|
|
|
@ -690,6 +690,15 @@ struct x11drv_adapter
|
||||||
DWORD state_flags;
|
DWORD state_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Represent a monitor in EnumDisplayDevices context */
|
||||||
|
struct x11drv_monitor
|
||||||
|
{
|
||||||
|
/* Name */
|
||||||
|
WCHAR name[128];
|
||||||
|
/* StateFlags in DISPLAY_DEVICE struct */
|
||||||
|
DWORD state_flags;
|
||||||
|
};
|
||||||
|
|
||||||
/* Required functions for display device registry initialization */
|
/* Required functions for display device registry initialization */
|
||||||
struct x11drv_display_device_handler
|
struct x11drv_display_device_handler
|
||||||
{
|
{
|
||||||
|
@ -710,11 +719,20 @@ struct x11drv_display_device_handler
|
||||||
* Return FALSE on failure with parameters unchanged */
|
* Return FALSE on failure with parameters unchanged */
|
||||||
BOOL (*pGetAdapters)(ULONG_PTR gpu_id, struct x11drv_adapter **adapters, int *count);
|
BOOL (*pGetAdapters)(ULONG_PTR gpu_id, struct x11drv_adapter **adapters, int *count);
|
||||||
|
|
||||||
|
/* pGetMonitors will be called to get a list of monitors in EnumDisplayDevices context under an adapter.
|
||||||
|
* The first monitor has to be primary if adapter is primary.
|
||||||
|
*
|
||||||
|
* Return FALSE on failure with parameters unchanged */
|
||||||
|
BOOL (*pGetMonitors)(ULONG_PTR adapter_id, struct x11drv_monitor **monitors, int *count);
|
||||||
|
|
||||||
/* pFreeGpus will be called to free a GPU list from pGetGpus */
|
/* pFreeGpus will be called to free a GPU list from pGetGpus */
|
||||||
void (*pFreeGpus)(struct x11drv_gpu *gpus);
|
void (*pFreeGpus)(struct x11drv_gpu *gpus);
|
||||||
|
|
||||||
/* pFreeAdapters will be called to free an adapter list from pGetAdapters */
|
/* pFreeAdapters will be called to free an adapter list from pGetAdapters */
|
||||||
void (*pFreeAdapters)(struct x11drv_adapter *adapters);
|
void (*pFreeAdapters)(struct x11drv_adapter *adapters);
|
||||||
|
|
||||||
|
/* pFreeMonitors will be called to free a monitor list from pGetMonitors */
|
||||||
|
void (*pFreeMonitors)(struct x11drv_monitor *monitors);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN;
|
extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -291,6 +291,55 @@ static void xinerama_free_adapters( struct x11drv_adapter *adapters )
|
||||||
heap_free( adapters );
|
heap_free( adapters );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL xinerama_get_monitors( ULONG_PTR adapter_id, struct x11drv_monitor **new_monitors, int *count )
|
||||||
|
{
|
||||||
|
static const WCHAR generic_nonpnp_monitorW[] = {
|
||||||
|
'G','e','n','e','r','i','c',' ',
|
||||||
|
'N','o','n','-','P','n','P',' ','M','o','n','i','t','o','r',0};
|
||||||
|
struct x11drv_monitor *monitor;
|
||||||
|
INT first = (INT)adapter_id;
|
||||||
|
INT monitor_count = 0;
|
||||||
|
INT index = 0;
|
||||||
|
INT i;
|
||||||
|
|
||||||
|
for (i = first; i < nb_monitors; i++)
|
||||||
|
{
|
||||||
|
if (i == first
|
||||||
|
|| (EqualRect( &monitors[i].rcMonitor, &monitors[first].rcMonitor )
|
||||||
|
&& !IsRectEmpty( &monitors[first].rcMonitor )))
|
||||||
|
monitor_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor = heap_calloc( monitor_count, sizeof(*monitor) );
|
||||||
|
if (!monitor)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = first; i < nb_monitors; i++)
|
||||||
|
{
|
||||||
|
if (i == first
|
||||||
|
|| (EqualRect( &monitors[i].rcMonitor, &monitors[first].rcMonitor )
|
||||||
|
&& !IsRectEmpty( &monitors[first].rcMonitor )))
|
||||||
|
{
|
||||||
|
lstrcpyW( monitor[index].name, generic_nonpnp_monitorW );
|
||||||
|
/* Xinerama only reports monitors already attached */
|
||||||
|
monitor[index].state_flags = DISPLAY_DEVICE_ATTACHED;
|
||||||
|
if (!IsRectEmpty( &monitors[i].rcMonitor ))
|
||||||
|
monitor[index].state_flags |= DISPLAY_DEVICE_ACTIVE;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*new_monitors = monitor;
|
||||||
|
*count = monitor_count;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xinerama_free_monitors( struct x11drv_monitor *monitors )
|
||||||
|
{
|
||||||
|
heap_free( monitors );
|
||||||
|
}
|
||||||
|
|
||||||
void xinerama_init( unsigned int width, unsigned int height )
|
void xinerama_init( unsigned int width, unsigned int height )
|
||||||
{
|
{
|
||||||
struct x11drv_display_device_handler handler;
|
struct x11drv_display_device_handler handler;
|
||||||
|
@ -331,8 +380,10 @@ void xinerama_init( unsigned int width, unsigned int height )
|
||||||
handler.priority = 100;
|
handler.priority = 100;
|
||||||
handler.pGetGpus = xinerama_get_gpus;
|
handler.pGetGpus = xinerama_get_gpus;
|
||||||
handler.pGetAdapters = xinerama_get_adapters;
|
handler.pGetAdapters = xinerama_get_adapters;
|
||||||
|
handler.pGetMonitors = xinerama_get_monitors;
|
||||||
handler.pFreeGpus = xinerama_free_gpus;
|
handler.pFreeGpus = xinerama_free_gpus;
|
||||||
handler.pFreeAdapters = xinerama_free_adapters;
|
handler.pFreeAdapters = xinerama_free_adapters;
|
||||||
|
handler.pFreeMonitors = xinerama_free_monitors;
|
||||||
X11DRV_DisplayDevices_SetHandler( &handler );
|
X11DRV_DisplayDevices_SetHandler( &handler );
|
||||||
|
|
||||||
TRACE( "virtual size: %s primary: %s\n",
|
TRACE( "virtual size: %s primary: %s\n",
|
||||||
|
|
Loading…
Reference in New Issue