Fixes an Apple Silicon issue where CGDisplayIOServicePort() returns a fake AMD GPU "compatibility" node rather than the real GPU node.
Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- dlls/winemac.drv/cocoa_display.m | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m index e769772feaa..1125d29839c 100644 --- a/dlls/winemac.drv/cocoa_display.m +++ b/dlls/winemac.drv/cocoa_display.m @@ -330,6 +330,21 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) return ret; }
+/*********************************************************************** + * macdrv_get_gpu_info_from_display_id_using_metal + * + * Get GPU information for a CG display id using Metal. + * + * Returns non-zero value on failure. + */ +static int macdrv_get_gpu_info_from_display_id_using_metal(struct macdrv_gpu* gpu, CGDirectDisplayID display_id) +{ + id<MTLDevice> device = [CGDirectDisplayCopyCurrentMetalDevice(display_id) autorelease]; + if (!device || ![device respondsToSelector:@selector(registryID)]) + return -1; + return macdrv_get_gpu_info_from_registry_id(gpu, device.registryID); +} + #else
static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) @@ -337,6 +352,11 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) return -1; }
+static int macdrv_get_gpu_info_from_display_id_using_metal(struct macdrv_gpu* gpu, CGDirectDisplayID display_id) +{ + return -1; +} + #endif
/*********************************************************************** @@ -349,8 +369,16 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) */ 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); + int ret; + io_registry_entry_t entry; + + ret = macdrv_get_gpu_info_from_display_id_using_metal(gpu, display_id); + if (ret) + { + entry = CGDisplayIOServicePort(display_id); + ret = macdrv_get_gpu_info_from_entry(gpu, entry); + } + return ret; }
/***********************************************************************
Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- dlls/winemac.drv/cocoa_display.m | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m index 1125d29839c..1ea135d42ae 100644 --- a/dlls/winemac.drv/cocoa_display.m +++ b/dlls/winemac.drv/cocoa_display.m @@ -183,7 +183,9 @@ static int get_entry_property_string(io_registry_entry_t entry, CFStringRef prop /*********************************************************************** * 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. + * Starting from entry (which must be the GPU or a child below the GPU), + * search upwards to find the IOPCIDevice and get information from it. + * In case the GPU is not a PCI device, get properties from 'entry'. * * Returns non-zero value on failure. */ @@ -193,18 +195,21 @@ static int macdrv_get_gpu_info_from_entry(struct macdrv_gpu* gpu, io_registry_en 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")) + while (![@"IOPCIDevice" isEqualToString:[(NSString*)IOObjectCopyClass(gpu_entry) autorelease]]) { result = IORegistryEntryGetParentEntry(gpu_entry, kIOServicePlane, &parent_entry); if (gpu_entry != entry) IOObjectRelease(gpu_entry); - if (result != kIOReturnSuccess) + if (result == kIOReturnNoDevice) + { + /* If no IOPCIDevice node is found, get properties from the given entry. */ + gpu_entry = entry; + break; + } + else if (result != kIOReturnSuccess) { [pool release]; return ret; @@ -399,6 +404,7 @@ static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count) int integrated_index = -1; int primary_index = 0; int gpu_count = 0; + char buffer[64]; int ret = -1; int i;
@@ -412,7 +418,9 @@ static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count)
while ((entry = IOIteratorNext(iterator))) { - if (!macdrv_get_gpu_info_from_entry(&gpus[gpu_count], entry)) + if (!get_entry_property_string(entry, CFSTR("IOName"), buffer, sizeof(buffer)) && + !strcmp(buffer, "display") && + !macdrv_get_gpu_info_from_entry(&gpus[gpu_count], entry)) { gpu_count++; assert(gpu_count < MAX_GPUS);
On 11/19/20 7:54 AM, Brendan Shanks wrote:
Fixes an Apple Silicon issue where CGDisplayIOServicePort() returns a fake AMD GPU "compatibility" node rather than the real GPU node.
Signed-off-by: Brendan Shanks bshanks@codeweavers.com
dlls/winemac.drv/cocoa_display.m | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m index e769772feaa..1125d29839c 100644 --- a/dlls/winemac.drv/cocoa_display.m +++ b/dlls/winemac.drv/cocoa_display.m @@ -330,6 +330,21 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) return ret; }
+/***********************************************************************
macdrv_get_gpu_info_from_display_id_using_metal
- Get GPU information for a CG display id using Metal.
- Returns non-zero value on failure.
- */
+static int macdrv_get_gpu_info_from_display_id_using_metal(struct macdrv_gpu* gpu, CGDirectDisplayID display_id) +{
- id<MTLDevice> device = [CGDirectDisplayCopyCurrentMetalDevice(display_id) autorelease];
- if (!device || ![device respondsToSelector:@selector(registryID)])
return -1;
- return macdrv_get_gpu_info_from_registry_id(gpu, device.registryID);
+}
#else
static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) @@ -337,6 +352,11 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) return -1; }
+static int macdrv_get_gpu_info_from_display_id_using_metal(struct macdrv_gpu* gpu, CGDirectDisplayID display_id) +{
- return -1;
+}
#endif
/*********************************************************************** @@ -349,8 +369,16 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) */ static int macdrv_get_gpu_info_from_display_id(struct macdrv_gpu* gpu, CGDirectDisplayID display_id)
Let's update/move the comment "This is a fallback for 32bit build or older Mac OS version where Metal is unavailable." for this function since it can be used when Metal is available.
{
- io_registry_entry_t entry = CGDisplayIOServicePort(display_id);
- return macdrv_get_gpu_info_from_entry(gpu, entry);
- int ret;
- io_registry_entry_t entry;
- ret = macdrv_get_gpu_info_from_display_id_using_metal(gpu, display_id);
- if (ret)
- {
entry = CGDisplayIOServicePort(display_id);
ret = macdrv_get_gpu_info_from_entry(gpu, entry);
- }
- return ret;
}
/***********************************************************************