/*
 * Copyright (c) 2019 Arm Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "arm_compute/runtime/CL/CLHelpers.h"

#include "arm_compute/core/CL/CLHelpers.h"
#include "arm_compute/core/Error.h"
#include "arm_compute/runtime/CL/CLRuntimeContext.h"

namespace
{
#if defined(ARM_COMPUTE_ASSERTS_ENABLED)
void printf_callback(const char *buffer, unsigned int len, size_t complete, void *user_data)
{
    ARM_COMPUTE_UNUSED(complete, user_data);
    printf("%.*s", len, buffer);
}
#endif /* defined(ARM_COMPUTE_ASSERTS_ENABLED) */

/** This initialises the properties vector with the configuration to be used when creating the opencl context
 *
 * @param[in] platform The opencl platform used to create the context
 * @param[in] device   The opencl device to be used to create the context
 * @param[in] prop     An array of properties to be initialised
 *
 * @note In debug builds, this function will enable cl_arm_printf if it's supported.
 *
 * @return A pointer to the context properties which can be used to create an opencl context
 */

void initialise_context_properties(const cl::Platform &platform, const cl::Device &device, std::array<cl_context_properties, 7> &prop)
{
    ARM_COMPUTE_UNUSED(device);
#if defined(ARM_COMPUTE_ASSERTS_ENABLED)
    // Query devices in the context for cl_arm_printf support
    if(arm_compute::device_supports_extension(device, "cl_arm_printf"))
    {
        // Create a cl_context with a printf_callback and user specified buffer size.
        std::array<cl_context_properties, 7> properties_printf =
        {
            CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(platform()),
            // Enable a printf callback function for this context.
            CL_PRINTF_CALLBACK_ARM, reinterpret_cast<cl_context_properties>(printf_callback),
            // Request a minimum printf buffer size of 4MB for devices in the
            // context that support this extension.
            CL_PRINTF_BUFFERSIZE_ARM, 0x1000,
            0
        };
        prop = properties_printf;
    }
    else
#endif // defined(ARM_COMPUTE_ASSERTS_ENABLED)
    {
        std::array<cl_context_properties, 3> properties =
        {
            CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(platform()),
            0
        };
        std::copy(properties.begin(), properties.end(), prop.begin());
    };
}
} //namespace

namespace arm_compute
{
std::tuple<cl::Context, cl::Device, cl_int>
create_opencl_context_and_device()
{
    ARM_COMPUTE_ERROR_ON(!opencl_is_available());
    std::vector<cl::Platform> platforms;
    cl::Platform::get(&platforms);
    ARM_COMPUTE_ERROR_ON_MSG(platforms.size() == 0, "Couldn't find any OpenCL platform");
    cl::Platform            p = platforms[0];
    cl::Device              device;
    std::vector<cl::Device> platform_devices;
    p.getDevices(CL_DEVICE_TYPE_DEFAULT, &platform_devices);
    ARM_COMPUTE_ERROR_ON_MSG(platform_devices.size() == 0, "Couldn't find any OpenCL device");
    device     = platform_devices[0];
    cl_int err = CL_SUCCESS;
    std::array<cl_context_properties, 7> properties = { 0, 0, 0, 0, 0, 0, 0 };
    initialise_context_properties(p, device, properties);
    cl::Context cl_context = cl::Context(device, properties.data(), nullptr, nullptr, &err);
    ARM_COMPUTE_ERROR_ON_MSG(err != CL_SUCCESS, "Failed to create OpenCL context");
    return std::make_tuple(cl_context, device, err);
}

void schedule_kernel_on_ctx(CLRuntimeContext *ctx, ICLKernel *kernel, bool flush)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(kernel);
    if(ctx)
    {
        ARM_COMPUTE_ERROR_ON(ctx->gpu_scheduler() == nullptr);
        ctx->gpu_scheduler()->enqueue(*kernel, flush);
    }
    else
    {
        CLScheduler::get().enqueue(*kernel, flush);
    }
}

} // namespace arm_compute
