tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SystemInfo.cpp (10971B)


      1 //
      2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // SystemInfo.cpp: implementation of the system-agnostic parts of SystemInfo.h
      8 
      9 #include "gpu_info_util/SystemInfo.h"
     10 
     11 #include <cstring>
     12 #include <iostream>
     13 #include <sstream>
     14 
     15 #include "anglebase/no_destructor.h"
     16 #include "common/debug.h"
     17 #include "common/string_utils.h"
     18 #include "common/system_utils.h"
     19 
     20 namespace angle
     21 {
     22 namespace
     23 {
     24 constexpr char kANGLEPreferredDeviceEnv[] = "ANGLE_PREFERRED_DEVICE";
     25 }
     26 
     27 std::string VendorName(VendorID vendor)
     28 {
     29    switch (vendor)
     30    {
     31        case kVendorID_AMD:
     32            return "AMD";
     33        case kVendorID_ARM:
     34            return "ARM";
     35        case kVendorID_Broadcom:
     36            return "Broadcom";
     37        case kVendorID_GOOGLE:
     38            return "Google";
     39        case kVendorID_ImgTec:
     40            return "ImgTec";
     41        case kVendorID_Intel:
     42            return "Intel";
     43        case kVendorID_Kazan:
     44            return "Kazan";
     45        case kVendorID_NVIDIA:
     46            return "NVIDIA";
     47        case kVendorID_Qualcomm:
     48            return "Qualcomm";
     49        case kVendorID_VeriSilicon:
     50            return "VeriSilicon";
     51        case kVendorID_Vivante:
     52            return "Vivante";
     53        case kVendorID_VMWare:
     54            return "VMWare";
     55        case kVendorID_Apple:
     56            return "Apple";
     57        case kVendorID_Microsoft:
     58            return "Microsoft";
     59        default:
     60            return "Unknown (" + std::to_string(vendor) + ")";
     61    }
     62 }
     63 
     64 GPUDeviceInfo::GPUDeviceInfo() = default;
     65 
     66 GPUDeviceInfo::~GPUDeviceInfo() = default;
     67 
     68 GPUDeviceInfo::GPUDeviceInfo(const GPUDeviceInfo &other) = default;
     69 
     70 SystemInfo::SystemInfo() = default;
     71 
     72 SystemInfo::~SystemInfo() = default;
     73 
     74 SystemInfo::SystemInfo(const SystemInfo &other) = default;
     75 
     76 bool SystemInfo::hasNVIDIAGPU() const
     77 {
     78    for (const GPUDeviceInfo &gpu : gpus)
     79    {
     80        if (IsNVIDIA(gpu.vendorId))
     81        {
     82            return true;
     83        }
     84    }
     85    return false;
     86 }
     87 
     88 bool SystemInfo::hasIntelGPU() const
     89 {
     90    for (const GPUDeviceInfo &gpu : gpus)
     91    {
     92        if (IsIntel(gpu.vendorId))
     93        {
     94            return true;
     95        }
     96    }
     97    return false;
     98 }
     99 
    100 bool SystemInfo::hasAMDGPU() const
    101 {
    102    for (const GPUDeviceInfo &gpu : gpus)
    103    {
    104        if (IsAMD(gpu.vendorId))
    105        {
    106            return true;
    107        }
    108    }
    109    return false;
    110 }
    111 
    112 std::optional<size_t> SystemInfo::getPreferredGPUIndex() const
    113 {
    114    std::string device = GetPreferredDeviceString();
    115    if (!device.empty())
    116    {
    117        for (size_t i = 0; i < gpus.size(); ++i)
    118        {
    119            std::string vendor = VendorName(gpus[i].vendorId);
    120            ToLower(&vendor);
    121            if (vendor == device)
    122                return i;
    123        }
    124    }
    125    return std::nullopt;
    126 }
    127 
    128 bool IsAMD(VendorID vendorId)
    129 {
    130    return vendorId == kVendorID_AMD;
    131 }
    132 
    133 bool IsARM(VendorID vendorId)
    134 {
    135    return vendorId == kVendorID_ARM;
    136 }
    137 
    138 bool IsBroadcom(VendorID vendorId)
    139 {
    140    return vendorId == kVendorID_Broadcom;
    141 }
    142 
    143 bool IsImgTec(VendorID vendorId)
    144 {
    145    return vendorId == kVendorID_ImgTec;
    146 }
    147 
    148 bool IsKazan(VendorID vendorId)
    149 {
    150    return vendorId == kVendorID_Kazan;
    151 }
    152 
    153 bool IsIntel(VendorID vendorId)
    154 {
    155    return vendorId == kVendorID_Intel;
    156 }
    157 
    158 bool IsNVIDIA(VendorID vendorId)
    159 {
    160    return vendorId == kVendorID_NVIDIA;
    161 }
    162 
    163 bool IsQualcomm(VendorID vendorId)
    164 {
    165    return vendorId == kVendorID_Qualcomm;
    166 }
    167 
    168 bool IsGoogle(VendorID vendorId)
    169 {
    170    return vendorId == kVendorID_GOOGLE;
    171 }
    172 
    173 bool IsVeriSilicon(VendorID vendorId)
    174 {
    175    return vendorId == kVendorID_VeriSilicon;
    176 }
    177 
    178 bool IsVMWare(VendorID vendorId)
    179 {
    180    return vendorId == kVendorID_VMWare;
    181 }
    182 
    183 bool IsVivante(VendorID vendorId)
    184 {
    185    return vendorId == kVendorID_Vivante;
    186 }
    187 
    188 bool IsApple(VendorID vendorId)
    189 {
    190    return vendorId == kVendorID_Apple;
    191 }
    192 
    193 bool IsMicrosoft(VendorID vendorId)
    194 {
    195    return vendorId == kVendorID_Microsoft;
    196 }
    197 
    198 bool ParseAMDBrahmaDriverVersion(const std::string &content, std::string *version)
    199 {
    200    const size_t begin = content.find_first_of("0123456789");
    201    if (begin == std::string::npos)
    202    {
    203        return false;
    204    }
    205 
    206    const size_t end = content.find_first_not_of("0123456789.", begin);
    207    if (end == std::string::npos)
    208    {
    209        *version = content.substr(begin);
    210    }
    211    else
    212    {
    213        *version = content.substr(begin, end - begin);
    214    }
    215    return true;
    216 }
    217 
    218 bool ParseAMDCatalystDriverVersion(const std::string &content, std::string *version)
    219 {
    220    std::istringstream stream(content);
    221 
    222    std::string line;
    223    while (std::getline(stream, line))
    224    {
    225        static const char kReleaseVersion[] = "ReleaseVersion=";
    226        if (line.compare(0, std::strlen(kReleaseVersion), kReleaseVersion) != 0)
    227        {
    228            continue;
    229        }
    230 
    231        if (ParseAMDBrahmaDriverVersion(line, version))
    232        {
    233            return true;
    234        }
    235    }
    236    return false;
    237 }
    238 
    239 bool ParseMacMachineModel(const std::string &identifier,
    240                          std::string *type,
    241                          int32_t *major,
    242                          int32_t *minor)
    243 {
    244    size_t numberLoc = identifier.find_first_of("0123456789");
    245    if (numberLoc == std::string::npos)
    246    {
    247        return false;
    248    }
    249 
    250    size_t commaLoc = identifier.find(',', numberLoc);
    251    if (commaLoc == std::string::npos || commaLoc >= identifier.size())
    252    {
    253        return false;
    254    }
    255 
    256    const char *numberPtr = &identifier[numberLoc];
    257    const char *commaPtr  = &identifier[commaLoc + 1];
    258    char *endPtr          = nullptr;
    259 
    260    int32_t majorTmp = static_cast<int32_t>(std::strtol(numberPtr, &endPtr, 10));
    261    if (endPtr == numberPtr)
    262    {
    263        return false;
    264    }
    265 
    266    int32_t minorTmp = static_cast<int32_t>(std::strtol(commaPtr, &endPtr, 10));
    267    if (endPtr == commaPtr)
    268    {
    269        return false;
    270    }
    271 
    272    *major = majorTmp;
    273    *minor = minorTmp;
    274    *type  = identifier.substr(0, numberLoc);
    275 
    276    return true;
    277 }
    278 
    279 bool CMDeviceIDToDeviceAndVendorID(const std::string &id, uint32_t *vendorId, uint32_t *deviceId)
    280 {
    281    unsigned int vendor = 0;
    282    unsigned int device = 0;
    283 
    284    bool success = id.length() >= 21 && HexStringToUInt(id.substr(8, 4), &vendor) &&
    285                   HexStringToUInt(id.substr(17, 4), &device);
    286 
    287    *vendorId = vendor;
    288    *deviceId = device;
    289    return success;
    290 }
    291 
    292 void GetDualGPUInfo(SystemInfo *info)
    293 {
    294    ASSERT(!info->gpus.empty());
    295 
    296    // On dual-GPU systems we assume the non-Intel GPU is the graphics one.
    297    // TODO: this is incorrect and problematic.  activeGPUIndex must be removed if it cannot be
    298    // determined correctly.  A potential solution is to create an OpenGL context and parse
    299    // GL_VENDOR.  Currently, our test infrastructure is relying on this information and incorrectly
    300    // applies test expectations on dual-GPU systems when the Intel GPU is active.
    301    // http://anglebug.com/6174.
    302    int active    = 0;
    303    bool hasIntel = false;
    304    for (size_t i = 0; i < info->gpus.size(); ++i)
    305    {
    306        if (IsIntel(info->gpus[i].vendorId))
    307        {
    308            hasIntel = true;
    309        }
    310        if (IsIntel(info->gpus[active].vendorId))
    311        {
    312            active = static_cast<int>(i);
    313        }
    314    }
    315 
    316    // Assume that a combination of NVIDIA or AMD with Intel means Optimus or AMD Switchable
    317    info->activeGPUIndex  = active;
    318    info->isOptimus       = hasIntel && IsNVIDIA(info->gpus[active].vendorId);
    319    info->isAMDSwitchable = hasIntel && IsAMD(info->gpus[active].vendorId);
    320 }
    321 
    322 void PrintSystemInfo(const SystemInfo &info)
    323 {
    324    std::cout << info.gpus.size() << " GPUs:\n";
    325 
    326    for (size_t i = 0; i < info.gpus.size(); i++)
    327    {
    328        const auto &gpu = info.gpus[i];
    329 
    330        std::cout << "  " << i << " - " << VendorName(gpu.vendorId) << " device id: 0x" << std::hex
    331                  << std::uppercase << gpu.deviceId << std::dec << ", revision id: 0x" << std::hex
    332                  << std::uppercase << gpu.revisionId << std::dec << ", system device id: 0x"
    333                  << std::hex << std::uppercase << gpu.systemDeviceId << std::dec << "\n";
    334        if (!gpu.driverVendor.empty())
    335        {
    336            std::cout << "       Driver Vendor: " << gpu.driverVendor << "\n";
    337        }
    338        if (!gpu.driverVersion.empty())
    339        {
    340            std::cout << "       Driver Version: " << gpu.driverVersion << "\n";
    341        }
    342        if (!gpu.driverDate.empty())
    343        {
    344            std::cout << "       Driver Date: " << gpu.driverDate << "\n";
    345        }
    346        if (gpu.detailedDriverVersion.major != 0 || gpu.detailedDriverVersion.minor != 0 ||
    347            gpu.detailedDriverVersion.subMinor != 0 || gpu.detailedDriverVersion.patch != 0)
    348        {
    349            std::cout << "       Detailed Driver Version:\n"
    350                      << "           major: " << gpu.detailedDriverVersion.major
    351                      << "           minor: " << gpu.detailedDriverVersion.minor
    352                      << "           subMinor: " << gpu.detailedDriverVersion.subMinor
    353                      << "           patch: " << gpu.detailedDriverVersion.patch << "\n";
    354        }
    355    }
    356 
    357    std::cout << "\n";
    358    std::cout << "Active GPU: " << info.activeGPUIndex << "\n";
    359 
    360    std::cout << "\n";
    361    std::cout << "Optimus: " << (info.isOptimus ? "true" : "false") << "\n";
    362    std::cout << "AMD Switchable: " << (info.isAMDSwitchable ? "true" : "false") << "\n";
    363    std::cout << "Mac Switchable: " << (info.isMacSwitchable ? "true" : "false") << "\n";
    364    std::cout << "Needs EAGL on Mac: " << (info.needsEAGLOnMac ? "true" : "false") << "\n";
    365 
    366    std::cout << "\n";
    367    if (!info.machineManufacturer.empty())
    368    {
    369        std::cout << "Machine Manufacturer: " << info.machineManufacturer << "\n";
    370    }
    371    if (info.androidSdkLevel != 0)
    372    {
    373        std::cout << "Android SDK Level: " << info.androidSdkLevel << "\n";
    374    }
    375    if (!info.machineModelName.empty())
    376    {
    377        std::cout << "Machine Model: " << info.machineModelName << "\n";
    378    }
    379    if (!info.machineModelVersion.empty())
    380    {
    381        std::cout << "Machine Model Version: " << info.machineModelVersion << "\n";
    382    }
    383    std::cout << std::endl;
    384 }
    385 
    386 VersionInfo ParseNvidiaDriverVersion(uint32_t version)
    387 {
    388    return {
    389        version >> 22,         // major
    390        version >> 14 & 0xff,  // minor
    391        version >> 6 & 0xff,   // subMinor
    392        version & 0x3f         // patch
    393    };
    394 }
    395 
    396 uint64_t GetSystemDeviceIdFromParts(uint32_t highPart, uint32_t lowPart)
    397 {
    398    return (static_cast<uint64_t>(highPart) << 32) | lowPart;
    399 }
    400 
    401 uint32_t GetSystemDeviceIdHighPart(uint64_t systemDeviceId)
    402 {
    403    return (systemDeviceId >> 32) & 0xffffffff;
    404 }
    405 
    406 uint32_t GetSystemDeviceIdLowPart(uint64_t systemDeviceId)
    407 {
    408    return systemDeviceId & 0xffffffff;
    409 }
    410 
    411 std::string GetPreferredDeviceString()
    412 {
    413    std::string device = angle::GetEnvironmentVar(kANGLEPreferredDeviceEnv);
    414    ToLower(&device);
    415    return device;
    416 }
    417 
    418 }  // namespace angle