• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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