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@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
CLImageKernel(const SmartPtr<CLContext> & context,const char * name,bool enable)34 CLImageKernel::CLImageKernel (const SmartPtr<CLContext> &context, const char *name, bool enable)
35 : CLKernel (context, name)
36 , _enable (enable)
37 {
38 }
39
~CLImageKernel()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
pre_execute()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
prepare_arguments(CLArgList & args,CLWorkSize & work_size)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
CLImageHandler(const SmartPtr<CLContext> & context,const char * name)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
~CLImageHandler()110 CLImageHandler::~CLImageHandler ()
111 {
112 if (_name)
113 xcam_free (_name);
114 }
115
116 bool
enable_buf_pool_swap_flags(uint32_t flags,uint32_t init_order)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
add_kernel(const SmartPtr<CLImageKernel> & kernel)145 CLImageHandler::add_kernel (const SmartPtr<CLImageKernel> &kernel)
146 {
147 _kernels.push_back (kernel);
148 return true;
149 }
150
151 bool
enable_handler(bool enable)152 CLImageHandler::enable_handler (bool enable)
153 {
154 _enable = enable;
155 return true;
156 }
157
158 bool
is_handler_enabled() const159 CLImageHandler::is_handler_enabled () const
160 {
161 return _enable;
162 }
163
164 XCamReturn
create_buffer_pool(const VideoBufferInfo & video_info)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
is_ready()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
prepare_buffer_pool_video_info(const VideoBufferInfo & input,VideoBufferInfo & output)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
prepare_parameters(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)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
ensure_parameters(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)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
reset_buf_cache(const SmartPtr<VideoBuffer> & input,const SmartPtr<VideoBuffer> & output)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
prepare_output_buf(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)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
emit_stop()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> &
get_input_buf()311 CLImageHandler::get_input_buf ()
312 {
313 XCAM_ASSERT (_input_buf_cache.ptr ());
314 return _input_buf_cache;
315 }
316
317 SmartPtr<VideoBuffer> &
get_output_buf()318 CLImageHandler::get_output_buf ()
319 {
320 XCAM_ASSERT (_output_buf_cache.ptr ());
321 return _output_buf_cache;
322 }
323
324 XCamReturn
execute_kernel(SmartPtr<CLImageKernel> & kernel)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
execute_kernels()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
execute(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)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
execute_done(SmartPtr<VideoBuffer> & output)435 CLImageHandler::execute_done (SmartPtr<VideoBuffer> &output)
436 {
437 XCAM_UNUSED (output);
438 return XCAM_RETURN_NO_ERROR;
439 }
440
441 void
set_3a_result(SmartPtr<X3aResult> & result)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>
get_3a_result(XCam3aResultType type)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
append_kernels(SmartPtr<CLImageHandler> handler)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
CLCloneImageHandler(const SmartPtr<CLContext> & context,const char * name)486 CLCloneImageHandler::CLCloneImageHandler (const SmartPtr<CLContext> &context, const char *name)
487 : CLImageHandler (context, name)
488 , _clone_flags (SwappedBuffer::SwapNone)
489 {
490 }
491
492 XCamReturn
prepare_output_buf(SmartPtr<VideoBuffer> & input,SmartPtr<VideoBuffer> & output)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