//
// 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.
//
// CLContext.h: Defines the cl::Context class, which manages OpenCL objects such as command-queues,
// memory, program and kernel objects and for executing kernels on one or more devices.

#ifndef LIBANGLE_CLCONTEXT_H_
#define LIBANGLE_CLCONTEXT_H_

#include <angle_cl.h>

#include "libANGLE/CLBitField.h"
#include "libANGLE/CLDevice.h"
#include "libANGLE/CLMemory.h"
#include "libANGLE/CLObject.h"
#include "libANGLE/CLPlatform.h"
#include "libANGLE/cl_utils.h"
#include "libANGLE/renderer/CLContextImpl.h"

#include <cstddef>
#include <string>

namespace cl
{

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

    static bool IsValidAndVersionOrNewer(const _cl_context *context, cl_uint major, cl_uint minor);

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

    angle::Result setDestructorCallback(ContextCB pfnNotify, void *userData);

    cl_command_queue createCommandQueueWithProperties(cl_device_id device,
                                                      const cl_queue_properties *properties);

    cl_command_queue createCommandQueue(cl_device_id device, CommandQueueProperties properties);

    cl_mem createBuffer(const cl_mem_properties *properties,
                        MemFlags flags,
                        size_t size,
                        void *hostPtr);

    cl_mem createImage(const cl_mem_properties *properties,
                       MemFlags flags,
                       const cl_image_format *format,
                       const cl_image_desc *desc,
                       void *hostPtr);

    cl_mem createImage2D(MemFlags flags,
                         const cl_image_format *format,
                         size_t width,
                         size_t height,
                         size_t rowPitch,
                         void *hostPtr);

    cl_mem createImage3D(MemFlags flags,
                         const cl_image_format *format,
                         size_t width,
                         size_t height,
                         size_t depth,
                         size_t rowPitch,
                         size_t slicePitch,
                         void *hostPtr);

    angle::Result getSupportedImageFormats(MemFlags flags,
                                           MemObjectType imageType,
                                           cl_uint numEntries,
                                           cl_image_format *imageFormats,
                                           cl_uint *numImageFormats) const;

    cl_sampler createSamplerWithProperties(const cl_sampler_properties *properties);

    cl_sampler createSampler(cl_bool normalizedCoords,
                             AddressingMode addressingMode,
                             FilterMode filterMode);

    cl_program createProgramWithSource(cl_uint count, const char **strings, const size_t *lengths);

    cl_program createProgramWithIL(const void *il, size_t length);

    cl_program createProgramWithBinary(cl_uint numDevices,
                                       const cl_device_id *devices,
                                       const size_t *lengths,
                                       const unsigned char **binaries,
                                       cl_int *binaryStatus);

    cl_program createProgramWithBuiltInKernels(cl_uint numDevices,
                                               const cl_device_id *devices,
                                               const char *kernelNames);

    cl_program linkProgram(cl_uint numDevices,
                           const cl_device_id *deviceList,
                           const char *options,
                           cl_uint numInputPrograms,
                           const cl_program *inputPrograms,
                           ProgramCB pfnNotify,
                           void *userData);

    cl_event createUserEvent();

    angle::Result waitForEvents(cl_uint numEvents, const cl_event *eventList);

  public:
    using PropArray = std::vector<cl_context_properties>;

    ~Context() override;

    const Platform &getPlatform() const noexcept;
    const DevicePtrs &getDevices() const;
    bool hasDevice(const _cl_device_id *device) const;

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

    bool supportsImages() const;
    bool supportsIL() const;
    bool supportsBuiltInKernel(const std::string &name) const;
    bool supportsImage2DFromBuffer() const;

  public:
    static void CL_CALLBACK ErrorCallback(const char *errinfo,
                                          const void *privateInfo,
                                          size_t cb,
                                          void *userData);
    static Memory::PropArray ConvertArmMemPropToMemProp(const cl_import_properties_arm *properties,
                                                        const void *handle);

  private:
    Context(Platform &platform,
            PropArray &&properties,
            DevicePtrs &&devices,
            ContextErrorCB notify,
            void *userData,
            bool userSync);

    Context(Platform &platform,
            PropArray &&properties,
            DeviceType deviceType,
            ContextErrorCB notify,
            void *userData,
            bool userSync);

    Platform &mPlatform;
    const PropArray mProperties;
    const ContextErrorCB mNotify;
    void *const mUserData;
    rx::CLContextImpl::Ptr mImpl;
    DevicePtrs mDevices;

    DestructorCallbacks<ContextCB> mDestructorCallbacks;

    friend class Object;
};

inline bool Context::IsValidAndVersionOrNewer(const _cl_context *context,
                                              cl_uint major,
                                              cl_uint minor)
{
    return IsValid(context) &&
           context->cast<Context>().getPlatform().isVersionOrNewer(major, minor);
}

inline const Platform &Context::getPlatform() const noexcept
{
    return mPlatform;
}

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

inline bool Context::hasDevice(const _cl_device_id *device) const
{
    return std::find(mDevices.cbegin(), mDevices.cend(), device) != mDevices.cend();
}

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

inline bool Context::supportsImages() const
{
    return (std::find_if(mDevices.cbegin(), mDevices.cend(), [](const DevicePtr &ptr) {
                return ptr->getInfo().imageSupport == CL_TRUE;
            }) != mDevices.cend());
}

inline bool Context::supportsImage2DFromBuffer() const
{
    return (std::find_if(mDevices.cbegin(), mDevices.cend(), [](const DevicePtr &ptr) {
                return ptr->getInfo().khrImage2D_FromBuffer == true;
            }) != mDevices.cend());
}

inline bool Context::supportsIL() const
{
    return (std::find_if(mDevices.cbegin(), mDevices.cend(), [](const DevicePtr &ptr) {
                return !ptr->getInfo().IL_Version.empty();
            }) != mDevices.cend());
}

inline bool Context::supportsBuiltInKernel(const std::string &name) const
{
    return (std::find_if(mDevices.cbegin(), mDevices.cend(), [&](const DevicePtr &ptr) {
                return ptr->supportsBuiltInKernel(name);
            }) != mDevices.cend());
}

}  // namespace cl

#endif  // LIBANGLE_CLCONTEXT_H_
