Commit 83a2ff33 authored by Zhiyi Zhang's avatar Zhiyi Zhang Committed by Alexandre Julliard

winemac.drv: Add monitor initialization functions.

parent 039a7715
......@@ -575,3 +575,112 @@ void macdrv_free_adapters(struct macdrv_adapter* adapters)
if (adapters)
free(adapters);
}
/***********************************************************************
* macdrv_get_monitors
*
* Get a list of monitors under adapter_id. The first monitor is primary if adapter is primary.
* Call macdrv_free_monitors() when you are done using the data.
*
* Returns non-zero value on failure with parameters unchanged and zero on success.
*/
int macdrv_get_monitors(uint32_t adapter_id, struct macdrv_monitor** new_monitors, int* count)
{
struct macdrv_monitor* monitors = NULL;
struct macdrv_monitor* realloc_monitors;
struct macdrv_display* displays = NULL;
CGDirectDisplayID display_ids[16];
uint32_t display_id_count;
int primary_index = 0;
int monitor_count = 0;
int display_count;
int capacity;
int ret = -1;
int i, j;
/* 2 should be enough for most cases */
capacity = 2;
monitors = calloc(capacity, sizeof(*monitors));
if (!monitors)
return -1;
/* Report an inactive monitor */
if (!CGDisplayIsActive(adapter_id) && !CGDisplayIsInMirrorSet(adapter_id))
{
strcpy(monitors[monitor_count].name, "Generic Non-PnP Monitor");
monitors[monitor_count].state_flags = DISPLAY_DEVICE_ATTACHED;
monitor_count++;
}
/* Report active and mirrored monitors in the same mirroring set */
else
{
if (CGGetOnlineDisplayList(sizeof(display_ids) / sizeof(display_ids[0]), display_ids, &display_id_count)
!= kCGErrorSuccess)
goto done;
if (macdrv_get_displays(&displays, &display_count))
goto done;
for (i = 0; i < display_id_count; i++)
{
if (display_ids[i] != adapter_id && CGDisplayMirrorsDisplay(display_ids[i]) != adapter_id)
continue;
/* Find and fill in monitor info */
for (j = 0; j < display_count; j++)
{
if (displays[j].displayID == display_ids[i]
|| CGDisplayMirrorsDisplay(display_ids[i]) == displays[j].displayID)
{
/* Allocate more space if needed */
if (monitor_count >= capacity)
{
capacity *= 2;
realloc_monitors = realloc(monitors, sizeof(*monitors) * capacity);
if (!realloc_monitors)
goto done;
monitors = realloc_monitors;
}
if (j == 0)
primary_index = monitor_count;
strcpy(monitors[monitor_count].name, "Generic Non-PnP Monitor");
monitors[monitor_count].state_flags = DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE;
monitor_count++;
break;
}
}
}
/* Make sure the first monitor on primary adapter is primary */
if (primary_index)
{
struct macdrv_monitor tmp;
tmp = monitors[0];
monitors[0] = monitors[primary_index];
monitors[primary_index] = tmp;
}
}
*new_monitors = monitors;
*count = monitor_count;
ret = 0;
done:
if (displays)
macdrv_free_displays(displays);
if (ret)
macdrv_free_monitors(monitors);
return ret;
}
/***********************************************************************
* macdrv_free_monitors
*
* Frees an monitor list allocated from macdrv_get_monitors()
*/
void macdrv_free_monitors(struct macdrv_monitor* monitors)
{
if (monitors)
free(monitors);
}
......@@ -51,15 +51,19 @@ 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);
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 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 guid_fmtW[] = {
'{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
......@@ -101,6 +105,13 @@ static const WCHAR nt_classW[] = {
'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;
......@@ -1544,7 +1555,7 @@ done:
*
* 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 struct macdrv_gpu *gpu, const WCHAR *guid_string, const WCHAR *gpu_driver,
const struct macdrv_adapter *adapter)
{
......@@ -1554,6 +1565,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);
lstrcpyW(bufferW, machine_prefixW);
......@@ -1588,6 +1600,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, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
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, (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)))
......@@ -1601,6 +1622,52 @@ done:
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)
{
SP_DEVINFO_DATA device_data = {sizeof(SP_DEVINFO_DATA)};
WCHAR nameW[MAX_PATH];
WCHAR bufferW[MAX_PATH];
HKEY hkey;
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;
/* 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 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;
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;
......@@ -1608,6 +1675,15 @@ static void prepare_devices(HKEY video_hkey)
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);
......@@ -1616,6 +1692,7 @@ static void prepare_devices(HKEY video_hkey)
* 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))
{
......@@ -1657,9 +1734,10 @@ void macdrv_init_display_devices(void)
HANDLE mutex;
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;
......@@ -1685,6 +1763,7 @@ void macdrv_init_display_devices(void)
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))
......@@ -1701,10 +1780,22 @@ void macdrv_init_display_devices(void)
for (adapter = 0; adapter < adapter_count; adapter++)
{
if (!macdrv_init_adapter(video_hkey, video_index, gpu, adapter, &gpus[gpu], guidW, driverW,
if (macdrv_get_monitors(adapters[adapter].id, &monitors, &monitor_count))
goto done;
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++)
{
if (!macdrv_init_monitor(monitor_devinfo, &monitors[monitor], monitor, video_index))
goto done;
}
macdrv_free_monitors(monitors);
monitors = NULL;
video_index++;
}
......@@ -1714,6 +1805,7 @@ void macdrv_init_display_devices(void)
done:
cleanup_devices();
SetupDiDestroyDeviceInfoList(monitor_devinfo);
SetupDiDestroyDeviceInfoList(gpu_devinfo);
RegCloseKey(video_hkey);
......@@ -1722,4 +1814,5 @@ done:
macdrv_free_gpus(gpus);
macdrv_free_adapters(adapters);
macdrv_free_monitors(monitors);
}
......@@ -261,6 +261,9 @@ extern int macdrv_clip_cursor(CGRect rect) DECLSPEC_HIDDEN;
/* Used DISPLAY_DEVICE.StateFlags for adapters */
#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
#define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
/* Used DISPLAY_DEVICE.StateFlags for monitors */
#define DISPLAY_DEVICE_ACTIVE 0x00000001
#define DISPLAY_DEVICE_ATTACHED 0x00000002
/* Represent a physical GPU in the PCI slots */
struct macdrv_gpu
......@@ -285,6 +288,15 @@ struct macdrv_adapter
uint32_t state_flags;
};
/* Represent a monitor in EnumDisplayDevices context */
struct macdrv_monitor
{
/* Name, in UTF-8 encoding */
char name[128];
/* StateFlags in DISPLAY_DEVICE struct */
uint32_t state_flags;
};
extern int macdrv_get_displays(struct macdrv_display** displays, int* count) DECLSPEC_HIDDEN;
extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDEN;
extern int macdrv_set_display_mode(const struct macdrv_display* display,
......@@ -293,6 +305,8 @@ extern int macdrv_get_gpus(struct macdrv_gpu** gpus, int* count) DECLSPEC_HIDDEN
extern void macdrv_free_gpus(struct macdrv_gpu* gpus) DECLSPEC_HIDDEN;
extern int macdrv_get_adapters(uint64_t gpu_id, struct macdrv_adapter** adapters, int* count) DECLSPEC_HIDDEN;
extern void macdrv_free_adapters(struct macdrv_adapter* adapters) DECLSPEC_HIDDEN;
extern int macdrv_get_monitors(uint32_t adapter_id, struct macdrv_monitor** monitors, int* count) DECLSPEC_HIDDEN;
extern void macdrv_free_monitors(struct macdrv_monitor* monitors) DECLSPEC_HIDDEN;
/* event */
......
......@@ -299,6 +299,8 @@ static BOOL process_attach(void)
return FALSE;
}
macdrv_init_display_devices();
return TRUE;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment