/*
 * cl_image_handler.cpp - CL image handler
 *
 *  Copyright (c) 2015 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Author: Wind Yuan <feng.yuan@intel.com>
 */

#include "cl_image_handler.h"
#if HAVE_LIBDRM
#include "drm_display.h"
#include "cl_image_bo_buffer.h"
#include "drm_bo_buffer.h"
#endif
#include "cl_device.h"
#include "swapped_buffer.h"

namespace XCam {

#define XCAM_CL_IMAGE_HANDLER_DEFAULT_BUF_NUM 4

CLImageKernel::CLImageKernel (const SmartPtr<CLContext> &context, const char *name, bool enable)
    : CLKernel (context, name)
    , _enable (enable)
{
}

CLImageKernel::~CLImageKernel ()
{
}

/*
 * Default kernel arguments
 * arg0:
 *     input,   __read_only image2d_t
 * arg1:
 *     output,  __write_only image2d_t
 * suppose cl can get width/height pixels from
 * get_image_width/get_image_height
 */
XCamReturn
CLImageKernel::pre_execute ()
{
    XCamReturn ret = XCAM_RETURN_NO_ERROR;
    CLArgList args;
    CLWorkSize work_size;

    XCAM_FAIL_RETURN (
        ERROR, !is_arguments_set (), XCAM_RETURN_ERROR_PARAM,
        "cl image kernel(%s) pre_execute failed since arguments was set somewhere", get_kernel_name ());

    ret = prepare_arguments (args, work_size);
    XCAM_FAIL_RETURN (
        WARNING,
        ret == XCAM_RETURN_NO_ERROR, ret,
        "cl image kernel(%s) prepare arguments failed", get_kernel_name ());

    ret = set_arguments (args, work_size);
    XCAM_FAIL_RETURN (
        WARNING,
        ret == XCAM_RETURN_NO_ERROR, ret,
        "cl image kernel(%s) set_arguments failed", get_kernel_name ());

    return ret;
}

XCamReturn
CLImageKernel::prepare_arguments (
    CLArgList &args, CLWorkSize &work_size)
{
    XCAM_UNUSED (args);
    XCAM_UNUSED (work_size);

    XCAM_LOG_ERROR (
        "cl image kernel(%s) prepare_arguments error."
        "Did you forget to set_arguments or prepare_arguments was not derived", get_kernel_name ());
    return XCAM_RETURN_ERROR_CL;
}

CLImageHandler::CLImageHandler (const SmartPtr<CLContext> &context, const char *name)
    : _name (NULL)
    , _enable (true)
    , _context (context)
    , _buf_pool_type (CLImageHandler::CLVideoPoolType)
    , _disable_buf_pool (false)
    , _buf_pool_size (XCAM_CL_IMAGE_HANDLER_DEFAULT_BUF_NUM)
    , _buf_swap_flags ((uint32_t)(SwappedBuffer::OrderY0Y1) | (uint32_t)(SwappedBuffer::OrderUV0UV1))
    , _buf_swap_init_order (SwappedBuffer::OrderY0Y1)
    , _result_timestamp (XCam::InvalidTimestamp)
{
    XCAM_ASSERT (name);
    if (name)
        _name = strndup (name, XCAM_MAX_STR_SIZE);

    XCAM_OBJ_PROFILING_INIT;
}

CLImageHandler::~CLImageHandler ()
{
    if (_name)
        xcam_free (_name);
}

bool
CLImageHandler::enable_buf_pool_swap_flags (
    uint32_t flags,
    uint32_t init_order)
{
#if HAVE_LIBDRM
    _buf_swap_flags = flags;
    _buf_swap_init_order = init_order;

    SmartPtr<DrmBoBufferPool> pool = _buf_pool.dynamic_cast_ptr<DrmBoBufferPool> ();

    if (pool.ptr () && !pool->update_swap_init_order (init_order)) {
        XCAM_LOG_ERROR (
            "Handler(%s) update swap order(0x%04x) to buffer pool failed",
            XCAM_STR (get_name ()),
            init_order);
        return false;
    }
    return true;
#else
    XCAM_LOG_ERROR ("CLImageHandler doesn't support swapping flags");

    XCAM_UNUSED (flags);
    XCAM_UNUSED (init_order);
    return false;
#endif
}

bool
CLImageHandler::add_kernel (const SmartPtr<CLImageKernel> &kernel)
{
    _kernels.push_back (kernel);
    return true;
}

bool
CLImageHandler::enable_handler (bool enable)
{
    _enable = enable;
    return true;
}

bool
CLImageHandler::is_handler_enabled () const
{
    return _enable;
}

XCamReturn
CLImageHandler::create_buffer_pool (const VideoBufferInfo &video_info)
{
    if (_buf_pool.ptr ())
        return XCAM_RETURN_ERROR_PARAM;

    SmartPtr<BufferPool> buffer_pool;
    if (_buf_pool_type == CLImageHandler::CLVideoPoolType) {
        buffer_pool = new CLVideoBufferPool ();
    }
#if HAVE_LIBDRM
    else {
        SmartPtr<DrmDisplay> display = DrmDisplay::instance ();
        XCAM_FAIL_RETURN(
            WARNING,
            display.ptr (),
            XCAM_RETURN_ERROR_CL,
            "CLImageHandler(%s) failed to get drm dispay", XCAM_STR (_name));

        if (_buf_pool_type == CLImageHandler::DrmBoPoolType) {
            buffer_pool = new DrmBoBufferPool (display);
        } else if (_buf_pool_type == CLImageHandler::CLBoPoolType) {
            buffer_pool = new CLBoBufferPool (display, get_context ());
        }
    }
#endif
    XCAM_FAIL_RETURN(
        WARNING,
        buffer_pool.ptr (),
        XCAM_RETURN_ERROR_CL,
        "CLImageHandler(%s) create buffer pool failed, pool_type:%d",
        XCAM_STR (_name), (int32_t)_buf_pool_type);

    XCAM_ASSERT (buffer_pool.ptr ());
    // buffer_pool->set_swap_flags (_buf_swap_flags, _buf_swap_init_order);
    buffer_pool->set_video_info (video_info);

    XCAM_FAIL_RETURN(
        WARNING,
        buffer_pool->reserve (_buf_pool_size),
        XCAM_RETURN_ERROR_CL,
        "CLImageHandler(%s) failed to init drm buffer pool", XCAM_STR (_name));

    _buf_pool = buffer_pool;
    return XCAM_RETURN_NO_ERROR;
}

bool CLImageHandler::is_ready ()
{
    if (_disable_buf_pool)
        return true;
    if (!_buf_pool.ptr ())  //execute not triggered
        return true;
    if (_buf_pool->has_free_buffers ())
        return true;
    return false;
}

XCamReturn CLImageHandler::prepare_buffer_pool_video_info (
    const VideoBufferInfo &input,
    VideoBufferInfo &output)
{
    output = input;
    return XCAM_RETURN_NO_ERROR;
}

XCamReturn
CLImageHandler::prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
{
    XCAM_UNUSED (input);
    XCAM_UNUSED (output);
    XCAM_ASSERT (input.ptr () && output.ptr ());
    return XCAM_RETURN_NO_ERROR;
}

XCamReturn
CLImageHandler::ensure_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
{
    XCamReturn ret = prepare_parameters (input, output);
    XCAM_FAIL_RETURN(
        WARNING, ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS, ret,
        "CLImageHandler(%s) failed to prepare_parameters", XCAM_STR (_name));

    reset_buf_cache (input, output);
    return ret;
}

void
CLImageHandler::reset_buf_cache (const SmartPtr<VideoBuffer>& input, const SmartPtr<VideoBuffer>& output)
{
    _input_buf_cache = input;
    _output_buf_cache = output;
}

XCamReturn
CLImageHandler::prepare_output_buf (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
{
    XCamReturn ret = XCAM_RETURN_NO_ERROR;

    if (_disable_buf_pool)
        return XCAM_RETURN_NO_ERROR;

    if (!_buf_pool.ptr ()) {
        VideoBufferInfo output_video_info;

        ret = prepare_buffer_pool_video_info (input->get_video_info (), output_video_info);
        XCAM_FAIL_RETURN(
            WARNING,
            ret == XCAM_RETURN_NO_ERROR,
            ret,
            "CLImageHandler(%s) prepare output video info failed", XCAM_STR (_name));

        ret = create_buffer_pool (output_video_info);
        XCAM_FAIL_RETURN(
            WARNING,
            ret == XCAM_RETURN_NO_ERROR,
            ret,
            "CLImageHandler(%s) ensure drm buffer pool failed", XCAM_STR (_name));
    }

    output = _buf_pool->get_buffer (_buf_pool);
    XCAM_FAIL_RETURN(
        WARNING,
        output.ptr(),
        XCAM_RETURN_ERROR_UNKNOWN,
        "CLImageHandler(%s) failed to get drm buffer from pool", XCAM_STR (_name));

    // TODO, need consider output is not sync up with input buffer
    output->set_timestamp (input->get_timestamp ());
    output->copy_attaches (input);

    return XCAM_RETURN_NO_ERROR;
}

void
CLImageHandler::emit_stop ()
{
    for (KernelList::iterator i_kernel = _kernels.begin ();
            i_kernel != _kernels.end ();  ++i_kernel) {
        (*i_kernel)->pre_stop ();
    }

    if (_buf_pool.ptr ())
        _buf_pool->stop ();
}

SmartPtr<VideoBuffer> &
CLImageHandler::get_input_buf ()
{
    XCAM_ASSERT (_input_buf_cache.ptr ());
    return _input_buf_cache;
}

SmartPtr<VideoBuffer> &
CLImageHandler::get_output_buf ()
{
    XCAM_ASSERT (_output_buf_cache.ptr ());
    return _output_buf_cache;
}

XCamReturn
CLImageHandler::execute_kernel (SmartPtr<CLImageKernel> &kernel)
{
    XCamReturn ret = XCAM_RETURN_NO_ERROR;

    if (!kernel->is_enabled ())
        return XCAM_RETURN_NO_ERROR;

    if (!kernel->is_arguments_set ()) {
        XCAM_FAIL_RETURN (
            WARNING,
            (ret = kernel->pre_execute ()) == XCAM_RETURN_NO_ERROR, ret,
            "cl_image_handler(%s) pre_execute kernel(%s) failed",
            XCAM_STR (_name), kernel->get_kernel_name ());
    }

    CLArgList args = kernel->get_args ();
    ret = kernel->execute (kernel, false);
    XCAM_FAIL_RETURN (
        WARNING, ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS, ret,
        "cl_image_handler(%s) execute kernel(%s) failed",
        XCAM_STR (_name), kernel->get_kernel_name ());

#if 0
    ret = kernel->post_execute (args);
    XCAM_FAIL_RETURN (
        WARNING,
        (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS),
        ret,
        "cl_image_handler(%s) post_execute kernel(%s) failed",
        XCAM_STR (_name), kernel->get_kernel_name ());
#endif

    return ret;
}

XCamReturn
CLImageHandler::execute_kernels ()
{
    XCamReturn ret = XCAM_RETURN_NO_ERROR;

    for (KernelList::iterator i_kernel = _kernels.begin ();
            i_kernel != _kernels.end (); ++i_kernel) {
        SmartPtr<CLImageKernel> &kernel = *i_kernel;

        XCAM_FAIL_RETURN (
            WARNING, kernel.ptr(), XCAM_RETURN_ERROR_PARAM,
            "kernel empty");

        ret = execute_kernel (kernel);

        if (ret != XCAM_RETURN_NO_ERROR)
            break;
    }

    return ret;
}

XCamReturn
CLImageHandler::execute (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
{
    XCamReturn ret = XCAM_RETURN_NO_ERROR;

    XCAM_FAIL_RETURN (
        WARNING,
        !_kernels.empty (),
        XCAM_RETURN_ERROR_PARAM,
        "cl_image_handler(%s) no image kernel set", XCAM_STR (_name));

    if (!is_handler_enabled ()) {
        output = input;
        return XCAM_RETURN_NO_ERROR;
    }

    XCAM_FAIL_RETURN (
        WARNING,
        (ret = prepare_output_buf (input, output)) == XCAM_RETURN_NO_ERROR,
        ret,
        "cl_image_handler (%s) prepare output buf failed", XCAM_STR (_name));
    XCAM_ASSERT (output.ptr ());

    ret = ensure_parameters (input, output);
    XCAM_FAIL_RETURN (
        WARNING, (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS), ret,
        "cl_image_handler (%s) ensure parameters failed", XCAM_STR (_name));

    if (ret == XCAM_RETURN_BYPASS)
        return ret;

    XCAM_OBJ_PROFILING_START;
    ret = execute_kernels ();

    reset_buf_cache (NULL, NULL);

#if ENABLE_PROFILING
    get_context ()->finish ();
#endif
    XCAM_OBJ_PROFILING_END (XCAM_STR (_name), XCAM_OBJ_DUR_FRAME_NUM);

    XCAM_FAIL_RETURN (
        WARNING, (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS), ret,
        "cl_image_handler (%s) execute kernels failed", XCAM_STR (_name));

    if (ret != XCAM_RETURN_NO_ERROR)
        return ret;

    ret = execute_done (output);
    return ret;
}

XCamReturn
CLImageHandler::execute_done (SmartPtr<VideoBuffer> &output)
{
    XCAM_UNUSED (output);
    return XCAM_RETURN_NO_ERROR;
}

void
CLImageHandler::set_3a_result (SmartPtr<X3aResult> &result)
{
    if (!result.ptr ())
        return;

    int64_t ts = result->get_timestamp ();
    _result_timestamp = (ts != XCam::InvalidTimestamp) ? ts : _result_timestamp;

    X3aResultList::iterator i_res = _3a_results.begin ();
    for (; i_res != _3a_results.end(); ++i_res) {
        if (result->get_type () == (*i_res)->get_type ()) {
            (*i_res) = result;
            break;
        }
    }

    if (i_res == _3a_results.end ()) {
        _3a_results.push_back (result);
    }
}

SmartPtr<X3aResult>
CLImageHandler::get_3a_result (XCam3aResultType type)
{
    X3aResultList::iterator i_res = _3a_results.begin ();
    SmartPtr<X3aResult> res;

    for ( ; i_res != _3a_results.end(); ++i_res) {
        if (type == (*i_res)->get_type ()) {
            res = (*i_res);
            break;
        }
    }
    return res;
}

bool
CLImageHandler::append_kernels (SmartPtr<CLImageHandler> handler)
{
    XCAM_ASSERT (!handler->_kernels.empty ());
    _kernels.insert (_kernels.end (), handler->_kernels.begin (), handler->_kernels.end ());
    return true;
}

CLCloneImageHandler::CLCloneImageHandler (const SmartPtr<CLContext> &context, const char *name)
    : CLImageHandler (context, name)
    , _clone_flags (SwappedBuffer::SwapNone)
{
}

XCamReturn
CLCloneImageHandler::prepare_output_buf (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
{
#if HAVE_LIBDRM
    XCAM_FAIL_RETURN (
        ERROR,
        _clone_flags != (uint32_t)(SwappedBuffer::SwapNone),
        XCAM_RETURN_ERROR_PARAM,
        "CLCloneImageHandler(%s) clone output buffer failed since clone_flags none",
        XCAM_STR (get_name ()));

    XCAM_ASSERT (input.ptr ());
    SmartPtr<SwappedBuffer> swap_input = input.dynamic_cast_ptr<DrmBoBuffer> ();
    XCAM_ASSERT (swap_input.ptr ());
    SmartPtr<SwappedBuffer> swap_output = swap_input->swap_clone (swap_input, _clone_flags);
    SmartPtr<DrmBoBuffer> swapped_buf = swap_output.dynamic_cast_ptr<DrmBoBuffer> ();
    XCAM_FAIL_RETURN (
        ERROR,
        swapped_buf.ptr (),
        XCAM_RETURN_ERROR_UNKNOWN,
        "CLCloneImageHandler(%s) clone output buffer failed(clone_flags:%d)",
        XCAM_STR (get_name ()), _clone_flags);

    output = swapped_buf;
    return XCAM_RETURN_NO_ERROR;
#else
    XCAM_LOG_ERROR ("CLCloneImageHandler doesn't support DrmBoBuffer");

    XCAM_UNUSED (input);
    XCAM_UNUSED (output);
    return XCAM_RETURN_ERROR_PARAM;
#endif
}

};
