summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm')
-rw-r--r--src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm
new file mode 100644
index 0000000000..7a7a62d170
--- /dev/null
+++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm
@@ -0,0 +1,170 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SystemInfo_mac.cpp: implementation of the Mac-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#import <Cocoa/Cocoa.h>
+#import <IOKit/IOKitLib.h>
+
+namespace angle
+{
+
+namespace
+{
+
+std::string GetMachineModel()
+{
+ io_service_t platformExpert = IOServiceGetMatchingService(
+ kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
+
+ if (platformExpert == IO_OBJECT_NULL)
+ {
+ return "";
+ }
+
+ CFDataRef modelData = static_cast<CFDataRef>(
+ IORegistryEntryCreateCFProperty(platformExpert, CFSTR("model"), kCFAllocatorDefault, 0));
+ if (modelData == nullptr)
+ {
+ IOObjectRelease(platformExpert);
+ return "";
+ }
+
+ std::string result = reinterpret_cast<const char *>(CFDataGetBytePtr(modelData));
+
+ IOObjectRelease(platformExpert);
+ CFRelease(modelData);
+
+ return result;
+}
+
+// Extracts one integer property from a registry entry.
+bool GetEntryProperty(io_registry_entry_t entry, CFStringRef name, uint32_t *value)
+{
+ *value = 0;
+
+ CFDataRef data = static_cast<CFDataRef>(
+ IORegistryEntrySearchCFProperty(entry, kIOServicePlane, name, kCFAllocatorDefault,
+ kIORegistryIterateRecursively | kIORegistryIterateParents));
+
+ if (data == nullptr)
+ {
+ return false;
+ }
+
+ const uint32_t *valuePtr = reinterpret_cast<const uint32_t *>(CFDataGetBytePtr(data));
+
+ if (valuePtr == nullptr)
+ {
+ CFRelease(data);
+ return false;
+ }
+
+ *value = *valuePtr;
+ CFRelease(data);
+ return true;
+}
+
+// CGDisplayIOServicePort is deprecated as of macOS 10.9, but has no replacement, see
+// https://crbug.com/650837
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+// Find the info of the current GPU.
+bool GetActiveGPU(VendorID *vendorId, DeviceID *deviceId)
+{
+ io_registry_entry_t port = CGDisplayIOServicePort(kCGDirectMainDisplay);
+
+ return GetEntryProperty(port, CFSTR("vendor-id"), vendorId) &&
+ GetEntryProperty(port, CFSTR("device-id"), deviceId);
+}
+
+#pragma clang diagnostic pop
+
+// Gathers the vendor and device IDs for the PCI GPUs
+bool GetPCIDevices(std::vector<GPUDeviceInfo> *devices)
+{
+ // matchDictionary will be consumed by IOServiceGetMatchingServices, no need to release it.
+ CFMutableDictionaryRef matchDictionary = IOServiceMatching("IOPCIDevice");
+
+ io_iterator_t entryIterator;
+ if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchDictionary, &entryIterator) !=
+ kIOReturnSuccess)
+ {
+ return false;
+ }
+
+ io_registry_entry_t entry = IO_OBJECT_NULL;
+
+ while ((entry = IOIteratorNext(entryIterator)) != IO_OBJECT_NULL)
+ {
+ constexpr uint32_t kClassCodeDisplayVGA = 0x30000;
+ uint32_t classCode;
+ GPUDeviceInfo info;
+
+ if (GetEntryProperty(entry, CFSTR("class-code"), &classCode) &&
+ classCode == kClassCodeDisplayVGA &&
+ GetEntryProperty(entry, CFSTR("vendor-id"), &info.vendorId) &&
+ GetEntryProperty(entry, CFSTR("device-id"), &info.deviceId))
+ {
+ devices->push_back(info);
+ }
+
+ IOObjectRelease(entry);
+ }
+ IOObjectRelease(entryIterator);
+
+ return true;
+}
+
+} // anonymous namespace
+
+bool GetSystemInfo(SystemInfo *info)
+{
+ {
+ int32_t major = 0;
+ int32_t minor = 0;
+ ParseMacMachineModel(GetMachineModel(), &info->machineModelName, &major, &minor);
+ info->machineModelVersion = std::to_string(major) + "." + std::to_string(minor);
+ }
+
+ if (!GetPCIDevices(&(info->gpus)))
+ {
+ return false;
+ }
+
+ if (info->gpus.empty())
+ {
+ return false;
+ }
+
+ // Find the active GPU
+ {
+ VendorID activeVendor;
+ DeviceID activeDevice;
+ if (!GetActiveGPU(&activeVendor, &activeDevice))
+ {
+ return false;
+ }
+
+ for (size_t i = 0; i < info->gpus.size(); ++i)
+ {
+ if (info->gpus[i].vendorId == activeVendor && info->gpus[i].deviceId == activeDevice)
+ {
+ info->activeGPUIndex = i;
+ break;
+ }
+ }
+ }
+
+ FindPrimaryGPU(info);
+
+ return true;
+}
+
+} // namespace angle