//
// 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.h: Defines the cl::Platform class, which provides information about platform-specific
// OpenCL features.

#ifndef LIBANGLE_CLPLATFORM_H_
#define LIBANGLE_CLPLATFORM_H_

#include "libANGLE/CLObject.h"
#include "libANGLE/Context.h"

#include "common/WorkerThread.h"

#include "libANGLE/renderer/CLPlatformImpl.h"

#include "anglebase/no_destructor.h"

namespace cl
{

class Platform final : public _cl_platform_id, public Object
{
  public:
    // Front end entry functions, only called from OpenCL entry points

    static void Initialize(const cl_icd_dispatch &dispatch,
                           rx::CLPlatformImpl::CreateFuncs &&createFuncs);

    static Platform *GetDefault();
    static Platform *CastOrDefault(cl_platform_id platform);
    static bool IsValidOrDefault(const _cl_platform_id *platform);
    static bool IsDeviceTypeMatch(DeviceType select, DeviceType type);

    static angle::Result GetPlatformIDs(cl_uint numEntries,
                                        cl_platform_id *platforms,
                                        cl_uint *numPlatforms);

    angle::Result getInfo(PlatformInfo name,
                          size_t valueSize,
                          void *value,
                          size_t *valueSizeRet) const;

    angle::Result getDeviceIDs(DeviceType deviceType,
                               cl_uint numEntries,
                               cl_device_id *devices,
                               cl_uint *numDevices) const;

    bool hasDeviceType(DeviceType) const;

    static cl_context CreateContext(const cl_context_properties *properties,
                                    cl_uint numDevices,
                                    const cl_device_id *devices,
                                    ContextErrorCB notify,
                                    void *userData);

    static cl_context CreateContextFromType(const cl_context_properties *properties,
                                            DeviceType deviceType,
                                            ContextErrorCB notify,
                                            void *userData);

    angle::Result unloadCompiler();

  public:
    ~Platform() override;

    const rx::CLPlatformImpl::Info &getInfo() const;
    cl_version getVersion() const;
    bool isVersionOrNewer(cl_uint major, cl_uint minor) const;
    const DevicePtrs &getDevices() const;

    template <typename T = rx::CLPlatformImpl>
    T &getImpl() const;

    static const PlatformPtrs &GetPlatforms();

    static constexpr const char *GetVendor();

    const std::shared_ptr<angle::WorkerThreadPool> &getMultiThreadPool() const;

    angle::FrameCaptureShared *getFrameCaptureShared();

  private:
    explicit Platform(const rx::CLPlatformImpl::CreateFunc &createFunc);

    DevicePtrs createDevices(rx::CLDeviceImpl::CreateDatas &&createDatas);

    static PlatformPtrs &GetPointers();

    const rx::CLPlatformImpl::Ptr mImpl;
    const DevicePtrs mDevices;
    const rx::CLPlatformImpl::Info mInfo;
    std::shared_ptr<angle::WorkerThreadPool> mMultiThreadPool;

    static constexpr char kVendor[]    = "ANGLE";
    static constexpr char kIcdSuffix[] = "ANGLE";

    static angle::FrameCaptureShared *mFrameCaptureShared;
};

inline Platform *Platform::GetDefault()
{
    return GetPlatforms().empty() ? nullptr : GetPlatforms().front().get();
}

inline Platform *Platform::CastOrDefault(cl_platform_id platform)
{
    return platform != nullptr ? &platform->cast<Platform>() : GetDefault();
}

// Our CL implementation defines that a nullptr value chooses the platform that we provide as
// default, so this function returns true for a nullptr value if a default platform exists.
inline bool Platform::IsValidOrDefault(const _cl_platform_id *platform)
{
    return platform != nullptr ? IsValid(platform) : GetDefault() != nullptr;
}

inline bool Platform::IsDeviceTypeMatch(DeviceType select, DeviceType type)
{
    // The type 'DeviceType' is a bitfield, so it matches if any selected bit is set.
    // A custom device is an exception, which only matches if it was explicitly selected, see:
    // https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#clGetDeviceIDs
    return type == CL_DEVICE_TYPE_CUSTOM ? select == CL_DEVICE_TYPE_CUSTOM
                                         : type.intersects(select);
}

inline const rx::CLPlatformImpl::Info &Platform::getInfo() const
{
    return mInfo;
}

inline cl_version Platform::getVersion() const
{
    return mInfo.version;
}

inline bool Platform::isVersionOrNewer(cl_uint major, cl_uint minor) const
{
    return mInfo.version >= CL_MAKE_VERSION(major, minor, 0u);
}

inline const DevicePtrs &Platform::getDevices() const
{
    return mDevices;
}

template <typename T>
inline T &Platform::getImpl() const
{
    return static_cast<T &>(*mImpl);
}

inline const PlatformPtrs &Platform::GetPlatforms()
{
    return GetPointers();
}

constexpr const char *Platform::GetVendor()
{
    return kVendor;
}

inline const std::shared_ptr<angle::WorkerThreadPool> &Platform::getMultiThreadPool() const
{
    return mMultiThreadPool;
}

inline PlatformPtrs &Platform::GetPointers()
{
    static angle::base::NoDestructor<PlatformPtrs> sPointers;
    return *sPointers;
}

}  // namespace cl

#endif  // LIBANGLE_CLPLATFORM_H_
