Home | History | Annotate | Download | only in ocl
      1 /*
      2  * cl_image_handler.cpp - CL image handler
      3  *
      4  *  Copyright (c) 2015 Intel Corporation
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  *
     18  * Author: Wind Yuan <feng.yuan (at) intel.com>
     19  */
     20 
     21 #include "cl_image_handler.h"
     22 #if HAVE_LIBDRM
     23 #include "drm_display.h"
     24 #include "cl_image_bo_buffer.h"
     25 #include "drm_bo_buffer.h"
     26 #endif
     27 #include "cl_device.h"
     28 #include "swapped_buffer.h"
     29 
     30 namespace XCam {
     31 
     32 #define XCAM_CL_IMAGE_HANDLER_DEFAULT_BUF_NUM 4
     33 
     34 CLImageKernel::CLImageKernel (const SmartPtr<CLContext> &context, const char *name, bool enable)
     35     : CLKernel (context, name)
     36     , _enable (enable)
     37 {
     38 }
     39 
     40 CLImageKernel::~CLImageKernel ()
     41 {
     42 }
     43 
     44 /*
     45  * Default kernel arguments
     46  * arg0:
     47  *     input,   __read_only image2d_t
     48  * arg1:
     49  *     output,  __write_only image2d_t
     50  * suppose cl can get width/height pixels from
     51  * get_image_width/get_image_height
     52  */
     53 XCamReturn
     54 CLImageKernel::pre_execute ()
     55 {
     56     XCamReturn ret = XCAM_RETURN_NO_ERROR;
     57     CLArgList args;
     58     CLWorkSize work_size;
     59 
     60     XCAM_FAIL_RETURN (
     61         ERROR, !is_arguments_set (), XCAM_RETURN_ERROR_PARAM,
     62         "cl image kernel(%s) pre_execute failed since arguments was set somewhere", get_kernel_name ());
     63 
     64     ret = prepare_arguments (args, work_size);
     65     XCAM_FAIL_RETURN (
     66         WARNING,
     67         ret == XCAM_RETURN_NO_ERROR, ret,
     68         "cl image kernel(%s) prepare arguments failed", get_kernel_name ());
     69 
     70     ret = set_arguments (args, work_size);
     71     XCAM_FAIL_RETURN (
     72         WARNING,
     73         ret == XCAM_RETURN_NO_ERROR, ret,
     74         "cl image kernel(%s) set_arguments failed", get_kernel_name ());
     75 
     76     return ret;
     77 }
     78 
     79 XCamReturn
     80 CLImageKernel::prepare_arguments (
     81     CLArgList &args, CLWorkSize &work_size)
     82 {
     83     XCAM_UNUSED (args);
     84     XCAM_UNUSED (work_size);
     85 
     86     XCAM_LOG_ERROR (
     87         "cl image kernel(%s) prepare_arguments error."
     88         "Did you forget to set_arguments or prepare_arguments was not derived", get_kernel_name ());
     89     return XCAM_RETURN_ERROR_CL;
     90 }
     91 
     92 CLImageHandler::CLImageHandler (const SmartPtr<CLContext> &context, const char *name)
     93     : _name (NULL)
     94     , _enable (true)
     95     , _context (context)
     96     , _buf_pool_type (CLImageHandler::CLVideoPoolType)
     97     , _disable_buf_pool (false)
     98     , _buf_pool_size (XCAM_CL_IMAGE_HANDLER_DEFAULT_BUF_NUM)
     99     , _buf_swap_flags ((uint32_t)(SwappedBuffer::OrderY0Y1) | (uint32_t)(SwappedBuffer::OrderUV0UV1))
    100     , _buf_swap_init_order (SwappedBuffer::OrderY0Y1)
    101     , _result_timestamp (XCam::InvalidTimestamp)
    102 {
    103     XCAM_ASSERT (name);
    104     if (name)
    105         _name = strndup (name, XCAM_MAX_STR_SIZE);
    106 
    107     XCAM_OBJ_PROFILING_INIT;
    108 }
    109 
    110 CLImageHandler::~CLImageHandler ()
    111 {
    112     if (_name)
    113         xcam_free (_name);
    114 }
    115 
    116 bool
    117 CLImageHandler::enable_buf_pool_swap_flags (
    118     uint32_t flags,
    119     uint32_t init_order)
    120 {
    121 #if HAVE_LIBDRM
    122     _buf_swap_flags = flags;
    123     _buf_swap_init_order = init_order;
    124 
    125     SmartPtr<DrmBoBufferPool> pool = _buf_pool.dynamic_cast_ptr<DrmBoBufferPool> ();
    126 
    127     if (pool.ptr () && !pool->update_swap_init_order (init_order)) {
    128         XCAM_LOG_ERROR (
    129             "Handler(%s) update swap order(0x%04x) to buffer pool failed",
    130             XCAM_STR (get_name ()),
    131             init_order);
    132         return false;
    133     }
    134     return true;
    135 #else
    136     XCAM_LOG_ERROR ("CLImageHandler doesn't support swapping flags");
    137 
    138     XCAM_UNUSED (flags);
    139     XCAM_UNUSED (init_order);
    140     return false;
    141 #endif
    142 }
    143 
    144 bool
    145 CLImageHandler::add_kernel (const SmartPtr<CLImageKernel> &kernel)
    146 {
    147     _kernels.push_back (kernel);
    148     return true;
    149 }
    150 
    151 bool
    152 CLImageHandler::enable_handler (bool enable)
    153 {
    154     _enable = enable;
    155     return true;
    156 }
    157 
    158 bool
    159 CLImageHandler::is_handler_enabled () const
    160 {
    161     return _enable;
    162 }
    163 
    164 XCamReturn
    165 CLImageHandler::create_buffer_pool (const VideoBufferInfo &video_info)
    166 {
    167     if (_buf_pool.ptr ())
    168         return XCAM_RETURN_ERROR_PARAM;
    169 
    170     SmartPtr<BufferPool> buffer_pool;
    171     if (_buf_pool_type == CLImageHandler::CLVideoPoolType) {
    172         buffer_pool = new CLVideoBufferPool ();
    173     }
    174 #if HAVE_LIBDRM
    175     else {
    176         SmartPtr<DrmDisplay> display = DrmDisplay::instance ();
    177         XCAM_FAIL_RETURN(
    178             WARNING,
    179             display.ptr (),
    180             XCAM_RETURN_ERROR_CL,
    181             "CLImageHandler(%s) failed to get drm dispay", XCAM_STR (_name));
    182 
    183         if (_buf_pool_type == CLImageHandler::DrmBoPoolType) {
    184             buffer_pool = new DrmBoBufferPool (display);
    185         } else if (_buf_pool_type == CLImageHandler::CLBoPoolType) {
    186             buffer_pool = new CLBoBufferPool (display, get_context ());
    187         }
    188     }
    189 #endif
    190     XCAM_FAIL_RETURN(
    191         WARNING,
    192         buffer_pool.ptr (),
    193         XCAM_RETURN_ERROR_CL,
    194         "CLImageHandler(%s) create buffer pool failed, pool_type:%d",
    195         XCAM_STR (_name), (int32_t)_buf_pool_type);
    196 
    197     XCAM_ASSERT (buffer_pool.ptr ());
    198     // buffer_pool->set_swap_flags (_buf_swap_flags, _buf_swap_init_order);
    199     buffer_pool->set_video_info (video_info);
    200 
    201     XCAM_FAIL_RETURN(
    202         WARNING,
    203         buffer_pool->reserve (_buf_pool_size),
    204         XCAM_RETURN_ERROR_CL,
    205         "CLImageHandler(%s) failed to init drm buffer pool", XCAM_STR (_name));
    206 
    207     _buf_pool = buffer_pool;
    208     return XCAM_RETURN_NO_ERROR;
    209 }
    210 
    211 bool CLImageHandler::is_ready ()
    212 {
    213     if (_disable_buf_pool)
    214         return true;
    215     if (!_buf_pool.ptr ())  //execute not triggered
    216         return true;
    217     if (_buf_pool->has_free_buffers ())
    218         return true;
    219     return false;
    220 }
    221 
    222 XCamReturn CLImageHandler::prepare_buffer_pool_video_info (
    223     const VideoBufferInfo &input,
    224     VideoBufferInfo &output)
    225 {
    226     output = input;
    227     return XCAM_RETURN_NO_ERROR;
    228 }
    229 
    230 XCamReturn
    231 CLImageHandler::prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
    232 {
    233     XCAM_UNUSED (input);
    234     XCAM_UNUSED (output);
    235     XCAM_ASSERT (input.ptr () && output.ptr ());
    236     return XCAM_RETURN_NO_ERROR;
    237 }
    238 
    239 XCamReturn
    240 CLImageHandler::ensure_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
    241 {
    242     XCamReturn ret = prepare_parameters (input, output);
    243     XCAM_FAIL_RETURN(
    244         WARNING, ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS, ret,
    245         "CLImageHandler(%s) failed to prepare_parameters", XCAM_STR (_name));
    246 
    247     reset_buf_cache (input, output);
    248     return ret;
    249 }
    250 
    251 void
    252 CLImageHandler::reset_buf_cache (const SmartPtr<VideoBuffer>& input, const SmartPtr<VideoBuffer>& output)
    253 {
    254     _input_buf_cache = input;
    255     _output_buf_cache = output;
    256 }
    257 
    258 XCamReturn
    259 CLImageHandler::prepare_output_buf (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
    260 {
    261     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    262 
    263     if (_disable_buf_pool)
    264         return XCAM_RETURN_NO_ERROR;
    265 
    266     if (!_buf_pool.ptr ()) {
    267         VideoBufferInfo output_video_info;
    268 
    269         ret = prepare_buffer_pool_video_info (input->get_video_info (), output_video_info);
    270         XCAM_FAIL_RETURN(
    271             WARNING,
    272             ret == XCAM_RETURN_NO_ERROR,
    273             ret,
    274             "CLImageHandler(%s) prepare output video info failed", XCAM_STR (_name));
    275 
    276         ret = create_buffer_pool (output_video_info);
    277         XCAM_FAIL_RETURN(
    278             WARNING,
    279             ret == XCAM_RETURN_NO_ERROR,
    280             ret,
    281             "CLImageHandler(%s) ensure drm buffer pool failed", XCAM_STR (_name));
    282     }
    283 
    284     output = _buf_pool->get_buffer (_buf_pool);
    285     XCAM_FAIL_RETURN(
    286         WARNING,
    287         output.ptr(),
    288         XCAM_RETURN_ERROR_UNKNOWN,
    289         "CLImageHandler(%s) failed to get drm buffer from pool", XCAM_STR (_name));
    290 
    291     // TODO, need consider output is not sync up with input buffer
    292     output->set_timestamp (input->get_timestamp ());
    293     output->copy_attaches (input);
    294 
    295     return XCAM_RETURN_NO_ERROR;
    296 }
    297 
    298 void
    299 CLImageHandler::emit_stop ()
    300 {
    301     for (KernelList::iterator i_kernel = _kernels.begin ();
    302             i_kernel != _kernels.end ();  ++i_kernel) {
    303         (*i_kernel)->pre_stop ();
    304     }
    305 
    306     if (_buf_pool.ptr ())
    307         _buf_pool->stop ();
    308 }
    309 
    310 SmartPtr<VideoBuffer> &
    311 CLImageHandler::get_input_buf ()
    312 {
    313     XCAM_ASSERT (_input_buf_cache.ptr ());
    314     return _input_buf_cache;
    315 }
    316 
    317 SmartPtr<VideoBuffer> &
    318 CLImageHandler::get_output_buf ()
    319 {
    320     XCAM_ASSERT (_output_buf_cache.ptr ());
    321     return _output_buf_cache;
    322 }
    323 
    324 XCamReturn
    325 CLImageHandler::execute_kernel (SmartPtr<CLImageKernel> &kernel)
    326 {
    327     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    328 
    329     if (!kernel->is_enabled ())
    330         return XCAM_RETURN_NO_ERROR;
    331 
    332     if (!kernel->is_arguments_set ()) {
    333         XCAM_FAIL_RETURN (
    334             WARNING,
    335             (ret = kernel->pre_execute ()) == XCAM_RETURN_NO_ERROR, ret,
    336             "cl_image_handler(%s) pre_execute kernel(%s) failed",
    337             XCAM_STR (_name), kernel->get_kernel_name ());
    338     }
    339 
    340     CLArgList args = kernel->get_args ();
    341     ret = kernel->execute (kernel, false);
    342     XCAM_FAIL_RETURN (
    343         WARNING, ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS, ret,
    344         "cl_image_handler(%s) execute kernel(%s) failed",
    345         XCAM_STR (_name), kernel->get_kernel_name ());
    346 
    347 #if 0
    348     ret = kernel->post_execute (args);
    349     XCAM_FAIL_RETURN (
    350         WARNING,
    351         (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS),
    352         ret,
    353         "cl_image_handler(%s) post_execute kernel(%s) failed",
    354         XCAM_STR (_name), kernel->get_kernel_name ());
    355 #endif
    356 
    357     return ret;
    358 }
    359 
    360 XCamReturn
    361 CLImageHandler::execute_kernels ()
    362 {
    363     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    364 
    365     for (KernelList::iterator i_kernel = _kernels.begin ();
    366             i_kernel != _kernels.end (); ++i_kernel) {
    367         SmartPtr<CLImageKernel> &kernel = *i_kernel;
    368 
    369         XCAM_FAIL_RETURN (
    370             WARNING, kernel.ptr(), XCAM_RETURN_ERROR_PARAM,
    371             "kernel empty");
    372 
    373         ret = execute_kernel (kernel);
    374 
    375         if (ret != XCAM_RETURN_NO_ERROR)
    376             break;
    377     }
    378 
    379     return ret;
    380 }
    381 
    382 XCamReturn
    383 CLImageHandler::execute (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
    384 {
    385     XCamReturn ret = XCAM_RETURN_NO_ERROR;
    386 
    387     XCAM_FAIL_RETURN (
    388         WARNING,
    389         !_kernels.empty (),
    390         XCAM_RETURN_ERROR_PARAM,
    391         "cl_image_handler(%s) no image kernel set", XCAM_STR (_name));
    392 
    393     if (!is_handler_enabled ()) {
    394         output = input;
    395         return XCAM_RETURN_NO_ERROR;
    396     }
    397 
    398     XCAM_FAIL_RETURN (
    399         WARNING,
    400         (ret = prepare_output_buf (input, output)) == XCAM_RETURN_NO_ERROR,
    401         ret,
    402         "cl_image_handler (%s) prepare output buf failed", XCAM_STR (_name));
    403     XCAM_ASSERT (output.ptr ());
    404 
    405     ret = ensure_parameters (input, output);
    406     XCAM_FAIL_RETURN (
    407         WARNING, (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS), ret,
    408         "cl_image_handler (%s) ensure parameters failed", XCAM_STR (_name));
    409 
    410     if (ret == XCAM_RETURN_BYPASS)
    411         return ret;
    412 
    413     XCAM_OBJ_PROFILING_START;
    414     ret = execute_kernels ();
    415 
    416     reset_buf_cache (NULL, NULL);
    417 
    418 #if ENABLE_PROFILING
    419     get_context ()->finish ();
    420 #endif
    421     XCAM_OBJ_PROFILING_END (XCAM_STR (_name), XCAM_OBJ_DUR_FRAME_NUM);
    422 
    423     XCAM_FAIL_RETURN (
    424         WARNING, (ret == XCAM_RETURN_NO_ERROR || ret == XCAM_RETURN_BYPASS), ret,
    425         "cl_image_handler (%s) execute kernels failed", XCAM_STR (_name));
    426 
    427     if (ret != XCAM_RETURN_NO_ERROR)
    428         return ret;
    429 
    430     ret = execute_done (output);
    431     return ret;
    432 }
    433 
    434 XCamReturn
    435 CLImageHandler::execute_done (SmartPtr<VideoBuffer> &output)
    436 {
    437     XCAM_UNUSED (output);
    438     return XCAM_RETURN_NO_ERROR;
    439 }
    440 
    441 void
    442 CLImageHandler::set_3a_result (SmartPtr<X3aResult> &result)
    443 {
    444     if (!result.ptr ())
    445         return;
    446 
    447     int64_t ts = result->get_timestamp ();
    448     _result_timestamp = (ts != XCam::InvalidTimestamp) ? ts : _result_timestamp;
    449 
    450     X3aResultList::iterator i_res = _3a_results.begin ();
    451     for (; i_res != _3a_results.end(); ++i_res) {
    452         if (result->get_type () == (*i_res)->get_type ()) {
    453             (*i_res) = result;
    454             break;
    455         }
    456     }
    457 
    458     if (i_res == _3a_results.end ()) {
    459         _3a_results.push_back (result);
    460     }
    461 }
    462 
    463 SmartPtr<X3aResult>
    464 CLImageHandler::get_3a_result (XCam3aResultType type)
    465 {
    466     X3aResultList::iterator i_res = _3a_results.begin ();
    467     SmartPtr<X3aResult> res;
    468 
    469     for ( ; i_res != _3a_results.end(); ++i_res) {
    470         if (type == (*i_res)->get_type ()) {
    471             res = (*i_res);
    472             break;
    473         }
    474     }
    475     return res;
    476 }
    477 
    478 bool
    479 CLImageHandler::append_kernels (SmartPtr<CLImageHandler> handler)
    480 {
    481     XCAM_ASSERT (!handler->_kernels.empty ());
    482     _kernels.insert (_kernels.end (), handler->_kernels.begin (), handler->_kernels.end ());
    483     return true;
    484 }
    485 
    486 CLCloneImageHandler::CLCloneImageHandler (const SmartPtr<CLContext> &context, const char *name)
    487     : CLImageHandler (context, name)
    488     , _clone_flags (SwappedBuffer::SwapNone)
    489 {
    490 }
    491 
    492 XCamReturn
    493 CLCloneImageHandler::prepare_output_buf (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output)
    494 {
    495 #if HAVE_LIBDRM
    496     XCAM_FAIL_RETURN (
    497         ERROR,
    498         _clone_flags != (uint32_t)(SwappedBuffer::SwapNone),
    499         XCAM_RETURN_ERROR_PARAM,
    500         "CLCloneImageHandler(%s) clone output buffer failed since clone_flags none",
    501         XCAM_STR (get_name ()));
    502 
    503     XCAM_ASSERT (input.ptr ());
    504     SmartPtr<SwappedBuffer> swap_input = input.dynamic_cast_ptr<DrmBoBuffer> ();
    505     XCAM_ASSERT (swap_input.ptr ());
    506     SmartPtr<SwappedBuffer> swap_output = swap_input->swap_clone (swap_input, _clone_flags);
    507     SmartPtr<DrmBoBuffer> swapped_buf = swap_output.dynamic_cast_ptr<DrmBoBuffer> ();
    508     XCAM_FAIL_RETURN (
    509         ERROR,
    510         swapped_buf.ptr (),
    511         XCAM_RETURN_ERROR_UNKNOWN,
    512         "CLCloneImageHandler(%s) clone output buffer failed(clone_flags:%d)",
    513         XCAM_STR (get_name ()), _clone_flags);
    514 
    515     output = swapped_buf;
    516     return XCAM_RETURN_NO_ERROR;
    517 #else
    518     XCAM_LOG_ERROR ("CLCloneImageHandler doesn't support DrmBoBuffer");
    519 
    520     XCAM_UNUSED (input);
    521     XCAM_UNUSED (output);
    522     return XCAM_RETURN_ERROR_PARAM;
    523 #endif
    524 }
    525 
    526 };
    527