//
// Copyright 2021 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.
//
// CLPlatform.cpp: Implements the cl::Platform class.
//

#include "common/unsafe_buffers.h"
#include "libANGLE/Context.h"
#include "libANGLE/capture/FrameCapture.h"

#include "libANGLE/CLPlatform.h"

#include "entry_points_utils.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/CLDevice.h"
#include "libANGLE/cl_utils.h"

#include <cstring>

namespace cl
{

namespace
{

Context::PropArray ParseContextProperties(const cl_context_properties *properties,
                                          Platform *&platform,
                                          bool &userSync)
{
    Context::PropArray propArray;
    if (properties != nullptr)
    {
        const cl_context_properties *propIt = properties;
        while (*propIt != 0)
        {
            switch (*ANGLE_UNSAFE_TODO(propIt++))
            {
                case CL_CONTEXT_PLATFORM:
                    platform = &reinterpret_cast<cl_platform_id>(*ANGLE_UNSAFE_TODO(propIt++))
                                    ->cast<Platform>();
                    break;
                case CL_CONTEXT_INTEROP_USER_SYNC:
                    userSync = *ANGLE_UNSAFE_TODO(propIt++) != CL_FALSE;
                    break;
            }
        }
        // Include the trailing zero
        ANGLE_UNSAFE_TODO(++propIt);
        propArray.reserve(propIt - properties);
        propArray.insert(propArray.cend(), properties, propIt);
    }
    return propArray;
}

}  // namespace

void Platform::Initialize(const cl_icd_dispatch &dispatch,
                          rx::CLPlatformImpl::CreateFuncs &&createFuncs)
{
    PlatformPtrs &platforms = GetPointers();
    ASSERT(_cl_platform_id::sDispatch == nullptr && platforms.empty());
    if (_cl_platform_id::sDispatch != nullptr || !platforms.empty())
    {
        ERR() << "Already initialized";
        return;
    }
    Dispatch::sDispatch = &dispatch;

    platforms.reserve(createFuncs.size());
    while (!createFuncs.empty())
    {
        platforms.emplace_back(new Platform(createFuncs.front()));

        // Release initialization reference, lifetime controlled by RefPointer.
        platforms.back()->release();

        // Remove platform on any errors
        if (!platforms.back()->mInfo.isValid() || platforms.back()->mDevices.empty())
        {
            platforms.pop_back();
        }

        createFuncs.pop_front();
    }
}

angle::Result Platform::GetPlatformIDs(cl_uint numEntries,
                                       cl_platform_id *platforms,
                                       cl_uint *numPlatforms)
{
    const PlatformPtrs &availPlatforms = GetPlatforms();
    if (numPlatforms != nullptr)
    {
        *numPlatforms = static_cast<cl_uint>(availPlatforms.size());
    }
    if (platforms != nullptr)
    {
        cl_uint entry   = 0u;
        auto platformIt = availPlatforms.cbegin();
        while (entry < numEntries && platformIt != availPlatforms.cend())
        {
            ANGLE_UNSAFE_TODO(platforms[entry++]) = (*platformIt++).get();
        }
    }
    return angle::Result::Continue;
}

angle::Result Platform::getInfo(PlatformInfo name,
                                size_t valueSize,
                                void *value,
                                size_t *valueSizeRet) const
{
    const void *copyValue = nullptr;
    size_t copySize       = 0u;

    switch (name)
    {
        case PlatformInfo::Profile:
            copyValue = mInfo.profile.c_str();
            copySize  = mInfo.profile.length() + 1u;
            break;
        case PlatformInfo::Version:
            copyValue = mInfo.versionStr.c_str();
            copySize  = mInfo.versionStr.length() + 1u;
            break;
        case PlatformInfo::NumericVersion:
            copyValue = &mInfo.version;
            copySize  = sizeof(mInfo.version);
            break;
        case PlatformInfo::Name:
            copyValue = mInfo.name.c_str();
            copySize  = mInfo.name.length() + 1u;
            break;
        case PlatformInfo::Vendor:
            copyValue = kVendor;
            copySize  = sizeof(kVendor);
            break;
        case PlatformInfo::Extensions:
            copyValue = mInfo.extensions.c_str();
            copySize  = mInfo.extensions.length() + 1u;
            break;
        case PlatformInfo::ExtensionsWithVersion:
            copyValue = mInfo.extensionsWithVersion.data();
            copySize  = mInfo.extensionsWithVersion.size() *
                       sizeof(decltype(mInfo.extensionsWithVersion)::value_type);
            break;
        case PlatformInfo::HostTimerResolution:
            copyValue = &mInfo.hostTimerRes;
            copySize  = sizeof(mInfo.hostTimerRes);
            break;
        case PlatformInfo::IcdSuffix:
            copyValue = kIcdSuffix;
            copySize  = sizeof(kIcdSuffix);
            break;
        case PlatformInfo::ExternalMemory:
            copyValue = mInfo.externalMemoryHandleSupportList.data();
            copySize  = mInfo.externalMemoryHandleSupportList.size() *
                       sizeof(*mInfo.externalMemoryHandleSupportList.data());
            break;
        default:
            ASSERT(false);
            ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
    }

    if (value != nullptr)
    {
        // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
        // as specified in the OpenCL Platform Queries table, and param_value is not a NULL value.
        if (valueSize < copySize)
        {
            ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
        }
        if (copyValue != nullptr)
        {
            ANGLE_UNSAFE_TODO(std::memcpy(value, copyValue, copySize));
        }
    }
    if (valueSizeRet != nullptr)
    {
        *valueSizeRet = copySize;
    }
    return angle::Result::Continue;
}

angle::Result Platform::getDeviceIDs(DeviceType deviceType,
                                     cl_uint numEntries,
                                     cl_device_id *devices,
                                     cl_uint *numDevices) const
{
    cl_uint found                = 0u;
    const bool requestForAll     = deviceType.intersects(CL_DEVICE_TYPE_ALL);
    const bool requestForDefault = deviceType.intersects(CL_DEVICE_TYPE_DEFAULT);

    for (const DevicePtr &device : mDevices)
    {
        // "default" and "all" types are edge cases
        if (requestForDefault || requestForAll)
        {
            if (devices != nullptr && found < numEntries)
            {
                ANGLE_UNSAFE_TODO(devices[found]) = device.get();
            }
            ++found;
            if (requestForDefault)
            {
                break;  // just return the 1st device as the "default"
            }
        }
        else
        {
            // otherwise, check for type-match
            if (IsDeviceTypeMatch(deviceType, device->getInfo().type))
            {
                if (devices != nullptr && found < numEntries)
                {
                    ANGLE_UNSAFE_TODO(devices[found]) = device.get();
                }
                ++found;
            }
        }
    }

    if (numDevices != nullptr)
    {
        *numDevices = found;
    }
    ASSERT(found != 0);

    return angle::Result::Continue;
}

bool Platform::hasDeviceType(DeviceType deviceType) const
{
    if (deviceType.intersects(CL_DEVICE_TYPE_DEFAULT | CL_DEVICE_TYPE_ALL))
    {
        return true;  // query-types are always valid/available
    }

    for (const DevicePtr &device : mDevices)
    {
        if (IsDeviceTypeMatch(deviceType, device->getInfo().type))
        {
            return true;
        }
    }
    return false;
}

cl_context Platform::CreateContext(const cl_context_properties *properties,
                                   cl_uint numDevices,
                                   const cl_device_id *devices,
                                   ContextErrorCB notify,
                                   void *userData)
{
    DevicePtrs devs;
    devs.reserve(numDevices);
    while (numDevices-- != 0u)
    {
        devs.emplace_back(&(*ANGLE_UNSAFE_TODO(devices++))->cast<Device>());
    }

    Platform *platform           = nullptr;
    bool userSync                = false;
    Context::PropArray propArray = ParseContextProperties(properties, platform, userSync);
    if (platform == nullptr)
    {
        // All devices in the list have already been validated at this point to contain the same
        // platform - just use/select the first device's platform.
        platform = &devs.front()->getPlatform();
    }

    return Object::Create<Context>(*platform, std::move(propArray), std::move(devs), notify,
                                   userData, userSync);
}

cl_context Platform::CreateContextFromType(const cl_context_properties *properties,
                                           DeviceType deviceType,
                                           ContextErrorCB notify,
                                           void *userData)
{
    Platform *platform           = nullptr;
    bool userSync                = false;
    Context::PropArray propArray = ParseContextProperties(properties, platform, userSync);

    // Choose default platform if user does not specify in the context properties field
    if (platform == nullptr)
    {
        platform = Platform::GetDefault();
    }

    return Object::Create<Context>(*platform, std::move(propArray), deviceType, notify, userData,
                                   userSync);
}

angle::Result Platform::unloadCompiler()
{
    return mImpl->unloadCompiler();
}

Platform::~Platform() = default;

Platform::Platform(const rx::CLPlatformImpl::CreateFunc &createFunc)
    : mImpl(createFunc(*this)),
      mDevices(mImpl ? createDevices(mImpl->createDevices()) : DevicePtrs{}),
      mInfo(mImpl ? mImpl->createInfo() : rx::CLPlatformImpl::Info{}),
      mMultiThreadPool(mImpl ? angle::WorkerThreadPool::Create(angle::ThreadPoolType::Asynchronous,
                                                               0,
                                                               ANGLEPlatformCurrent())
                             : nullptr)
{}

DevicePtrs Platform::createDevices(rx::CLDeviceImpl::CreateDatas &&createDatas)
{
    DevicePtrs devices;
    devices.reserve(createDatas.size());
    while (!createDatas.empty())
    {
        devices.emplace_back(
            new Device(*this, nullptr, createDatas.front().first, createDatas.front().second));
        // Release initialization reference, lifetime controlled by RefPointer.
        devices.back()->release();
        if (!devices.back()->mInfo.isValid())
        {
            devices.pop_back();
        }
        createDatas.pop_front();
    }
    return devices;
}

angle::FrameCaptureShared *Platform::getFrameCaptureShared()
{
    if (mFrameCaptureShared == nullptr)
    {
        mFrameCaptureShared = new angle::FrameCaptureShared;
    }
    return mFrameCaptureShared;
}

angle::FrameCaptureShared *Platform::mFrameCaptureShared = nullptr;
constexpr char Platform::kVendor[];
constexpr char Platform::kIcdSuffix[];

}  // namespace cl
