/*
 * Copyright (c) 2016-2020 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 "src/core/CL/kernels/CLChannelCombineKernel.h"

#include "arm_compute/core/CL/CLKernelLibrary.h"
#include "arm_compute/core/CL/ICLMultiImage.h"
#include "arm_compute/core/CL/ICLTensor.h"
#include "arm_compute/core/CL/OpenCL.h"
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/MultiImageInfo.h"
#include "arm_compute/core/TensorInfo.h"
#include "arm_compute/core/Utils.h"
#include "arm_compute/core/Validate.h"
#include "src/core/helpers/WindowHelpers.h"

#include <set>
#include <string>

namespace arm_compute
{
namespace
{
constexpr unsigned int num_elems_processed_per_iteration = 16;
} // namespace

CLChannelCombineKernel::CLChannelCombineKernel()
    : _planes{ { nullptr } }, _output(nullptr), _output_multi(nullptr), _x_subsampling{ { 1, 1, 1 } }, _y_subsampling{ { 1, 1, 1 } }
{
}

void CLChannelCombineKernel::configure(const ICLTensor *plane0, const ICLTensor *plane1, const ICLTensor *plane2, const ICLTensor *plane3, ICLTensor *output)
{
    configure(CLKernelLibrary::get().get_compile_context(), plane0, plane1, plane2, plane3, output);
}

void CLChannelCombineKernel::configure(const CLCompileContext &compile_context, const ICLTensor *plane0, const ICLTensor *plane1, const ICLTensor *plane2, const ICLTensor *plane3, ICLTensor *output)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(plane0, plane1, plane2, output);
    ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(plane0);
    ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(plane1);
    ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(plane2);
    ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(output);

    ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(plane0, Format::U8);
    ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(plane1, Format::U8);
    ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(plane2, Format::U8);
    ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(output, Format::RGB888, Format::RGBA8888, Format::YUYV422, Format::UYVY422);

    ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(plane0, 1, DataType::U8);
    ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(plane1, 1, DataType::U8);
    ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(plane2, 1, DataType::U8);

    const Format output_format = output->info()->format();

    // Check if horizontal dimension of Y plane is even and validate horizontal sub-sampling dimensions for U and V planes
    if(Format::YUYV422 == output_format || Format::UYVY422 == output_format)
    {
        // Validate Y plane of input and output
        ARM_COMPUTE_ERROR_ON_TENSORS_NOT_EVEN(output_format, plane0, output);

        // Validate U and V plane of the input
        ARM_COMPUTE_ERROR_ON_TENSORS_NOT_SUBSAMPLED(output_format, plane0->info()->tensor_shape(), plane1, plane2);
    }

    _planes[0] = plane0;
    _planes[1] = plane1;
    _planes[2] = plane2;
    _planes[3] = nullptr;

    // Validate the last input tensor only for RGBA format
    if(Format::RGBA8888 == output_format)
    {
        ARM_COMPUTE_ERROR_ON_NULLPTR(plane3);
        ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(plane3);

        ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(plane3, Format::U8);
        ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(plane3, 1, DataType::U8);

        _planes[3] = plane3;
    }

    _output       = output;
    _output_multi = nullptr;

    // Half the processed elements for U and V channels due to horizontal sub-sampling of 2
    if(Format::YUYV422 == output_format || Format::UYVY422 == output_format)
    {
        _x_subsampling[1] = 2;
        _x_subsampling[2] = 2;
    }

    // Create kernel
    std::string kernel_name = "channel_combine_" + string_from_format(output_format);
    _kernel                 = create_kernel(compile_context, kernel_name);

    // Configure window
    Window win = calculate_max_window(*output->info(), Steps(num_elems_processed_per_iteration));

    AccessWindowHorizontal plane0_access(plane0->info(), 0, num_elems_processed_per_iteration);
    AccessWindowRectangle  plane1_access(plane1->info(), 0, 0, num_elems_processed_per_iteration, 1, 1.f / _x_subsampling[1], 1.f / _y_subsampling[1]);
    AccessWindowRectangle  plane2_access(plane2->info(), 0, 0, num_elems_processed_per_iteration, 1, 1.f / _x_subsampling[2], 1.f / _y_subsampling[2]);
    AccessWindowHorizontal plane3_access(plane3 == nullptr ? nullptr : plane3->info(), 0, num_elems_processed_per_iteration);
    AccessWindowHorizontal output_access(output->info(), 0, num_elems_processed_per_iteration);

    update_window_and_padding(win, plane0_access, plane1_access, plane2_access, plane3_access, output_access);

    ValidRegion valid_region = intersect_valid_regions(plane0->info()->valid_region(),
                                                       plane1->info()->valid_region(),
                                                       plane2->info()->valid_region());
    if(plane3 != nullptr)
    {
        valid_region = intersect_valid_regions(plane3->info()->valid_region(), valid_region);
    }
    output_access.set_valid_region(win, ValidRegion(valid_region.anchor, output->info()->tensor_shape()));

    ICLKernel::configure_internal(win);
}

void CLChannelCombineKernel::configure(const ICLImage *plane0, const ICLImage *plane1, const ICLImage *plane2, ICLMultiImage *output)
{
    configure(CLKernelLibrary::get().get_compile_context(), plane0, plane1, plane2, output);
}

void CLChannelCombineKernel::configure(const CLCompileContext &compile_context, const ICLImage *plane0, const ICLImage *plane1, const ICLImage *plane2, ICLMultiImage *output)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(plane0, plane1, plane2, output);
    ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(plane0);
    ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(plane1);
    ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(plane2);

    ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(plane0, Format::U8);
    ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(plane1, Format::U8);
    ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(plane2, Format::U8);
    ARM_COMPUTE_ERROR_ON_FORMAT_NOT_IN(output, Format::NV12, Format::NV21, Format::IYUV, Format::YUV444);

    ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(plane0, 1, DataType::U8);
    ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(plane1, 1, DataType::U8);
    ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(plane2, 1, DataType::U8);

    const Format output_format = output->info()->format();

    // Validate shape of Y plane to be even and shape of sub-sampling dimensions for U and V planes
    // Perform validation only for formats which require sub-sampling.
    if(Format::YUV444 != output_format)
    {
        // Validate Y plane of input and output
        ARM_COMPUTE_ERROR_ON_TENSORS_NOT_EVEN(output_format, plane0, output->plane(0));

        // Validate U and V plane of the input
        ARM_COMPUTE_ERROR_ON_TENSORS_NOT_SUBSAMPLED(output_format, plane0->info()->tensor_shape(), plane1, plane2);

        // Validate second plane U (NV12 and NV21 have a UV88 combined plane while IYUV has only the U plane)
        // MultiImage generates the correct tensor shape but also check in case the tensor shape of planes was changed to a wrong size
        ARM_COMPUTE_ERROR_ON_TENSORS_NOT_SUBSAMPLED(output_format, plane0->info()->tensor_shape(), output->plane(1));

        // Validate the last plane V of format IYUV
        if(Format::IYUV == output_format)
        {
            // Validate Y plane of the output
            ARM_COMPUTE_ERROR_ON_TENSORS_NOT_SUBSAMPLED(output_format, plane0->info()->tensor_shape(), output->plane(2));
        }
    }

    // Set input tensors
    _planes[0] = plane0;
    _planes[1] = plane1;
    _planes[2] = plane2;
    _planes[3] = nullptr;

    // Set output tensor
    _output       = nullptr;
    _output_multi = output;

    bool has_two_planars = false;

    // Set sub-sampling parameters for each plane
    std::string           kernel_name;
    std::set<std::string> build_opts;

    if(Format::NV12 == output_format || Format::NV21 == output_format)
    {
        _x_subsampling = { { 1, 2, 2 } };
        _y_subsampling = { { 1, 2, 2 } };
        kernel_name    = "channel_combine_NV";
        build_opts.emplace(Format::NV12 == output_format ? "-DNV12" : "-DNV21");
        has_two_planars = true;
    }
    else
    {
        if(Format::IYUV == output_format)
        {
            _x_subsampling = { { 1, 2, 2 } };
            _y_subsampling = { { 1, 2, 2 } };
        }

        kernel_name = "copy_planes_3p";
        build_opts.emplace(Format::IYUV == output_format ? "-DIYUV" : "-DYUV444");
    }

    // Create kernel
    _kernel = create_kernel(compile_context, kernel_name, build_opts);

    // Configure window
    Window win = calculate_max_window(*plane0->info(), Steps(num_elems_processed_per_iteration));

    AccessWindowRectangle input_plane0_access(plane0->info(), 0, 0, num_elems_processed_per_iteration, 1.f);
    AccessWindowRectangle input_plane1_access(plane1->info(), 0, 0, num_elems_processed_per_iteration, 1.f, 1.f / _x_subsampling[1], 1.f / _y_subsampling[1]);
    AccessWindowRectangle input_plane2_access(plane2->info(), 0, 0, num_elems_processed_per_iteration, 1.f, 1.f / _x_subsampling[2], 1.f / _y_subsampling[2]);
    AccessWindowRectangle output_plane0_access(output->plane(0)->info(), 0, 0, num_elems_processed_per_iteration, 1.f, 1.f, 1.f / _y_subsampling[1]);
    AccessWindowRectangle output_plane1_access(output->plane(1)->info(), 0, 0, num_elems_processed_per_iteration, 1.f, 1.f / _x_subsampling[1], 1.f / _y_subsampling[1]);
    AccessWindowRectangle output_plane2_access(has_two_planars ? nullptr : output->plane(2)->info(), 0, 0, num_elems_processed_per_iteration, 1.f, 1.f / _x_subsampling[2], 1.f / _y_subsampling[2]);

    update_window_and_padding(win,
                              input_plane0_access, input_plane1_access, input_plane2_access,
                              output_plane0_access, output_plane1_access, output_plane2_access);

    ValidRegion plane0_valid_region  = plane0->info()->valid_region();
    ValidRegion output_plane1_region = has_two_planars ? intersect_valid_regions(plane1->info()->valid_region(), plane2->info()->valid_region()) : plane2->info()->valid_region();
    output_plane0_access.set_valid_region(win, ValidRegion(plane0_valid_region.anchor, output->plane(0)->info()->tensor_shape()));
    output_plane1_access.set_valid_region(win, ValidRegion(output_plane1_region.anchor, output->plane(1)->info()->tensor_shape()));
    output_plane2_access.set_valid_region(win, ValidRegion(plane2->info()->valid_region().anchor, output->plane(2)->info()->tensor_shape()));

    ICLKernel::configure_internal(win);
}

void CLChannelCombineKernel::run(const Window &window, cl::CommandQueue &queue)
{
    ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
    ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(ICLKernel::window(), window);

    Window slice = window.first_slice_window_2D();
    slice.set_dimension_step(Window::DimY, 1);

    do
    {
        // Subsampling in plane 1
        Window win_sub_plane1(slice);
        win_sub_plane1.set(Window::DimX, Window::Dimension(win_sub_plane1.x().start() / _x_subsampling[1], win_sub_plane1.x().end() / _x_subsampling[1], win_sub_plane1.x().step() / _x_subsampling[1]));
        win_sub_plane1.set(Window::DimY, Window::Dimension(win_sub_plane1.y().start() / _y_subsampling[1], win_sub_plane1.y().end() / _y_subsampling[1], 1));

        // Subsampling in plane 2
        Window win_sub_plane2(slice);
        win_sub_plane2.set(Window::DimX, Window::Dimension(win_sub_plane2.x().start() / _x_subsampling[2], win_sub_plane2.x().end() / _x_subsampling[2], win_sub_plane2.x().step() / _x_subsampling[2]));
        win_sub_plane2.set(Window::DimY, Window::Dimension(win_sub_plane2.y().start() / _y_subsampling[2], win_sub_plane2.y().end() / _y_subsampling[2], 1));

        unsigned int idx = 0;

        // Set inputs
        add_2D_tensor_argument(idx, _planes[0], slice);
        add_2D_tensor_argument(idx, _planes[1], win_sub_plane1);
        add_2D_tensor_argument(idx, _planes[2], win_sub_plane2);
        add_2D_tensor_argument_if((nullptr != _planes[3]), idx, _planes[3], slice);

        // Set outputs
        if(nullptr != _output) // Single planar output
        {
            add_2D_tensor_argument(idx, _output, slice);
        }
        else // Multi-planar output
        {
            // Reduce slice in case of subsampling to avoid out-of bounds access
            slice.set(Window::DimY, Window::Dimension(slice.y().start() / _y_subsampling[1], slice.y().end() / _y_subsampling[1], 1));

            add_2D_tensor_argument(idx, _output_multi->cl_plane(0), slice);
            add_2D_tensor_argument(idx, _output_multi->cl_plane(1), win_sub_plane1);
            add_2D_tensor_argument_if((3 == num_planes_from_format(_output_multi->info()->format())), idx, _output_multi->cl_plane(2), win_sub_plane2);

            _kernel.setArg(idx++, slice.y().end());
        }

        enqueue(queue, *this, slice, lws_hint());
    }
    while(window.slide_window_slice_2D(slice));
}
} // namespace arm_compute
