//
// 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>
#define __uuidof(NAME) IID_##NAME

#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;
    // The CreateDXGIFactory function does not exist for Windows Store apps.
    // Instead, Windows Store apps use the CreateDXGIFactory1 function.
    if (!SUCCEEDED(CreateDXGIFactory1(__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.
    // GetModuleHandleW is desktop apps only.
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY==WINAPI_FAMILY_APP
    info->isOptimus = false;
#else
    HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll");
    info->isOptimus    = nvd3d9wrap != nullptr;
#endif


    return true;
}

}  // namespace angle
