/*
|
* 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
|
}
|
|
};
|