winemac.drv: Add adapter initialization functions.
Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com> Signed-off-by: Ken Thomases <ken@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
0699089f0e
commit
039a7715f3
|
@ -26,6 +26,8 @@
|
|||
#endif
|
||||
#include "macdrv_cocoa.h"
|
||||
|
||||
static uint64_t dedicated_gpu_id;
|
||||
static uint64_t integrated_gpu_id;
|
||||
|
||||
/***********************************************************************
|
||||
* convert_display_rect
|
||||
|
@ -291,6 +293,7 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count)
|
|||
/* Hide the integrated GPU if the system default device is a dedicated GPU */
|
||||
if (!primary_device.isLowPower)
|
||||
{
|
||||
dedicated_gpu_id = primary_gpu.id;
|
||||
hide_integrated = TRUE;
|
||||
}
|
||||
|
||||
|
@ -301,6 +304,7 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count)
|
|||
|
||||
if (hide_integrated && devices[i].isLowPower)
|
||||
{
|
||||
integrated_gpu_id = gpus[gpu_count].id;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -406,6 +410,7 @@ static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count)
|
|||
* Assuming integrated GPU vendor is Intel for now */
|
||||
if (gpus[i].vendor_id == 0x8086)
|
||||
{
|
||||
integrated_gpu_id = gpus[i].id;
|
||||
integrated_index = i;
|
||||
}
|
||||
|
||||
|
@ -428,6 +433,7 @@ static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count)
|
|||
else if (primary_index == gpu_count - 1)
|
||||
primary_index = integrated_index;
|
||||
|
||||
dedicated_gpu_id = gpus[primary_index].id;
|
||||
gpu_count--;
|
||||
}
|
||||
}
|
||||
|
@ -460,6 +466,9 @@ static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count)
|
|||
*/
|
||||
int macdrv_get_gpus(struct macdrv_gpu** new_gpus, int* count)
|
||||
{
|
||||
integrated_gpu_id = 0;
|
||||
dedicated_gpu_id = 0;
|
||||
|
||||
if (!macdrv_get_gpus_from_metal(new_gpus, count))
|
||||
return 0;
|
||||
else
|
||||
|
@ -476,3 +485,93 @@ void macdrv_free_gpus(struct macdrv_gpu* gpus)
|
|||
if (gpus)
|
||||
free(gpus);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_get_adapters
|
||||
*
|
||||
* Get a list of adapters under gpu_id. The first adapter is primary if GPU is primary.
|
||||
* Call macdrv_free_adapters() when you are done using the data.
|
||||
*
|
||||
* Returns non-zero value on failure with parameters unchanged and zero on success.
|
||||
*/
|
||||
int macdrv_get_adapters(uint64_t gpu_id, struct macdrv_adapter** new_adapters, int* count)
|
||||
{
|
||||
CGDirectDisplayID display_ids[16];
|
||||
uint32_t display_id_count;
|
||||
struct macdrv_adapter* adapters;
|
||||
struct macdrv_gpu gpu;
|
||||
int primary_index = 0;
|
||||
int adapter_count = 0;
|
||||
int ret = -1;
|
||||
uint32_t i;
|
||||
|
||||
if (CGGetOnlineDisplayList(sizeof(display_ids) / sizeof(display_ids[0]), display_ids, &display_id_count)
|
||||
!= kCGErrorSuccess)
|
||||
return -1;
|
||||
|
||||
if (!display_id_count)
|
||||
{
|
||||
*new_adapters = NULL;
|
||||
*count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Actual adapter count may be less */
|
||||
adapters = calloc(display_id_count, sizeof(*adapters));
|
||||
if (!adapters)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < display_id_count; i++)
|
||||
{
|
||||
/* Mirrored displays are under the same adapter with primary display, so they doesn't increase adapter count */
|
||||
if (CGDisplayMirrorsDisplay(display_ids[i]) != kCGNullDirectDisplay)
|
||||
continue;
|
||||
|
||||
if (macdrv_get_gpu_info_from_display_id(&gpu, display_ids[i]))
|
||||
goto done;
|
||||
|
||||
if (gpu.id == gpu_id || (gpu_id == dedicated_gpu_id && gpu.id == integrated_gpu_id))
|
||||
{
|
||||
adapters[adapter_count].id = display_ids[i];
|
||||
|
||||
if (CGDisplayIsMain(display_ids[i]))
|
||||
{
|
||||
adapters[adapter_count].state_flags |= DISPLAY_DEVICE_PRIMARY_DEVICE;
|
||||
primary_index = adapter_count;
|
||||
}
|
||||
|
||||
if (CGDisplayIsActive(display_ids[i]))
|
||||
adapters[adapter_count].state_flags |= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
|
||||
|
||||
adapter_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure the first adapter is primary if the GPU is primary */
|
||||
if (primary_index)
|
||||
{
|
||||
struct macdrv_adapter tmp;
|
||||
tmp = adapters[0];
|
||||
adapters[0] = adapters[primary_index];
|
||||
adapters[primary_index] = tmp;
|
||||
}
|
||||
|
||||
*new_adapters = adapters;
|
||||
*count = adapter_count;
|
||||
ret = 0;
|
||||
done:
|
||||
if (ret)
|
||||
macdrv_free_adapters(adapters);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_free_adapters
|
||||
*
|
||||
* Frees an adapter list allocated from macdrv_get_adapters()
|
||||
*/
|
||||
void macdrv_free_adapters(struct macdrv_adapter* adapters)
|
||||
{
|
||||
if (adapters)
|
||||
free(adapters);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,9 @@ static const WCHAR driver_date_dataW[] = {'D','r','i','v','e','r','D','a','t','e
|
|||
static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',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 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};
|
||||
|
@ -78,6 +81,26 @@ 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 CFArrayRef modes;
|
||||
|
@ -1432,11 +1455,12 @@ void macdrv_displays_changed(const macdrv_event *event)
|
|||
/***********************************************************************
|
||||
* macdrv_init_gpu
|
||||
*
|
||||
* Initialize a GPU instance.
|
||||
* Initialize a GPU instance and return its GUID string in guid_string and driver value in driver parameter.
|
||||
*
|
||||
* Return FALSE on failure and TRUE on success.
|
||||
*/
|
||||
static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int gpu_index)
|
||||
static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int gpu_index, WCHAR *guid_string,
|
||||
WCHAR *driver)
|
||||
{
|
||||
static const BOOL present = TRUE;
|
||||
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
|
||||
|
@ -1484,6 +1508,13 @@ static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int
|
|||
goto done;
|
||||
RegCloseKey(hkey);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
@ -1496,6 +1527,7 @@ static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int
|
|||
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:
|
||||
|
@ -1505,13 +1537,80 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void prepare_devices(void)
|
||||
/***********************************************************************
|
||||
* 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 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;
|
||||
|
||||
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 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, (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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* 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
|
||||
|
@ -1557,11 +1656,15 @@ void macdrv_init_display_devices(void)
|
|||
static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0};
|
||||
HANDLE mutex;
|
||||
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];
|
||||
|
||||
mutex = CreateMutexW(NULL, FALSE, init_mutexW);
|
||||
WaitForSingleObject(mutex, INFINITE);
|
||||
|
@ -1579,7 +1682,7 @@ void macdrv_init_display_devices(void)
|
|||
|
||||
TRACE("\n");
|
||||
|
||||
prepare_devices();
|
||||
prepare_devices(video_hkey);
|
||||
|
||||
gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL);
|
||||
|
||||
|
@ -1589,8 +1692,24 @@ void macdrv_init_display_devices(void)
|
|||
|
||||
for (gpu = 0; gpu < gpu_count; gpu++)
|
||||
{
|
||||
if (!macdrv_init_gpu(gpu_devinfo, &gpus[gpu], gpu))
|
||||
if (!macdrv_init_gpu(gpu_devinfo, &gpus[gpu], gpu, guidW, driverW))
|
||||
goto done;
|
||||
|
||||
/* Initialize adapters */
|
||||
if (macdrv_get_adapters(gpus[gpu].id, &adapters, &adapter_count))
|
||||
goto done;
|
||||
|
||||
for (adapter = 0; adapter < adapter_count; adapter++)
|
||||
{
|
||||
if (!macdrv_init_adapter(video_hkey, video_index, gpu, adapter, &gpus[gpu], guidW, driverW,
|
||||
&adapters[adapter]))
|
||||
goto done;
|
||||
|
||||
video_index++;
|
||||
}
|
||||
|
||||
macdrv_free_adapters(adapters);
|
||||
adapters = NULL;
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -1602,4 +1721,5 @@ done:
|
|||
CloseHandle(mutex);
|
||||
|
||||
macdrv_free_gpus(gpus);
|
||||
macdrv_free_adapters(adapters);
|
||||
}
|
||||
|
|
|
@ -258,6 +258,10 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point)
|
|||
|
||||
/* display */
|
||||
|
||||
/* Used DISPLAY_DEVICE.StateFlags for adapters */
|
||||
#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
|
||||
#define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
|
||||
|
||||
/* Represent a physical GPU in the PCI slots */
|
||||
struct macdrv_gpu
|
||||
{
|
||||
|
@ -272,12 +276,23 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point)
|
|||
uint32_t revision_id;
|
||||
};
|
||||
|
||||
/* Represent an adapter in EnumDisplayDevices context */
|
||||
struct macdrv_adapter
|
||||
{
|
||||
/* ID to uniquely identify an adapter. Currently it's a CGDirectDisplayID */
|
||||
uint32_t id;
|
||||
/* as 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,
|
||||
CGDisplayModeRef display_mode) DECLSPEC_HIDDEN;
|
||||
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;
|
||||
|
||||
|
||||
/* event */
|
||||
|
|
Loading…
Reference in New Issue