//
// Copyright (c) 2013-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_win.cpp: implementation of the Windows-specific parts of SystemInfo.h

#include "gpu_info_util/SystemInfo_internal.h"

// Windows.h needs to be included first
#include <windows.h>

#if defined(GPU_INFO_USE_SETUPAPI)
#include <cfgmgr32.h>
#include <setupapi.h>
#elif defined(GPU_INFO_USE_DXGI)
#include <dxgi.h>
#include <d3d10.h>
#else
#error "SystemInfo_win needs at least GPU_INFO_USE_SETUPAPI or GPU_INFO_USE_DXGI defined"
#endif

#include <array>
#include <sstream>

namespace angle
{

namespace
{

#if defined(GPU_INFO_USE_SETUPAPI)

std::string GetRegistryStringValue(HKEY key, const char *valueName)
{
    std::array<char, 255> value;
    DWORD valueSize = sizeof(value);
    if (RegQueryValueExA(key, valueName, nullptr, nullptr, reinterpret_cast<LPBYTE>(value.data()),
                         &valueSize) == ERROR_SUCCESS)
    {
        return value.data();
    }
    return "";
}

// Gathers information about the devices from the registry. The reason why we aren't using
// a dedicated API such as DXGI is that we need information like the driver vendor and date.
// DXGI doesn't provide a way to know the device registry key from an IDXGIAdapter.
bool GetDevicesFromRegistry(std::vector<GPUDeviceInfo> *devices)
{
    // Display adapter class GUID from
    // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx
    GUID displayClass = {
        0x4d36e968, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};

    HDEVINFO deviceInfo = SetupDiGetClassDevsW(&displayClass, nullptr, nullptr, DIGCF_PRESENT);

    if (deviceInfo == INVALID_HANDLE_VALUE)
    {
        return false;
    }

    // This iterates over the devices of the "Display adapter" class
    DWORD deviceIndex = 0;
    SP_DEVINFO_DATA deviceData;
    deviceData.cbSize = sizeof(deviceData);
    while (SetupDiEnumDeviceInfo(deviceInfo, deviceIndex++, &deviceData))
    {
        // The device and vendor IDs can be gathered directly, but information about the driver
        // requires some registry digging
        char fullDeviceID[MAX_DEVICE_ID_LEN];
        if (CM_Get_Device_IDA(deviceData.DevInst, fullDeviceID, MAX_DEVICE_ID_LEN, 0) != CR_SUCCESS)
        {
            continue;
        }

        GPUDeviceInfo device;

        if (!CMDeviceIDToDeviceAndVendorID(fullDeviceID, &device.vendorId, &device.deviceId))
        {
            continue;
        }

        // The driver key will end with something like {<displayClass>}/<4 digit number>.
        std::array<WCHAR, 255> value;
        if (!SetupDiGetDeviceRegistryPropertyW(deviceInfo, &deviceData, SPDRP_DRIVER, nullptr,
                                               reinterpret_cast<PBYTE>(value.data()), sizeof(value),
                                               nullptr))
        {
            continue;
        }

        std::wstring driverKey = L"System\\CurrentControlSet\\Control\\Class\\";
        driverKey += value.data();

        HKEY key;
        if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.c_str(), 0, KEY_QUERY_VALUE, &key) !=
            ERROR_SUCCESS)
        {
            continue;
        }

        device.driverVersion = GetRegistryStringValue(key, "DriverVersion");
        device.driverDate    = GetRegistryStringValue(key, "DriverDate");
        device.driverVendor  = GetRegistryStringValue(key, "ProviderName");

        RegCloseKey(key);

        devices->push_back(device);
    }

    SetupDiDestroyDeviceInfoList(deviceInfo);

    return true;
}

#elif defined(GPU_INFO_USE_DXGI)

bool GetDevicesFromDXGI(std::vector<GPUDeviceInfo> *devices)
{
    IDXGIFactory *factory;
    if (!SUCCEEDED(CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&factory))))
    {
        return false;
    }

    UINT i                = 0;
    IDXGIAdapter *adapter = nullptr;
    while (factory->EnumAdapters(i++, &adapter) != DXGI_ERROR_NOT_FOUND)
    {
        DXGI_ADAPTER_DESC desc;
        adapter->GetDesc(&desc);

        LARGE_INTEGER umdVersion;
        if (adapter->CheckInterfaceSupport(__uuidof(ID3D10Device), &umdVersion) ==
            DXGI_ERROR_UNSUPPORTED)
        {
            adapter->Release();
            continue;
        }

        // The UMD driver version here is the same as in the registry except for the last number.
        uint64_t intVersion = umdVersion.QuadPart;
        std::ostringstream o;

        const uint64_t kMask = 0xFF;
        o << ((intVersion >> 48) & kMask) << ".";
        o << ((intVersion >> 32) & kMask) << ".";
        o << ((intVersion >> 16) & kMask) << ".";
        o << (intVersion & kMask);

        GPUDeviceInfo device;
        device.vendorId      = desc.VendorId;
        device.deviceId      = desc.DeviceId;
        device.driverVersion = o.str();

        devices->push_back(device);

        adapter->Release();
    }

    factory->Release();

    return true;
}

#else
#error
#endif

}  // anonymous namespace

bool GetSystemInfo(SystemInfo *info)
{
#if defined(GPU_INFO_USE_SETUPAPI)
    if (!GetDevicesFromRegistry(&info->gpus))
    {
        return false;
    }
#elif defined(GPU_INFO_USE_DXGI)
    if (!GetDevicesFromDXGI(&info->gpus))
    {
        return false;
    }
#else
#error
#endif

    if (info->gpus.size() == 0)
    {
        return false;
    }

    FindPrimaryGPU(info);

    // nvd3d9wrap.dll is loaded into all processes when Optimus is enabled.
    HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll");
    info->isOptimus    = nvd3d9wrap != nullptr;

    return true;
}

}  // namespace angle
