From: Zhiyi Zhang zzhang@codeweavers.com
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com Signed-off-by: Ken Thomases ken@codeweavers.com --- v3: Supersede 169138~169143 Minor style changes v2: Supersede 167500~167504. Split GPU initialization patch. Add DriverDateData registry property to display adapters.
dlls/winemac.drv/Makefile.in | 2 +- dlls/winemac.drv/cocoa_display.m | 258 +++++++++++++++++++++++++++++++ dlls/winemac.drv/display.c | 206 ++++++++++++++++++++++++ dlls/winemac.drv/macdrv.h | 1 + dlls/winemac.drv/macdrv_cocoa.h | 17 ++ 5 files changed, 483 insertions(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in index 3ffb7d666c6..c6ae9733bdd 100644 --- a/dlls/winemac.drv/Makefile.in +++ b/dlls/winemac.drv/Makefile.in @@ -1,5 +1,5 @@ MODULE = winemac.drv -IMPORTS = uuid user32 gdi32 advapi32 +IMPORTS = uuid setupapi rpcrt4 user32 gdi32 advapi32 DELAYIMPORTS = ole32 shell32 imm32 EXTRALIBS = -framework AppKit -framework Carbon -framework Security -framework OpenGL -framework IOKit -framework CoreVideo $(METAL_LIBS)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m index 93a0fbca353..b8f27309790 100644 --- a/dlls/winemac.drv/cocoa_display.m +++ b/dlls/winemac.drv/cocoa_display.m @@ -103,3 +103,261 @@ void macdrv_free_displays(struct macdrv_display* displays) { free(displays); } + +/*********************************************************************** + * get_entry_property_uint32 + * + * Get an io registry entry property of type uint32 and store it in value parameter. + * + * Returns non-zero value on failure. + */ +static int get_entry_property_uint32(io_registry_entry_t entry, CFStringRef property_name, uint32_t* value) +{ + CFDataRef data = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, property_name, kCFAllocatorDefault, 0); + if (!data) + return -1; + + if (CFGetTypeID(data) != CFDataGetTypeID() || CFDataGetLength(data) != sizeof(uint32_t)) + { + CFRelease(data); + return -1; + } + + CFDataGetBytes(data, CFRangeMake(0, sizeof(uint32_t)), (UInt8*)value); + CFRelease(data); + return 0; +} + +/*********************************************************************** + * get_entry_property_string + * + * Get an io registry entry property of type string and write it in buffer parameter. + * + * Returns non-zero value on failure. + */ +static int get_entry_property_string(io_registry_entry_t entry, CFStringRef property_name, char* buffer, + size_t buffer_size) +{ + CFTypeRef type_ref; + CFDataRef data_ref; + CFStringRef string_ref; + size_t length; + int ret = -1; + + type_ref = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, property_name, kCFAllocatorDefault, 0); + if (!type_ref) + goto done; + + if (CFGetTypeID(type_ref) == CFDataGetTypeID()) + { + data_ref = type_ref; + length = CFDataGetLength(data_ref); + if (length + 1 > buffer_size) + goto done; + CFDataGetBytes(data_ref, CFRangeMake(0, length), (UInt8*)buffer); + buffer[length] = 0; + } + else if (CFGetTypeID(type_ref) == CFStringGetTypeID()) + { + string_ref = type_ref; + if (!CFStringGetCString(string_ref, buffer, buffer_size, kCFStringEncodingUTF8)) + goto done; + } + else + goto done; + + ret = 0; +done: + if (type_ref) + CFRelease(type_ref); + return ret; +} + +/*********************************************************************** + * macdrv_get_gpu_info_from_entry + * + * Starting from entry, search upwards to find the PCI GPU. And get GPU information from the PCI GPU entry. + * + * Returns non-zero value on failure. + */ +static int macdrv_get_gpu_info_from_entry(struct macdrv_gpu* gpu, io_registry_entry_t entry) +{ + io_registry_entry_t parent_entry; + io_registry_entry_t gpu_entry; + kern_return_t result; + int ret = -1; + char buffer[64]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + gpu_entry = entry; + while (![@"IOPCIDevice" isEqualToString:[(NSString*)IOObjectCopyClass(gpu_entry) autorelease]] + || get_entry_property_string(gpu_entry, CFSTR("IOName"), buffer, sizeof(buffer)) + || strcmp(buffer, "display")) + { + result = IORegistryEntryGetParentEntry(gpu_entry, kIOServicePlane, &parent_entry); + if (gpu_entry != entry) + IOObjectRelease(gpu_entry); + if (result != kIOReturnSuccess) + { + [pool release]; + return ret; + } + + gpu_entry = parent_entry; + } + + if (IORegistryEntryGetRegistryEntryID(gpu_entry, &gpu->id) != kIOReturnSuccess) + goto done; + if (get_entry_property_uint32(gpu_entry, CFSTR("vendor-id"), &gpu->vendor_id)) + goto done; + if (get_entry_property_uint32(gpu_entry, CFSTR("device-id"), &gpu->device_id)) + goto done; + if (get_entry_property_uint32(gpu_entry, CFSTR("subsystem-id"), &gpu->subsys_id)) + goto done; + if (get_entry_property_uint32(gpu_entry, CFSTR("revision-id"), &gpu->revision_id)) + goto done; + if (get_entry_property_string(gpu_entry, CFSTR("model"), gpu->name, sizeof(gpu->name))) + goto done; + + ret = 0; +done: + if (gpu_entry != entry) + IOObjectRelease(gpu_entry); + [pool release]; + return ret; +} + +/*********************************************************************** + * macdrv_get_gpu_info_from_display_id + * + * Get GPU information from a display id. + * This is a fallback for 32bit build or older Mac OS version where Metal is unavailable. + * + * Returns non-zero value on failure. + */ +static int macdrv_get_gpu_info_from_display_id(struct macdrv_gpu* gpu, CGDirectDisplayID display_id) +{ + io_registry_entry_t entry = CGDisplayIOServicePort(display_id); + return macdrv_get_gpu_info_from_entry(gpu, entry); +} + +/*********************************************************************** + * macdrv_get_gpus_from_iokit + * + * Get a list of GPUs from IOKit. + * This is a fallback for 32bit build or older Mac OS version where Metal is unavailable. + * + * Returns non-zero value on failure with parameters unchanged and zero on success. + */ +static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count) +{ + static const int MAX_GPUS = 4; + struct macdrv_gpu primary_gpu = {0}; + io_registry_entry_t entry; + io_iterator_t iterator; + struct macdrv_gpu* gpus; + int integrated_index = -1; + int primary_index = 0; + int gpu_count = 0; + int ret = -1; + int i; + + gpus = calloc(MAX_GPUS, sizeof(*gpus)); + if (!gpus) + goto done; + + if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOPCIDevice"), &iterator) + != kIOReturnSuccess) + goto done; + + while ((entry = IOIteratorNext(iterator))) + { + if (!macdrv_get_gpu_info_from_entry(&gpus[gpu_count], entry)) + { + gpu_count++; + assert(gpu_count < MAX_GPUS); + } + IOObjectRelease(entry); + } + IOObjectRelease(iterator); + + macdrv_get_gpu_info_from_display_id(&primary_gpu, CGMainDisplayID()); + + /* If there are more than two GPUs and an Intel card exists, + * assume an automatic graphics pair exists and hide the integrated GPU */ + if (gpu_count > 1) + { + for (i = 0; i < gpu_count; i++) + { + /* FIXME: + * Find integrated GPU without Metal support. + * Assuming integrated GPU vendor is Intel for now */ + if (gpus[i].vendor_id == 0x8086) + { + integrated_index = i; + } + + if (gpus[i].id == primary_gpu.id) + { + primary_index = i; + } + } + + if (integrated_index != -1) + { + if (integrated_index != gpu_count - 1) + gpus[integrated_index] = gpus[gpu_count - 1]; + + /* FIXME: + * Find the dedicated GPU in an automatic graphics switching pair and use that as primary GPU. + * Choose the first dedicated GPU as primary */ + if (primary_index == integrated_index) + primary_index = 0; + else if (primary_index == gpu_count - 1) + primary_index = integrated_index; + + gpu_count--; + } + } + + /* Make sure the first GPU is primary */ + if (primary_index) + { + struct macdrv_gpu tmp; + tmp = gpus[0]; + gpus[0] = gpus[primary_index]; + gpus[primary_index] = tmp; + } + + *new_gpus = gpus; + *count = gpu_count; + ret = 0; +done: + if (ret) + macdrv_free_gpus(gpus); + return ret; +} + +/*********************************************************************** + * macdrv_get_gpus + * + * Get a list of GPUs currently in the system. The first GPU is primary. + * Call macdrv_free_gpus() when you are done using the data. + * + * Returns non-zero value on failure with parameters unchanged and zero on success. + */ +int macdrv_get_gpus(struct macdrv_gpu** new_gpus, int* count) +{ + return macdrv_get_gpus_from_iokit(new_gpus, count); +} + +/*********************************************************************** + * macdrv_free_gpus + * + * Frees a GPU list allocated from macdrv_get_gpus() + */ +void macdrv_free_gpus(struct macdrv_gpu* gpus) +{ + if (gpus) + free(gpus); +} diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index ed7766d1d4e..88f8f8f4f33 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -25,6 +25,13 @@ #include "winuser.h" #include "winreg.h" #include "ddrawi.h" +#include "rpc.h" +#include "initguid.h" +#include "devguid.h" +#include "devpkey.h" +#include "setupapi.h" +#define WIN32_NO_STATUS +#include "winternl.h" #include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(display); @@ -47,6 +54,30 @@ BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW
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 pciW[] = {'P','C','I',0}; +static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',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 CFArrayRef modes; @@ -1397,3 +1428,178 @@ void macdrv_displays_changed(const macdrv_event *event) MAKELPARAM(width, height)); } } + +/*********************************************************************** + * macdrv_init_gpu + * + * Initialize a GPU instance. + * + * Return FALSE on failure and TRUE on success. + */ +static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int gpu_index) +{ + static const BOOL present = TRUE; + SP_DEVINFO_DATA device_data = {sizeof(device_data)}; + WCHAR instanceW[MAX_PATH]; + WCHAR nameW[MAX_PATH]; + WCHAR bufferW[1024]; + FILETIME filetime; + HKEY hkey = NULL; + GUID guid; + 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; + } + + /* 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; + + /* 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); + + /* Write DriverDesc value */ + if (RegSetValueExW(hkey, driver_descW, 0, REG_SZ, (const BYTE *)nameW, (lstrlenW(nameW) + 1) * sizeof(WCHAR))) + 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; + RegCloseKey(hkey); + + /* 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; + } + + ret = TRUE; +done: + RegCloseKey(hkey); + if (!ret) + ERR("Failed to initialize GPU\n"); + return ret; +} + +static void prepare_devices(void) +{ + static const BOOL not_present = FALSE; + SP_DEVINFO_DATA device_data = {sizeof(device_data)}; + HDEVINFO devinfo; + DWORD i = 0; + + /* 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. */ + 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 *)¬_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_init_display_devices + * + * Initialize display device registry data. + */ +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; + HDEVINFO gpu_devinfo = NULL; + HKEY video_hkey = NULL; + DWORD disposition = 0; + + mutex = CreateMutexW(NULL, FALSE, init_mutexW); + WaitForSingleObject(mutex, INFINITE); + + 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 (disposition != REG_CREATED_NEW_KEY) + goto done; + + TRACE("\n"); + + prepare_devices(); + + gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL); + + /* Initialize GPUs */ + if (macdrv_get_gpus(&gpus, &gpu_count)) + goto done; + + for (gpu = 0; gpu < gpu_count; gpu++) + { + if (!macdrv_init_gpu(gpu_devinfo, &gpus[gpu], gpu)) + goto done; + } + +done: + cleanup_devices(); + SetupDiDestroyDeviceInfoList(gpu_devinfo); + RegCloseKey(video_hkey); + + ReleaseMutex(mutex); + CloseHandle(mutex); + + macdrv_free_gpus(gpus); +} diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 8b2f2cb5a38..b9f58b90da7 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -223,6 +223,7 @@ extern CGImageRef create_cgimage_from_icon_bitmaps(HDC hdc, HANDLE icon, HBITMAP extern void macdrv_status_item_mouse_move(const macdrv_event *event) DECLSPEC_HIDDEN;
extern void check_retina_status(void) DECLSPEC_HIDDEN; +extern void macdrv_init_display_devices(void) DECLSPEC_HIDDEN;
/************************************************************************** * Mac IME driver diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 8ca9b9afa0a..513746fa0ee 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -257,10 +257,27 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point)
/* display */ + +/* Represent a physical GPU in the PCI slots */ +struct macdrv_gpu +{ + /* PCI GPU io registry entry id */ + uint64_t id; + /* Name, in UTF-8 encoding */ + char name[128]; + /* PCI ID */ + uint32_t vendor_id; + uint32_t device_id; + uint32_t subsys_id; + uint32_t revision_id; +}; + 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;
/* event */
From: Zhiyi Zhang zzhang@codeweavers.com
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com Signed-off-by: Ken Thomases ken@codeweavers.com --- v3: Check if MTLCopyAllDevices() is available before calling it (for backward deployment).
dlls/winemac.drv/cocoa_display.m | 117 ++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m index b8f27309790..68ea89705d2 100644 --- a/dlls/winemac.drv/cocoa_display.m +++ b/dlls/winemac.drv/cocoa_display.m @@ -18,7 +18,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "config.h" + #import <AppKit/AppKit.h> +#ifdef HAVE_METAL_METAL_H +#import <Metal/Metal.h> +#endif #include "macdrv_cocoa.h"
@@ -227,6 +232,113 @@ static int macdrv_get_gpu_info_from_entry(struct macdrv_gpu* gpu, io_registry_en return ret; }
+#ifdef HAVE_METAL_METAL_H + +/*********************************************************************** + * macdrv_get_gpu_info_from_registry_id + * + * Get GPU information from a Metal device registry id. + * + * Returns non-zero value on failure. + */ +static int macdrv_get_gpu_info_from_registry_id(struct macdrv_gpu* gpu, uint64_t registry_id) +{ + int ret; + io_registry_entry_t entry; + + entry = IOServiceGetMatchingService(kIOMasterPortDefault, IORegistryEntryIDMatching(registry_id)); + ret = macdrv_get_gpu_info_from_entry(gpu, entry); + IOObjectRelease(entry); + return ret; +} + +/*********************************************************************** + * macdrv_get_gpus_from_metal + * + * Get a list of GPUs from Metal. + * + * Returns non-zero value on failure with parameters unchanged and zero on success. + */ +static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) +{ + struct macdrv_gpu* gpus = NULL; + struct macdrv_gpu primary_gpu; + id<MTLDevice> primary_device; + BOOL hide_integrated = FALSE; + int primary_index = 0, i; + int gpu_count = 0; + int ret = -1; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + /* Test if Metal is available */ + if (&MTLCopyAllDevices == NULL) + goto done; + NSArray<id<MTLDevice>>* devices = [MTLCopyAllDevices() autorelease]; + if (!devices.count || ![devices[0] respondsToSelector:@selector(registryID)]) + goto done; + + gpus = calloc(devices.count, sizeof(*gpus)); + if (!gpus) + goto done; + + /* Use MTLCreateSystemDefaultDevice instead of CGDirectDisplayCopyCurrentMetalDevice(CGMainDisplayID()) to get + * the primary GPU because we need to hide the integrated GPU for an automatic graphic switching pair to avoid apps + * using the integrated GPU. This is the behavior of Windows on a Mac. */ + primary_device = [MTLCreateSystemDefaultDevice() autorelease]; + if (macdrv_get_gpu_info_from_registry_id(&primary_gpu, primary_device.registryID)) + goto done; + + /* Hide the integrated GPU if the system default device is a dedicated GPU */ + if (!primary_device.isLowPower) + { + hide_integrated = TRUE; + } + + for (i = 0; i < devices.count; i++) + { + if (macdrv_get_gpu_info_from_registry_id(&gpus[gpu_count], devices[i].registryID)) + goto done; + + if (hide_integrated && devices[i].isLowPower) + { + continue; + } + + if (gpus[gpu_count].id == primary_gpu.id) + primary_index = gpu_count; + + gpu_count++; + } + + /* Make sure the first GPU is primary */ + if (primary_index) + { + struct macdrv_gpu tmp; + tmp = gpus[0]; + gpus[0] = gpus[primary_index]; + gpus[primary_index] = tmp; + } + + *new_gpus = gpus; + *count = gpu_count; + ret = 0; +done: + if (ret) + macdrv_free_gpus(gpus); + [pool release]; + return ret; +} + +#else + +static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) +{ + TRACE("Metal support not compiled in\n"); + return -1; +} + +#endif + /*********************************************************************** * macdrv_get_gpu_info_from_display_id * @@ -348,7 +460,10 @@ 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) { - return macdrv_get_gpus_from_iokit(new_gpus, count); + if (!macdrv_get_gpus_from_metal(new_gpus, count)) + return 0; + else + return macdrv_get_gpus_from_iokit(new_gpus, count); }
/***********************************************************************
From: Zhiyi Zhang zzhang@codeweavers.com
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com Signed-off-by: Ken Thomases ken@codeweavers.com --- dlls/winemac.drv/cocoa_display.m | 99 +++++++++++++++++++++++ dlls/winemac.drv/display.c | 134 +++++++++++++++++++++++++++++-- dlls/winemac.drv/macdrv_cocoa.h | 15 ++++ 3 files changed, 241 insertions(+), 7 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m index 68ea89705d2..284ffe0a535 100644 --- a/dlls/winemac.drv/cocoa_display.m +++ b/dlls/winemac.drv/cocoa_display.m @@ -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); +} diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 88f8f8f4f33..97ebca22e57 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -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); } diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 513746fa0ee..b960e902e3f 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -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 */
From: Zhiyi Zhang zzhang@codeweavers.com
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com Signed-off-by: Ken Thomases ken@codeweavers.com --- v3: Fix which variable is used to index into which array. Stop checking displays after finding a match. Take advantage of the fact that the primary display is always index 0 in the array returned from macdrv_get_displays().
dlls/winemac.drv/cocoa_display.m | 109 +++++++++++++++++++++++++++++++ dlls/winemac.drv/display.c | 103 +++++++++++++++++++++++++++-- dlls/winemac.drv/macdrv_cocoa.h | 14 ++++ dlls/winemac.drv/macdrv_main.c | 2 + 4 files changed, 223 insertions(+), 5 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m index 284ffe0a535..0459462f06c 100644 --- a/dlls/winemac.drv/cocoa_display.m +++ b/dlls/winemac.drv/cocoa_display.m @@ -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); +} diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 97ebca22e57..a953e0c5746 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -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); } diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index b960e902e3f..96ebb97e764 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -261,6 +261,9 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point) /* 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 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point) 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_set_display_mode(const struct macdrv_display* display, 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 */ diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index 544d448f9fa..038578491f2 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -299,6 +299,8 @@ static BOOL process_attach(void) return FALSE; }
+ macdrv_init_display_devices(); + return TRUE; }
From: Zhiyi Zhang zzhang@codeweavers.com
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com Signed-off-by: Ken Thomases ken@codeweavers.com --- dlls/winemac.drv/display.c | 8 ++++++-- dlls/winemac.drv/macdrv.h | 2 +- dlls/winemac.drv/macdrv_main.c | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index a953e0c5746..236f63d5633 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -946,6 +946,8 @@ better: SendMessageW(GetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp, MAKELPARAM(width, height)); ret = DISP_CHANGE_SUCCESSFUL; + + macdrv_init_display_devices(TRUE); } else { @@ -1452,6 +1454,8 @@ void macdrv_displays_changed(const macdrv_event *event) free_display_mode_descriptor(desc); CGDisplayModeRelease(mode);
+ macdrv_init_display_devices(TRUE); + if (is_original && retina_enabled) { width *= 2; @@ -1728,7 +1732,7 @@ static void cleanup_devices(void) * * Initialize display device registry data. */ -void macdrv_init_display_devices(void) +void macdrv_init_display_devices(BOOL force) { 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; @@ -1755,7 +1759,7 @@ void macdrv_init_display_devices(void) }
/* Avoid unnecessary reinit */ - if (disposition != REG_CREATED_NEW_KEY) + if (!force && disposition != REG_CREATED_NEW_KEY) goto done;
TRACE("\n"); diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index b9f58b90da7..a7c0b4cac87 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -223,7 +223,7 @@ extern CGImageRef create_cgimage_from_icon_bitmaps(HDC hdc, HANDLE icon, HBITMAP extern void macdrv_status_item_mouse_move(const macdrv_event *event) DECLSPEC_HIDDEN;
extern void check_retina_status(void) DECLSPEC_HIDDEN; -extern void macdrv_init_display_devices(void) DECLSPEC_HIDDEN; +extern void macdrv_init_display_devices(BOOL force) DECLSPEC_HIDDEN;
/************************************************************************** * Mac IME driver diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index 038578491f2..694a46b11e6 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -299,7 +299,7 @@ static BOOL process_attach(void) return FALSE; }
- macdrv_init_display_devices(); + macdrv_init_display_devices(FALSE);
return TRUE; }
From: Zhiyi Zhang zzhang@codeweavers.com
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com Signed-off-by: Ken Thomases ken@codeweavers.com --- dlls/winemac.drv/cocoa_display.m | 2 + dlls/winemac.drv/display.c | 154 ++++-------------------------- dlls/winemac.drv/macdrv_cocoa.h | 4 + dlls/winemac.drv/winemac.drv.spec | 2 - 4 files changed, 26 insertions(+), 136 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m index 0459462f06c..3863557d96a 100644 --- a/dlls/winemac.drv/cocoa_display.m +++ b/dlls/winemac.drv/cocoa_display.m @@ -647,6 +647,8 @@ int macdrv_get_monitors(uint32_t adapter_id, struct macdrv_monitor** new_monitor
strcpy(monitors[monitor_count].name, "Generic Non-PnP Monitor"); monitors[monitor_count].state_flags = DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE; + monitors[monitor_count].rc_monitor = displays[j].frame; + monitors[monitor_count].rc_work = displays[j].work_frame; monitor_count++; break; } diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 236f63d5633..cb9f1ebcab9 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -53,6 +53,9 @@ BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW
/* 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}; @@ -64,6 +67,7 @@ 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 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','-', @@ -128,18 +132,6 @@ static CRITICAL_SECTION modes_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static BOOL inited_original_display_mode;
- -static inline HMONITOR display_id_to_monitor(CGDirectDisplayID display_id) -{ - return (HMONITOR)(UINT_PTR)display_id; -} - -static inline CGDirectDisplayID monitor_to_display_id(HMONITOR handle) -{ - return (CGDirectDisplayID)(UINT_PTR)handle; -} - - static BOOL get_display_device_reg_key(char *key, unsigned len) { static const char display_device_guid_prop[] = "__wine_display_device_guid"; @@ -969,76 +961,6 @@ better: return ret; }
- -/*********************************************************************** - * EnumDisplayMonitors (MACDRV.@) - */ -BOOL CDECL macdrv_EnumDisplayMonitors(HDC hdc, LPRECT rect, MONITORENUMPROC proc, LPARAM lparam) -{ - struct macdrv_display *displays; - int num_displays; - int i; - BOOL ret = TRUE; - - TRACE("%p, %s, %p, %#lx\n", hdc, wine_dbgstr_rect(rect), proc, lparam); - - if (hdc) - { - POINT origin; - RECT limit; - - if (!GetDCOrgEx(hdc, &origin)) return FALSE; - if (GetClipBox(hdc, &limit) == ERROR) return FALSE; - - if (rect && !IntersectRect(&limit, &limit, rect)) return TRUE; - - if (macdrv_get_displays(&displays, &num_displays)) - return FALSE; - - for (i = 0; i < num_displays; i++) - { - RECT monrect = rect_from_cgrect(displays[i].frame); - OffsetRect(&monrect, -origin.x, -origin.y); - if (IntersectRect(&monrect, &monrect, &limit)) - { - HMONITOR monitor = display_id_to_monitor(displays[i].displayID); - TRACE("monitor %d handle %p @ %s\n", i, monitor, wine_dbgstr_rect(&monrect)); - if (!proc(monitor, hdc, &monrect, lparam)) - { - ret = FALSE; - break; - } - } - } - } - else - { - if (macdrv_get_displays(&displays, &num_displays)) - return FALSE; - - for (i = 0; i < num_displays; i++) - { - RECT monrect = rect_from_cgrect(displays[i].frame); - RECT unused; - if (!rect || IntersectRect(&unused, &monrect, rect)) - { - HMONITOR monitor = display_id_to_monitor(displays[i].displayID); - TRACE("monitor %d handle %p @ %s\n", i, monitor, wine_dbgstr_rect(&monrect)); - if (!proc(monitor, 0, &monrect, lparam)) - { - ret = FALSE; - break; - } - } - } - } - - macdrv_free_displays(displays); - - return ret; -} - - /*********************************************************************** * EnumDisplaySettingsEx (MACDRV.@) * @@ -1323,58 +1245,6 @@ done: return ret; }
- -/*********************************************************************** - * GetMonitorInfo (MACDRV.@) - */ -BOOL CDECL macdrv_GetMonitorInfo(HMONITOR monitor, LPMONITORINFO info) -{ - static const WCHAR adapter_name[] = { '\','\','.','\','D','I','S','P','L','A','Y','1',0 }; - struct macdrv_display *displays; - int num_displays; - CGDirectDisplayID display_id; - int i; - - TRACE("%p, %p\n", monitor, info); - - if (macdrv_get_displays(&displays, &num_displays)) - { - ERR("couldn't get display list\n"); - SetLastError(ERROR_GEN_FAILURE); - return FALSE; - } - - display_id = monitor_to_display_id(monitor); - for (i = 0; i < num_displays; i++) - { - if (displays[i].displayID == display_id) - break; - } - - if (i < num_displays) - { - info->rcMonitor = rect_from_cgrect(displays[i].frame); - info->rcWork = rect_from_cgrect(displays[i].work_frame); - - info->dwFlags = (i == 0) ? MONITORINFOF_PRIMARY : 0; - - if (info->cbSize >= sizeof(MONITORINFOEXW)) - lstrcpyW(((MONITORINFOEXW*)info)->szDevice, adapter_name); - - TRACE(" -> rcMonitor %s rcWork %s dwFlags %08x\n", wine_dbgstr_rect(&info->rcMonitor), - wine_dbgstr_rect(&info->rcWork), info->dwFlags); - } - else - { - ERR("invalid monitor handle\n"); - SetLastError(ERROR_INVALID_HANDLE); - } - - macdrv_free_displays(displays); - return (i < num_displays); -} - - /*********************************************************************** * SetDeviceGammaRamp (MACDRV.@) */ @@ -1640,6 +1510,7 @@ static BOOL macdrv_init_monitor(HDEVINFO devinfo, const struct macdrv_monitor *m WCHAR nameW[MAX_PATH]; WCHAR bufferW[MAX_PATH]; HKEY hkey; + RECT rect; BOOL ret = FALSE;
/* Create GUID_DEVCLASS_MONITOR instance */ @@ -1664,6 +1535,21 @@ static BOOL macdrv_init_monitor(HDEVINFO devinfo, const struct macdrv_monitor *m 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 */ + sprintfW(bufferW, adapter_name_fmtW, video_index + 1); + if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, DEVPROP_TYPE_STRING, + (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR), 0)) + goto done;
ret = TRUE; done: diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 96ebb97e764..676adb435bb 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -293,6 +293,10 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point) { /* Name, in UTF-8 encoding */ char name[128]; + /* as RcMonitor in MONITORINFO struct after conversion by rect_from_cgrect */ + CGRect rc_monitor; + /* as RcWork in MONITORINFO struct after conversion by rect_from_cgrect */ + CGRect rc_work; /* StateFlags in DISPLAY_DEVICE struct */ uint32_t state_flags; }; diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec index 6fa723a6904..39cf33370b4 100644 --- a/dlls/winemac.drv/winemac.drv.spec +++ b/dlls/winemac.drv/winemac.drv.spec @@ -12,14 +12,12 @@ @ cdecl CreateWindow(long) macdrv_CreateWindow @ cdecl DestroyCursorIcon(long) macdrv_DestroyCursorIcon @ cdecl DestroyWindow(long) macdrv_DestroyWindow -@ cdecl EnumDisplayMonitors(long ptr ptr long) macdrv_EnumDisplayMonitors @ cdecl EnumDisplaySettingsEx(ptr long ptr long) macdrv_EnumDisplaySettingsEx @ cdecl GetCursorPos(ptr) macdrv_GetCursorPos @ cdecl GetKeyboardLayout(long) macdrv_GetKeyboardLayout @ cdecl GetKeyboardLayoutList(long ptr) macdrv_GetKeyboardLayoutList @ cdecl GetKeyboardLayoutName(ptr) macdrv_GetKeyboardLayoutName @ cdecl GetKeyNameText(long ptr long) macdrv_GetKeyNameText -@ cdecl GetMonitorInfo(long ptr) macdrv_GetMonitorInfo @ cdecl MapVirtualKeyEx(long long long) macdrv_MapVirtualKeyEx @ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) macdrv_MsgWaitForMultipleObjectsEx @ cdecl RegisterHotKey(long long long) macdrv_RegisterHotKey