/*
 * Copyright (c) 2017-2019 The Khronos Group Inc.
 *
 * 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.
 *
 * OpenCL is a trademark of Apple Inc. used under license by Khronos.
 */

#include "icd.h"
#include "icd_windows_dxgk.h"

#if defined(OPENCL_ICD_LOADER_REQUIRE_WDK)
#include <windows.h>

#ifndef NTSTATUS
typedef LONG NTSTATUS;
#define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023)
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif

#include <d3dkmthk.h>
#endif

bool khrIcdOsVendorsEnumerateDXGK(void)
{
    bool ret = false;
    int result = 0;
#if defined(OPENCL_ICD_LOADER_REQUIRE_WDK)
#if defined(DXGKDDI_INTERFACE_VERSION_WDDM2_4) && (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_4)
    // Get handle to GDI Runtime
    HMODULE h = LoadLibrary("gdi32.dll");
    if (h == NULL)
        return ret;

    if(GetProcAddress((HMODULE)h, "D3DKMTSubmitPresentBltToHwQueue")) // OS Version check
    {
        D3DKMT_ADAPTERINFO* pAdapterInfo = NULL;
        D3DKMT_ENUMADAPTERS2 EnumAdapters;
        NTSTATUS Status = STATUS_SUCCESS;

        char cszLibraryName[MAX_PATH] = { 0 };
        EnumAdapters.NumAdapters = 0;
        EnumAdapters.pAdapters = NULL;
        PFND3DKMT_ENUMADAPTERS2 pEnumAdapters2 = (PFND3DKMT_ENUMADAPTERS2)GetProcAddress((HMODULE)h, "D3DKMTEnumAdapters2");
        if (!pEnumAdapters2)
        {
            KHR_ICD_TRACE("GetProcAddress failed for D3DKMT_ENUMADAPTERS2\n");
            goto out;
        }
        while (1)
        {
            EnumAdapters.NumAdapters = 0;
            EnumAdapters.pAdapters = NULL;
            Status = pEnumAdapters2(&EnumAdapters);
            if (Status == STATUS_BUFFER_TOO_SMALL)
            {
                // Number of Adapters increased between calls, retry;
                continue;
            }
            else if (!NT_SUCCESS(Status))
            {
                KHR_ICD_TRACE("D3DKMT_ENUMADAPTERS2 status != SUCCESS\n");
                goto out;
            }
            break;
        }
        pAdapterInfo = (D3DKMT_ADAPTERINFO*)malloc(sizeof(D3DKMT_ADAPTERINFO)*(EnumAdapters.NumAdapters));
        if (pAdapterInfo == NULL)
        {
            KHR_ICD_TRACE("Allocation failure for AdapterInfo buffer\n");
            goto out;
        }
        EnumAdapters.pAdapters = pAdapterInfo;
        Status = pEnumAdapters2(&EnumAdapters);
        if (!NT_SUCCESS(Status))
        {
            KHR_ICD_TRACE("D3DKMT_ENUMADAPTERS2 status != SUCCESS\n");
            goto out;
        }
        const char* cszOpenCLRegKeyName = getOpenCLRegKeyName();
        const int szOpenCLRegKeyName = (int)(strlen(cszOpenCLRegKeyName) + 1)*sizeof(cszOpenCLRegKeyName[0]);
        for (UINT AdapterIndex = 0; AdapterIndex < EnumAdapters.NumAdapters; AdapterIndex++)
        {
            D3DDDI_QUERYREGISTRY_INFO queryArgs = {0};
            D3DDDI_QUERYREGISTRY_INFO* pQueryArgs = &queryArgs;
            D3DDDI_QUERYREGISTRY_INFO* pQueryBuffer = NULL;
            queryArgs.QueryType = D3DDDI_QUERYREGISTRY_ADAPTERKEY;
            queryArgs.QueryFlags.TranslatePath = TRUE;
            queryArgs.ValueType = REG_SZ;
            result = MultiByteToWideChar(
                CP_ACP,
                0,
                cszOpenCLRegKeyName,
                szOpenCLRegKeyName,
                queryArgs.ValueName,
                ARRAYSIZE(queryArgs.ValueName));
            if (!result)
            {
                KHR_ICD_TRACE("MultiByteToWideChar status != SUCCESS\n");
                continue;
            }
            D3DKMT_QUERYADAPTERINFO queryAdapterInfo = {0};
            queryAdapterInfo.hAdapter = pAdapterInfo[AdapterIndex].hAdapter;
            queryAdapterInfo.Type = KMTQAITYPE_QUERYREGISTRY;
            queryAdapterInfo.pPrivateDriverData = &queryArgs;
            queryAdapterInfo.PrivateDriverDataSize = sizeof(queryArgs);
            Status = D3DKMTQueryAdapterInfo(&queryAdapterInfo);
            if (!NT_SUCCESS(Status))
            {
                // Try a different value type.  Some vendors write the key as a multi-string type.
                queryArgs.ValueType = REG_MULTI_SZ;
                Status = D3DKMTQueryAdapterInfo(&queryAdapterInfo);
                if (NT_SUCCESS(Status))
                {
                    KHR_ICD_TRACE("Accepting multi-string registry key type\n");
                }
                else
                {
                    // Continue trying to get as much info on each adapter as possible.
                    // It's too late to return FALSE and claim WDDM2_4 enumeration is not available here.
                    continue;
                }
            }
            if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW)
            {
                ULONG queryBufferSize = sizeof(D3DDDI_QUERYREGISTRY_INFO) + queryArgs.OutputValueSize;
                pQueryBuffer = (D3DDDI_QUERYREGISTRY_INFO*)malloc(queryBufferSize);
                if (pQueryBuffer == NULL)
                    continue;
                memcpy(pQueryBuffer, &queryArgs, sizeof(D3DDDI_QUERYREGISTRY_INFO));
                queryAdapterInfo.pPrivateDriverData = pQueryBuffer;
                queryAdapterInfo.PrivateDriverDataSize = queryBufferSize;
                Status = D3DKMTQueryAdapterInfo(&queryAdapterInfo);
                pQueryArgs = pQueryBuffer;
            }
            if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_SUCCESS)
            {
                wchar_t* pWchar = pQueryArgs->OutputString;
                memset(cszLibraryName, 0, sizeof(cszLibraryName));
                {
                    size_t len = wcstombs(cszLibraryName, pWchar, sizeof(cszLibraryName));
                    KHR_ICD_ASSERT(len == (sizeof(cszLibraryName) - 1));
                    ret |= adapterAdd(cszLibraryName, pAdapterInfo[AdapterIndex].AdapterLuid);
                }
            }
            else if (Status == STATUS_INVALID_PARAMETER && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_FAIL)
            {
                free(pQueryBuffer);
                goto out;
            }
            free(pQueryBuffer);
        }
out:
      free(pAdapterInfo);
    }

    FreeLibrary(h);

#endif
#endif
    return ret;
}
