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