blob: 885c8d0b59dcbc193d37623cfc3a466614f9a447 [file] [log] [blame]
// Copyright 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "host-common/opengl/NativeGpuInfo.h"
#include "host-common/opengl/macTouchOpenGL.h"
#include <CoreGraphics/CGDirectDisplay.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include <IOKit/IOTypes.h>
#include <IOKit/IOKitLib.h>
#include <string>
#include <vector>
#include <stdio.h>
typedef std::pair<uint32_t, uint32_t> GpuVendorDeviceId;
typedef std::vector<GpuVendorDeviceId> GpuVendorDeviceIdList;
// Based on code from:
// https://chromium.googlesource.com/chromium/src/gpu/+/e626016b34c63b7ff51bf9a6c20b37bcc18150c4/config/gpu_info_collector_mac.mm
// https://github.com/glfw/glfw/blob/e0a6772e5e4c672179fc69a90bcda3369792ed1f/src/cocoa_monitor.m
// GetEntryProperty():
// Return 0 if we couldn't find the property.
// The property values we use should not be 0, so it's OK to use 0 as failure.
uint32_t GetEntryProperty(io_registry_entry_t entry, CFStringRef property_name) {
CFDataRef ref(
static_cast<CFDataRef>(IORegistryEntrySearchCFProperty(
entry,
kIOServicePlane,
property_name,
kCFAllocatorDefault,
kIORegistryIterateRecursively | kIORegistryIterateParents)));
if (!ref)
return 0;
uint32_t value = 0;
const uint32_t* value_pointer =
reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(ref));
if (value_pointer != NULL)
value = *value_pointer;
CFRelease(ref);
return value;
}
static auto GetGPUInfoMac() {
GpuVendorDeviceIdList res;
io_iterator_t iter;
io_service_t serv = 0;
CFMutableDictionaryRef matching = IOServiceMatching("IODisplayConnect");
kern_return_t err = IOServiceGetMatchingServices(kIOMasterPortDefault,
matching,
&iter);
if (err) return res;
while ((serv = IOIteratorNext(iter)) != 0) {
uint32_t vendor_id = GetEntryProperty(serv, CFSTR("vendor-id"));
if (vendor_id) {
uint32_t device_id = GetEntryProperty(serv, CFSTR("device-id"));
if (device_id) {
res.push_back(std::make_pair(vendor_id, device_id));
}
}
}
return res;
}
void getGpuInfoListNative(GpuInfoList* out) {
// This call initializes a pixel format,
// which should update the IOKit stuff to the
// correct GPU that will actually be used
// while the emulator is running.
macTouchOpenGL();
auto gpulist = GetGPUInfoMac();
char vendoridbuf[64] = {};
char deviceidbuf[64] = {};
for (const auto& elt : gpulist) {
snprintf(vendoridbuf, sizeof(vendoridbuf), "%04x", elt.first);
snprintf(deviceidbuf, sizeof(deviceidbuf), "%04x", elt.second);
out->infos.emplace_back(
std::string(vendoridbuf), // make -> vendorid
std::string(deviceidbuf), // model -> deviceid
std::string(deviceidbuf), // device_id -> deviceid
"", "", "" // revision, version, renderer blank
);
}
}
// macOS: Disable Vulkan for now unless on M1.
bool isVulkanSafeToUseNative() {
#ifdef __aarch64__
return true;
#else
return false;
#endif
}