// Copyright 2019 The Dawn Authors
//
// 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 "common/GPUInfo.h"

#include "common/Assert.h"

#include <algorithm>
#include <array>

namespace gpu_info {
    namespace {
        // Intel
        // Referenced from the following Mesa source code:
        // https://github.com/mesa3d/mesa/blob/master/include/pci_ids/i965_pci_ids.h
        // gen9
        const std::array<uint32_t, 25> Skylake = {
            {0x1902, 0x1906, 0x190A, 0x190B, 0x190E, 0x1912, 0x1913, 0x1915, 0x1916,
             0x1917, 0x191A, 0x191B, 0x191D, 0x191E, 0x1921, 0x1923, 0x1926, 0x1927,
             0x192A, 0x192B, 0x192D, 0x1932, 0x193A, 0x193B, 0x193D}};
        // gen9p5
        const std::array<uint32_t, 20> Kabylake = {
            {0x5916, 0x5913, 0x5906, 0x5926, 0x5921, 0x5915, 0x590E, 0x591E, 0x5912, 0x5917,
             0x5902, 0x591B, 0x593B, 0x590B, 0x591A, 0x590A, 0x591D, 0x5908, 0x5923, 0x5927}};
        const std::array<uint32_t, 17> Coffeelake = {
            {0x87CA, 0x3E90, 0x3E93, 0x3E99, 0x3E9C, 0x3E91, 0x3E92, 0x3E96, 0x3E98, 0x3E9A, 0x3E9B,
             0x3E94, 0x3EA9, 0x3EA5, 0x3EA6, 0x3EA7, 0x3EA8}};
        const std::array<uint32_t, 5> Whiskylake = {{0x3EA1, 0x3EA4, 0x3EA0, 0x3EA3, 0x3EA2}};
        const std::array<uint32_t, 21> Cometlake = {
            {0x9B21, 0x9BA0, 0x9BA2, 0x9BA4, 0x9BA5, 0x9BA8, 0x9BAA, 0x9BAB, 0x9BAC, 0x9B41, 0x9BC0,
             0x9BC2, 0x9BC4, 0x9BC5, 0x9BC6, 0x9BC8, 0x9BCA, 0x9BCB, 0x9BCC, 0x9BE6, 0x9BF6}};

        // According to Intel graphics driver version schema, build number is generated from the
        // last two fields.
        // See https://www.intel.com/content/www/us/en/support/articles/000005654/graphics.html for
        // more details.
        uint32_t GetIntelD3DDriverBuildNumber(const D3DDriverVersion& driverVersion) {
            return driverVersion[2] * 10000 + driverVersion[3];
        }

    }  // anonymous namespace

    bool IsAMD(PCIVendorID vendorId) {
        return vendorId == kVendorID_AMD;
    }
    bool IsARM(PCIVendorID vendorId) {
        return vendorId == kVendorID_ARM;
    }
    bool IsImgTec(PCIVendorID vendorId) {
        return vendorId == kVendorID_ImgTec;
    }
    bool IsIntel(PCIVendorID vendorId) {
        return vendorId == kVendorID_Intel;
    }
    bool IsNvidia(PCIVendorID vendorId) {
        return vendorId == kVendorID_Nvidia;
    }
    bool IsQualcomm(PCIVendorID vendorId) {
        return vendorId == kVendorID_Qualcomm;
    }
    bool IsSwiftshader(PCIVendorID vendorId, PCIDeviceID deviceId) {
        return vendorId == kVendorID_Google && deviceId == kDeviceID_Swiftshader;
    }
    bool IsWARP(PCIVendorID vendorId, PCIDeviceID deviceId) {
        return vendorId == kVendorID_Microsoft && deviceId == kDeviceID_WARP;
    }

    int CompareD3DDriverVersion(PCIVendorID vendorId,
                                const D3DDriverVersion& version1,
                                const D3DDriverVersion& version2) {
        if (IsIntel(vendorId)) {
            uint32_t buildNumber1 = GetIntelD3DDriverBuildNumber(version1);
            uint32_t buildNumber2 = GetIntelD3DDriverBuildNumber(version2);
            return buildNumber1 < buildNumber2 ? -1 : (buildNumber1 == buildNumber2 ? 0 : 1);
        }

        // TODO(crbug.com/dawn/823): support other GPU vendors
        UNREACHABLE();
        return 0;
    }

    // Intel GPUs
    bool IsSkylake(PCIDeviceID deviceId) {
        return std::find(Skylake.cbegin(), Skylake.cend(), deviceId) != Skylake.cend();
    }
    bool IsKabylake(PCIDeviceID deviceId) {
        return std::find(Kabylake.cbegin(), Kabylake.cend(), deviceId) != Kabylake.cend();
    }
    bool IsCoffeelake(PCIDeviceID deviceId) {
        return (std::find(Coffeelake.cbegin(), Coffeelake.cend(), deviceId) != Coffeelake.cend()) ||
               (std::find(Whiskylake.cbegin(), Whiskylake.cend(), deviceId) != Whiskylake.cend()) ||
               (std::find(Cometlake.cbegin(), Cometlake.cend(), deviceId) != Cometlake.cend());
    }
}  // namespace gpu_info
