//
// 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.
//
// cl_utils.h: Helper functions for the CL front end

#ifndef LIBANGLE_CL_UTILS_H_
#define LIBANGLE_CL_UTILS_H_

#include "common/PackedCLEnums_autogen.h"
#include "libANGLE/renderer/FormatID_autogen.h"
#include "libANGLE/renderer/cl_types.h"

#include <stack>

#define ANGLE_CL_SET_ERROR(error) cl::gClErrorTls = error

#define ANGLE_CL_RETURN_ERROR(error) \
    do                               \
    {                                \
        cl::gClErrorTls = error;     \
        return angle::Result::Stop;  \
    } while (0)

#define ANGLE_CL_TRY(expression)                           \
    do                                                     \
    {                                                      \
        const cl_int ANGLE_LOCAL_VAR = expression;         \
        if (ANGLE_UNLIKELY(ANGLE_LOCAL_VAR != CL_SUCCESS)) \
        {                                                  \
            ANGLE_CL_RETURN_ERROR(ANGLE_LOCAL_VAR);        \
        }                                                  \
    } while (0)

#define ANGLE_CL_IMPL_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, static_cast<void>(0), (void))
#define ANGLE_CL_IMPL_TRY_ERROR(EXPR, ERROR) \
    ANGLE_TRY_TEMPLATE(EXPR, static_cast<void>(0), ANGLE_CL_RETURN_ERROR(ERROR); (void))

namespace cl
{

template <typename CallbackT>
class DestructorCallbacks final
{
  public:
    void add(CallbackT callback, void *userData) { mCallbacks->push({callback, userData}); }

    template <typename ObjectT>
    void invoke(ObjectT *object)
    {
        // Invoke callbacks in reverse registration order without holding the lock.
        CallbackStack callbacks;
        mCallbacks->swap(callbacks);
        while (!callbacks.empty())
        {
            const CallbackData callbackData = callbacks.top();
            callbacks.pop();
            callbackData.callback(object, callbackData.userData);
        }
    }

  private:
    struct CallbackData
    {
        CallbackT callback;
        void *userData;
    };

    using CallbackStack = std::stack<CallbackData>;

    angle::SynchronizedValue<CallbackStack> mCallbacks;
};

size_t GetChannelCount(cl_channel_order channelOrder);

size_t GetElementSize(const cl_image_format &image_format);

inline bool OverlapRegions(size_t offset1, size_t offset2, size_t size)
{
    // From https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html
    // The regions overlap if src_offset <= dst_offset <= src_offset + size - 1
    // or if dst_offset <= src_offset <= dst_offset + size - 1.
    return (offset1 <= offset2 && offset2 <= offset1 + size - 1u) ||
           (offset2 <= offset1 && offset1 <= offset2 + size - 1u);
}

inline constexpr ChannelMapping GetChannelOrderMapping(cl_channel_order order)
{
    switch (order)
    {
        case CL_BGRA:
            return {2, 1, 0, 3};  // B,G,R,A
        case CL_ARGB:
            return {3, 0, 1, 2};  // A,R,G,B
        case CL_A:
            return {3, 3, 3, 3};  // Alpha-only
        default:
            return {0, 1, 2, 3};  // R,G,B,A
    }
}

bool IsValidImageFormat(const cl_image_format *imageFormat, const rx::CLExtensions &extensions);

bool IsImageType(cl::MemObjectType memObjectType);
bool IsBufferType(cl::MemObjectType memObjectType);
bool IsArrayType(cl::MemObjectType memObjectType);
bool Is3DImage(cl::MemObjectType memObjectType);
bool Is2DImage(cl::MemObjectType memObjectType);
bool Is1DImage(cl::MemObjectType memObjectType);
bool Is1DImageBuffer(cl::MemObjectType memObjectType);

cl::Extents GetExtentFromDescriptor(cl::ImageDescriptor desc);
angle::FormatID GetImageAngleFormat(cl_image_format format);
bool IsDepthOrder(cl_channel_order channelOrder);

extern thread_local cl_int gClErrorTls;

}  // namespace cl

#endif  // LIBANGLE_CL_UTILS_H_
