//
// 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 <angle_cl.h>

#include "libANGLE/CLBitField.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/CLObject.h"
#include "libANGLE/CLPlatform.h"
#include "libANGLE/Context.h"
#include "libANGLE/capture/FrameCapture.h"
#include "libANGLE/cl_types.h"
#include "libANGLE/cl_utils.h"

#include <cstdlib>
#include <cstring>
#include <mutex>

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(PlatformPtr::Create(createFuncs.front()));

        // 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(RefPointer<Device>::Create(*this, nullptr, createDatas.front().first,
                                                        createDatas.front().second));

        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
