| /* |
| * 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 <[email protected]> |
| */ |
| |
| #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 |
| } |
| |
| }; |