1 /**************************************************************************
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
35 #include "tdm_backend_sprd.h"
39 typedef struct _tdm_sprd_capture_buffer {
41 struct list_head link;
42 } tdm_sprd_capture_buffer;
44 typedef struct _tdm_sprd_capture_pp_data {
46 tbm_surface_h src_buffer;
47 tbm_surface_h dst_buffer;
48 struct list_head link;
49 } tdm_sprd_capture_pp_data;
51 typedef struct _tdm_sprd_capture_composite_data {
52 tbm_surface_h temp_layer_buffer[LAYER_COUNT_PER_OUTPUT];
53 hal_tdm_pos dst_pos[LAYER_COUNT_PER_OUTPUT];
54 int zpos[LAYER_COUNT_PER_OUTPUT];
55 tbm_surface_h client_buffer;
56 tbm_surface_h temp_composite_buffer;
57 tdm_sprd_capture_pp_data * composite_buf_pp_task;
58 int current_done_buf_num;
59 int need_done_buf_num;
60 struct list_head link;
61 } tdm_sprd_capture_composite;
63 typedef struct _tdm_sprd_capture_data {
66 tdm_sprd_display *display_data;
68 hal_tdm_output *output_data;
70 hal_tdm_info_capture info;
72 struct list_head pending_buffer_list;
73 struct list_head pp_convert_list;
74 struct list_head composite_list;
76 hal_tdm_capture_done_handler done_func;
78 struct list_head link;
79 } tdm_sprd_capture_data;
81 typedef struct _tdm_sprd_capture_internal {
82 tdm_sprd_capture_data *stream_data;
86 } tdm_sprd_capture_internal;
88 static tdm_sprd_capture_internal *g_capture_data;
90 static tbm_format capture_client_formats[] = {
97 #define NUM_CAPTURE_FORMAT (sizeof(capture_client_formats) / sizeof(capture_client_formats[0]))
99 static int capture_list_init;
100 static struct list_head capture_list;
101 static int capture_stamp = 1001;
103 int _tdm_sprd_capture_check_struct(tdm_sprd_capture_data *capture_data)
105 TDM_BACKEND_RETURN_VAL_IF_FAIL(capture_list_init == 1, 0);
106 if (capture_data == NULL) {
107 TDM_BACKEND_WRN("capture nil(0). Received NULL pointer");
110 tdm_sprd_capture_data * capture_next = NULL;
111 LIST_FOR_EACH_ENTRY(capture_next, &capture_list, link) {
112 if (capture_next->stamp == capture_data->stamp)
115 TDM_BACKEND_INFO("capture %p(%d). Maybe, receive handler after remove",
116 capture_data, capture_data->stamp);
121 _tdm_sprd_capture_oneshot_center_rect(int src_w, int src_h, int dst_w, int dst_h, hal_tdm_pos *fit)
123 float rw = (float)src_w / dst_w;
124 float rh = (float)src_h / dst_h;
131 fit->y = (dst_h - fit->h) / 2;
132 } else if (rw < rh) {
135 fit->x = (dst_w - fit->w) / 2;
141 fit->x = fit->x & ~0x1;
145 _tdm_sprd_capture_oneshot_rect_scale(int src_w, int src_h, int dst_w, int dst_h, hal_tdm_pos *scale)
148 hal_tdm_pos center = {0,};
150 _tdm_sprd_capture_oneshot_center_rect(src_w, src_h, dst_w, dst_h, ¢er);
152 ratio = (float)center.w / src_w;
153 scale->x = scale->x * ratio + center.x;
154 scale->y = scale->y * ratio + center.y;
155 scale->w = scale->w * ratio;
156 scale->h = scale->h * ratio;
160 _tdm_sprd_capture_destroy_converter(tdm_sprd_capture_pp_data ** pp_task_p)
162 TDM_BACKEND_RETURN_IF_FAIL(pp_task_p);
163 TDM_BACKEND_RETURN_IF_FAIL(*pp_task_p);
164 LIST_DEL(&(*pp_task_p)->link);
165 if ((*pp_task_p)->pp_link)
166 sprd_pp_destroy((*pp_task_p)->pp_link);
167 if ((*pp_task_p)->src_buffer) {
168 tbm_surface_internal_unref((*pp_task_p)->src_buffer);
169 (*pp_task_p)->src_buffer = NULL;
171 if ((*pp_task_p)->dst_buffer) {
172 tbm_surface_internal_unref((*pp_task_p)->dst_buffer);
173 (*pp_task_p)->dst_buffer = NULL;
179 static pixman_format_code_t
180 _tdm_sprd_pixman_format_get(tbm_format format)
183 case TBM_FORMAT_ARGB8888:
184 return PIXMAN_a8r8g8b8;
185 case TBM_FORMAT_XRGB8888:
186 return PIXMAN_x8r8g8b8;
195 _tdm_sprd_capture_convert_buffer(tbm_surface_h srcbuf, tbm_surface_h dstbuf,
196 hal_tdm_pos *srcpos, hal_tdm_pos *dstpos,
197 hal_tdm_transform transform, int over)
199 tbm_surface_info_s src_info, dst_info;
200 pixman_image_t *src_img = NULL, *dst_img = NULL;
201 pixman_format_code_t src_format, dst_format;
202 double scale_x, scale_y;
203 int rotate_step, bos;
204 pixman_transform_t t;
205 struct pixman_f_transform ft;
207 int src_stride, dst_stride;
209 hal_tdm_error ret = HAL_TDM_ERROR_OPERATION_FAILED;
211 TDM_BACKEND_RETURN_VAL_IF_FAIL(srcbuf != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
212 TDM_BACKEND_RETURN_VAL_IF_FAIL(dstbuf != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
214 bos = tbm_surface_internal_get_num_bos(srcbuf);
215 TDM_BACKEND_RETURN_VAL_IF_FAIL(bos == 1, HAL_TDM_ERROR_OPERATION_FAILED);
217 bos = tbm_surface_internal_get_num_bos(dstbuf);
218 TDM_BACKEND_RETURN_VAL_IF_FAIL(bos == 1, HAL_TDM_ERROR_OPERATION_FAILED);
220 err = tbm_surface_map(srcbuf, TBM_OPTION_READ, &src_info);
221 TDM_BACKEND_RETURN_VAL_IF_FAIL(err == TBM_SURFACE_ERROR_NONE, HAL_TDM_ERROR_OPERATION_FAILED);
223 err = tbm_surface_map(dstbuf, TBM_OPTION_WRITE, &dst_info);
224 TDM_BACKEND_GOTO_VAL_IF_FAIL(err == TBM_SURFACE_ERROR_NONE, unmap_srcbuf);
226 /* not handle buffers which have 2 more gem handles */
227 TDM_BACKEND_GOTO_VAL_IF_FAIL(src_info.planes[0].ptr != NULL, unmap_dstbuf);
228 TDM_BACKEND_GOTO_VAL_IF_FAIL(dst_info.planes[0].ptr != NULL, unmap_dstbuf);
230 src_format = _tdm_sprd_pixman_format_get(src_info.format);
231 TDM_BACKEND_GOTO_VAL_IF_FAIL(src_format > 0, unmap_dstbuf);
232 dst_format = _tdm_sprd_pixman_format_get(dst_info.format);
233 TDM_BACKEND_GOTO_VAL_IF_FAIL(dst_format > 0, unmap_dstbuf);
235 buf_width = src_info.planes[0].stride >> 2;
236 src_stride = src_info.planes[0].stride;
237 src_img = pixman_image_create_bits(src_format, buf_width, src_info.height,
238 (uint32_t*)src_info.planes[0].ptr, src_stride);
239 TDM_BACKEND_GOTO_VAL_IF_FAIL(src_img, unref_img);
241 buf_width = dst_info.planes[0].stride >> 2;
242 dst_stride = dst_info.planes[0].stride;
243 dst_img = pixman_image_create_bits(dst_format, buf_width, dst_info.height,
244 (uint32_t*)dst_info.planes[0].ptr, dst_stride);
245 TDM_BACKEND_GOTO_VAL_IF_FAIL(dst_img, unref_img);
247 pixman_f_transform_init_identity(&ft);
249 if (transform & HAL_TDM_TRANSFORM_FLIPPED) {
250 pixman_f_transform_scale(&ft, NULL, -1, 1);
251 pixman_f_transform_translate(&ft, NULL, dstpos->w, 0);
254 rotate_step = transform & 0x3;
255 if (rotate_step > 0) {
256 int c, s, tx = 0, ty = 0;
257 switch (rotate_step) {
259 c = 0, s = -1, tx = -dstpos->w;
262 c = -1, s = 0, tx = -dstpos->w, ty = -dstpos->h;
265 c = 0, s = 1, ty = -dstpos->h;
268 pixman_f_transform_translate(&ft, NULL, tx, ty);
269 pixman_f_transform_rotate(&ft, NULL, c, s);
272 if (rotate_step % 2 == 0) {
273 scale_x = (double)srcpos->w / dstpos->w;
274 scale_y = (double)srcpos->h / dstpos->h;
276 scale_x = (double)srcpos->w / dstpos->h;
277 scale_y = (double)srcpos->h / dstpos->w;
280 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
281 pixman_f_transform_translate(&ft, NULL, srcpos->x, srcpos->y);
282 pixman_transform_from_pixman_f_transform(&t, &ft);
283 pixman_image_set_transform(src_img, &t);
285 op = (!over) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER;
287 pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0,
288 dstpos->x, dstpos->y, dstpos->w, dstpos->h);
290 ret = HAL_TDM_ERROR_NONE;
294 pixman_image_unref(src_img);
296 pixman_image_unref(dst_img);
298 tbm_surface_unmap(dstbuf);
300 tbm_surface_unmap(srcbuf);
306 _tdm_sprd_capture_composite_sw(tdm_sprd_capture_data *capture_data,
307 tdm_sprd_capture_composite * composite_data,
308 tbm_surface_h composite_buf)
311 hal_tdm_error tdm_err = HAL_TDM_ERROR_NONE;
312 tbm_surface_h temp_buffer = NULL;
314 hal_tdm_pos temp_dpos = {0, 0, 0, 0};
315 /* Good old bubble sort */
316 for (k = 0; k < LAYER_COUNT_PER_OUTPUT-1; ++k) {
317 for (i = 0; i < LAYER_COUNT_PER_OUTPUT - 1 - k; ++i) {
318 if (composite_data->zpos[i] > composite_data->zpos[i+1]) {
319 temp_buffer = composite_data->temp_layer_buffer[i];
320 temp_zpos = composite_data->zpos[i];
321 temp_dpos = composite_data->dst_pos[i];
322 composite_data->temp_layer_buffer[i] = composite_data->temp_layer_buffer[i+1];
323 composite_data->zpos[i] = composite_data->zpos[i+1];
324 composite_data->dst_pos[i] = composite_data->dst_pos[i+1];
325 composite_data->dst_pos[i+1] = temp_dpos;
326 composite_data->temp_layer_buffer[i+1] = temp_buffer;
327 composite_data->zpos[i+1] = temp_zpos;
331 for (i = 0; i < LAYER_COUNT_PER_OUTPUT; i++) {
332 if (composite_data->temp_layer_buffer[i]) {
333 hal_tdm_pos src_pos = {.x = 0,
335 .w = tbm_surface_get_width(composite_data->temp_layer_buffer[i]),
336 .h = tbm_surface_get_height(composite_data->temp_layer_buffer[i])};
337 tdm_err = _tdm_sprd_capture_convert_buffer(composite_data->temp_layer_buffer[i],
338 composite_buf, &src_pos,
339 &composite_data->dst_pos[i], 0, 1);
340 if (tdm_err != HAL_TDM_ERROR_NONE) {
341 TDM_BACKEND_WRN("Capture %p error %d Can't composite buffers src %p dst %p. Skip",
342 capture_data, tdm_err, composite_data->temp_layer_buffer[i], composite_buf);
344 tbm_surface_internal_unref(composite_data->temp_layer_buffer[i]);
345 composite_data->temp_layer_buffer[i] = NULL;
349 return HAL_TDM_ERROR_NONE;
353 _tdm_sprd_capture_pp_done_handler (hal_tdm_pp *pp, tbm_surface_h src,
354 tbm_surface_h dst, void *user_data)
356 if (!_tdm_sprd_capture_check_struct(user_data)) {
359 tdm_sprd_capture_data *capture_data = user_data;
360 if (capture_data->removing) {
361 TDM_BACKEND_INFO("Capture removing. Skip handler");
364 tdm_sprd_capture_composite *composite_data = NULL, *composite_next = NULL;
365 tdm_sprd_capture_pp_data *pp_task = NULL, *pp_tasks_next = NULL;
367 LIST_FOR_EACH_ENTRY_SAFE(pp_task, pp_tasks_next, &capture_data->pp_convert_list, link) {
368 if (pp_task->pp_link == pp) {
369 tbm_surface_internal_unref(pp_task->src_buffer);
370 pp_task->src_buffer = NULL;
371 tbm_surface_internal_unref(pp_task->dst_buffer);
372 pp_task->dst_buffer = NULL;
376 LIST_FOR_EACH_ENTRY_SAFE(composite_data, composite_next, &capture_data->composite_list, link) {
377 if (composite_data->client_buffer && composite_data->client_buffer == dst) {
378 LIST_DEL(&composite_data->link);
379 tbm_surface_internal_unref(composite_data->client_buffer);
380 tbm_surface_internal_unref(composite_data->temp_composite_buffer);
381 composite_data->temp_composite_buffer = NULL;
382 if (capture_data->done_func) {
383 capture_data->done_func(capture_data,
384 composite_data->client_buffer,
385 capture_data->done_user_data);
387 free(composite_data);
390 for (i = 0; i < LAYER_COUNT_PER_OUTPUT; i++) {
391 if (composite_data->temp_layer_buffer[i] && composite_data->temp_layer_buffer[i] == dst) {
392 composite_data->current_done_buf_num++;
395 if (composite_data->current_done_buf_num == composite_data->need_done_buf_num) {
396 if (!composite_data->temp_composite_buffer) {
397 _tdm_sprd_capture_composite_sw(capture_data, composite_data,
398 composite_data->client_buffer);
399 tbm_surface_internal_unref(composite_data->client_buffer);
400 if (capture_data->done_func) {
401 capture_data->done_func(capture_data,
402 composite_data->client_buffer,
403 capture_data->done_user_data);
405 LIST_DEL(&composite_data->link);
406 free(composite_data);
408 _tdm_sprd_capture_composite_sw(capture_data, composite_data,
409 composite_data->temp_composite_buffer);
410 sprd_pp_commit(composite_data->composite_buf_pp_task->pp_link);
411 composite_data->current_done_buf_num = 0;
416 TDM_BACKEND_DBG("capture pp handler done");
420 _tdm_sprd_capture_make_converter(tdm_sprd_capture_data *capture_data,
421 tbm_surface_h src, tbm_surface_h dst,
422 hal_tdm_pos *src_pos, hal_tdm_pos *dst_pos,
423 hal_tdm_transform transform,
424 tdm_sprd_capture_pp_data ** pp_task_p)
426 hal_tdm_error tdm_err = HAL_TDM_ERROR_NONE;
427 hal_tdm_pp *pp = NULL;
428 hal_tdm_info_pp info_pp;
429 tdm_sprd_capture_pp_data *new_pp_task = NULL, *pp_task = NULL, *pp_tasks_next = NULL;
430 tbm_format src_format, dst_format;
431 unsigned int src_bpp, src_stride, dst_bpp, dst_stride;
433 if (pp_task_p == NULL) {
434 return HAL_TDM_ERROR_INVALID_PARAMETER;
436 LIST_FOR_EACH_ENTRY_SAFE(pp_task, pp_tasks_next, &capture_data->pp_convert_list, link) {
437 if (pp_task->src_buffer == NULL &&
438 pp_task->dst_buffer == NULL) {
439 new_pp_task = pp_task;
440 new_pp_task->dst_buffer = dst;
441 new_pp_task->src_buffer = src;
442 tbm_surface_internal_ref(dst);
443 tbm_surface_internal_ref(src);
447 if (new_pp_task == NULL) {
448 new_pp_task = calloc(1, sizeof(tdm_sprd_capture_pp_data));
449 if (new_pp_task == NULL) {
450 TDM_BACKEND_WRN("Out of memory");
451 return HAL_TDM_ERROR_OUT_OF_MEMORY;
453 new_pp_task->dst_buffer = dst;
454 new_pp_task->src_buffer = src;
455 tbm_surface_internal_ref(dst);
456 tbm_surface_internal_ref(src);
457 LIST_ADD(&new_pp_task->link, &capture_data->pp_convert_list);
458 pp = tdm_sprd_pp_create(capture_data->display_data, &tdm_err);
459 if (tdm_err != HAL_TDM_ERROR_NONE) {
460 TDM_BACKEND_WRN("can't create pp");
463 if ((tdm_err = sprd_pp_set_done_handler(pp, _tdm_sprd_capture_pp_done_handler,
464 capture_data)) != HAL_TDM_ERROR_NONE) {
465 TDM_BACKEND_WRN("can't create done handler");
468 new_pp_task->pp_link = pp;
471 src_format = tbm_surface_get_format(src);
472 src_bpp = tbm_surface_internal_get_bpp(src_format);
474 if (!tbm_surface_internal_get_plane_data(src, 0, NULL, NULL, &src_stride)) {
475 TDM_BACKEND_WRN("can't get stride");
476 tdm_err = HAL_TDM_ERROR_OPERATION_FAILED;
479 if (IS_RGB(src_format)) {
482 src_stride /= src_bpp;
484 info_pp.src_config.format = tbm_surface_get_format(src);
485 info_pp.src_config.pos.x = (src_pos) ? src_pos->x : 0;
486 info_pp.src_config.pos.y = (src_pos) ? src_pos->y : 0;
487 info_pp.src_config.pos.w = (src_pos) ? src_pos->w : tbm_surface_get_width(src);
488 info_pp.src_config.pos.h = (src_pos) ? src_pos->h : tbm_surface_get_height(src);
489 info_pp.src_config.size.h = src_stride;
490 info_pp.src_config.size.v = tbm_surface_get_height(src);
492 dst_format = tbm_surface_get_format(dst);
493 dst_bpp = tbm_surface_internal_get_bpp(dst_format);
495 if (!tbm_surface_internal_get_plane_data(dst, 0, NULL, NULL, &dst_stride)) {
496 TDM_BACKEND_WRN("can't get stride");
497 tdm_err = HAL_TDM_ERROR_OPERATION_FAILED;
500 if (IS_RGB(dst_format)) {
503 dst_stride /= dst_bpp;
506 info_pp.dst_config.format = dst_format;
507 info_pp.dst_config.pos.x = (dst_pos) ? dst_pos->x : 0;
508 info_pp.dst_config.pos.y = (dst_pos) ? dst_pos->y : 0;
509 info_pp.dst_config.pos.w = (dst_pos) ? dst_pos->w : tbm_surface_get_width(dst);
510 info_pp.dst_config.pos.h = (dst_pos) ? dst_pos->h : tbm_surface_get_height(dst);
511 info_pp.dst_config.size.h = dst_stride;
512 info_pp.dst_config.size.v = tbm_surface_get_height(dst);
513 info_pp.transform = transform;
514 if ((tdm_err = sprd_pp_set_info(new_pp_task->pp_link, &info_pp)) != HAL_TDM_ERROR_NONE) {
515 TDM_BACKEND_WRN("can't set pp info");
516 tdm_err = HAL_TDM_ERROR_OPERATION_FAILED;
519 if ((tdm_err = sprd_pp_attach(new_pp_task->pp_link, src, dst)) != HAL_TDM_ERROR_NONE) {
520 TDM_BACKEND_WRN("can't set buffers to pp");
521 tdm_err = HAL_TDM_ERROR_OPERATION_FAILED;
524 *pp_task_p = new_pp_task;
525 return HAL_TDM_ERROR_NONE;
531 LIST_DEL(&new_pp_task->link);
532 if (new_pp_task->dst_buffer)
533 tbm_surface_internal_unref(dst);
534 if (new_pp_task->src_buffer)
535 tbm_surface_internal_unref(src);
541 void _tdm_sprd_capture_oneshot_transform_rect(int dpy_w, int dpy_h, hal_tdm_transform transform, hal_tdm_pos *pos)
545 if (transform == HAL_TDM_TRANSFORM_90) {
547 pos->x = dpy_h - pos->y - pos->h;
552 } else if (transform == HAL_TDM_TRANSFORM_180) {
553 pos->x = dpy_w - pos->x - pos->w;
554 pos->y = dpy_h - pos->y - pos->h;
555 } else if (transform == HAL_TDM_TRANSFORM_270) {
557 pos->y = dpy_w - pos->x - pos->w;
562 } else if (transform == HAL_TDM_TRANSFORM_FLIPPED) {
563 pos->x = dpy_w - pos->x - pos->w;
564 } else if (transform == HAL_TDM_TRANSFORM_FLIPPED_90) {
571 } else if (transform == HAL_TDM_TRANSFORM_FLIPPED_180) {
572 pos->y = dpy_h - pos->y - pos->h;
573 } else if (transform == HAL_TDM_TRANSFORM_FLIPPED_270) {
575 pos->y = dpy_w - pos->x - pos->w;
576 pos->x = dpy_h - temp - pos->h;
584 _tdm_sprd_capture_oneshot_composite_layers_sw(tdm_sprd_capture_data *capture_data,
585 tbm_surface_h buffer)
587 tbm_surface_info_s buf_info;
588 const hal_tdm_output_mode *current_mode = NULL;
589 tbm_surface_h surface = NULL;
590 tdm_sprd_capture_composite *composite_data = NULL;
591 tdm_sprd_capture_pp_data ** pp_tasks = NULL;
593 hal_tdm_error tdm_err = HAL_TDM_ERROR_NONE;
595 if ((sprd_output_get_mode(capture_data->output_data, ¤t_mode)) != HAL_TDM_ERROR_NONE) {
596 TDM_BACKEND_ERR("can't get output mode");
597 return HAL_TDM_ERROR_OPERATION_FAILED;
599 if (current_mode == NULL) {
600 TDM_BACKEND_WRN("Output mode not init. Can't capture");
601 return HAL_TDM_ERROR_OPERATION_FAILED;
604 int_err = tbm_surface_get_info(buffer, &buf_info);
605 TDM_BACKEND_RETURN_VAL_IF_FAIL(int_err == TBM_SURFACE_ERROR_NONE, HAL_TDM_ERROR_BAD_REQUEST);
607 composite_data = calloc(1, sizeof(tdm_sprd_capture_composite));
608 if (composite_data == NULL) {
609 TDM_BACKEND_WRN("Out of memory");
610 tdm_err = HAL_TDM_ERROR_OUT_OF_MEMORY;
614 composite_data->client_buffer = buffer;
615 tbm_surface_internal_ref(buffer);
616 LIST_ADD(&composite_data->link, &capture_data->composite_list);
617 pp_tasks = calloc(NUM_LAYERS, sizeof(tdm_sprd_capture_pp_data *));
618 if (pp_tasks == NULL) {
619 TDM_BACKEND_WRN("Out of memory");
620 tdm_err = HAL_TDM_ERROR_OUT_OF_MEMORY;
623 for (i = 0; i < NUM_LAYERS; ++i) {
624 tdm_sprd_output *output_data = NULL;
625 tdm_sprd_layer *layer_data = NULL;
626 tdm_sprd_layer_info layer_info;
628 output_data = (tdm_sprd_output *)capture_data->output_data;
629 layer_data = tdm_sprd_output_get_tdm_sprd_layer(output_data, i);
630 if (!layer_data) continue;
633 if (tdm_sprd_layer_get_info(layer_data, &layer_info) != HAL_TDM_ERROR_NONE) {
634 TDM_BACKEND_WRN("can't get layer %p info. Skip", layer_data);
637 if (layer_info.src_config.pos.h == 0 || layer_info.src_config.pos.w == 0) {
638 TDM_BACKEND_INFO("layer %p info is NULL. Skip", layer_data);
641 if (tdm_sprd_layer_get_buffer(layer_data, &surface) != HAL_TDM_ERROR_NONE) {
642 TDM_BACKEND_WRN("can't get layer %p surface. Skip", layer_data);
645 if (surface == NULL) {
646 TDM_BACKEND_INFO("layer %p buffer is NULL. Skip", layer_data);
649 tbm_surface_internal_ref(surface);
650 TDM_BACKEND_DBG("Get layer %p surface %p", layer_data, surface);
653 int output_width = current_mode->hdisplay;
654 int width = layer_info.src_config.pos.w;
655 int pos_x = layer_info.dst_pos.x;
656 hal_tdm_pos scale_pos = {.x = pos_x, .y = layer_info.dst_pos.y,
657 .w = ((width + pos_x) <= output_width ? width : output_width - pos_x),
658 .h = layer_info.src_config.pos.h};
659 hal_tdm_pos src_pos = layer_info.src_config.pos;
660 hal_tdm_pos dst_pos = capture_data->info.dst_config.pos;
662 TDM_BACKEND_DBG("src_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", src_pos.x, src_pos.y,
663 src_pos.w, src_pos.h);
664 TDM_BACKEND_DBG("dst_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", dst_pos.x, dst_pos.y,
665 dst_pos.w, dst_pos.h);
666 TDM_BACKEND_DBG("scale_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", scale_pos.x, scale_pos.y,
667 scale_pos.w, scale_pos.h);
668 if (dst_pos.w == 0 || dst_pos.h == 0) {
671 dst_pos.h = tbm_surface_get_height(buffer);
672 dst_pos.w = tbm_surface_get_width(buffer);
674 if (dst_pos.w == 0 || dst_pos.h == 0) {
675 TDM_BACKEND_WRN("dst_pos size is zero");
676 tbm_surface_internal_unref(surface);
680 _tdm_sprd_capture_oneshot_center_rect(current_mode->hdisplay,
681 current_mode->vdisplay,
682 dst_pos.w, dst_pos.h, &dst_pos);
684 TDM_BACKEND_DBG("--> new_dst_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", dst_pos.x, dst_pos.y,
685 dst_pos.w, dst_pos.h);
688 _tdm_sprd_capture_oneshot_transform_rect(current_mode->hdisplay,
689 current_mode->vdisplay,
690 capture_data->info.transform,
693 if (capture_data->info.transform & 1) {
694 _tdm_sprd_capture_oneshot_rect_scale(current_mode->vdisplay,
695 current_mode->hdisplay,
696 dst_pos.w, dst_pos.h, &scale_pos);
698 _tdm_sprd_capture_oneshot_rect_scale(current_mode->hdisplay,
699 current_mode->vdisplay,
700 dst_pos.w, dst_pos.h, &scale_pos);
703 TDM_BACKEND_DBG("scale_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", scale_pos.x, scale_pos.y,
704 scale_pos.w, scale_pos.h);
706 if (capture_data->info.transform & 1) {
710 tbm_surface_h temp_buffer = tbm_surface_create(dst_pos.w,
712 TBM_FORMAT_ARGB8888);
713 if (temp_buffer == NULL) {
714 TDM_BACKEND_WRN("Out of memory");
715 tbm_surface_internal_unref(surface);
719 dst_pos.x += scale_pos.x;
720 dst_pos.y += scale_pos.y;
721 dst_pos.h = scale_pos.h;
722 dst_pos.w = scale_pos.w;
724 TDM_BACKEND_DBG("adapted dst_pos (x)(y)+(w)+(h) (%d)(%d)+(%d)+(%d)", dst_pos.x, dst_pos.y,
725 dst_pos.w, dst_pos.h);
727 tdm_err = _tdm_sprd_capture_make_converter(capture_data, surface, temp_buffer,
728 &src_pos, NULL, capture_data->info.transform,
730 if (tdm_err != HAL_TDM_ERROR_NONE) {
731 TDM_BACKEND_WRN("can't create converter");
732 tbm_surface_internal_unref(surface);
733 tbm_surface_internal_unref(temp_buffer);
738 if (tdm_sprd_layer_get_zpos(layer_data, &zpos) != HAL_TDM_ERROR_NONE) {
739 TDM_BACKEND_WRN("can't get layer %p zpos", layer_data);
740 _tdm_sprd_capture_destroy_converter(&pp_tasks[i]);
741 tbm_surface_internal_unref(surface);
742 tbm_surface_internal_unref(temp_buffer);
745 composite_data->temp_layer_buffer[i] = temp_buffer;
746 composite_data->dst_pos[i] = dst_pos;
747 composite_data->zpos[i] = zpos;
748 composite_data->need_done_buf_num++;
750 tbm_surface_internal_unref(surface);
753 if (!composite_data->need_done_buf_num) {
754 TDM_BACKEND_INFO("Layers buffer are empty. Nothing to do");
755 tdm_err = HAL_TDM_ERROR_NONE;
759 if (!IS_RGB(tbm_surface_get_format(composite_data->client_buffer))) {
760 tdm_sprd_capture_pp_data * pp_task = NULL;
761 composite_data->temp_composite_buffer = tbm_surface_create(tbm_surface_get_width(buffer),
762 tbm_surface_get_height(buffer),
763 TBM_FORMAT_ARGB8888);
764 if (composite_data->temp_composite_buffer == NULL) {
765 TDM_BACKEND_WRN("Out of memory");
766 tdm_err = HAL_TDM_ERROR_OUT_OF_MEMORY;
769 tdm_err = _tdm_sprd_capture_make_converter(capture_data, composite_data->temp_composite_buffer,
770 composite_data->client_buffer,
771 NULL, NULL, 0, &pp_task);
772 if (tdm_err != HAL_TDM_ERROR_NONE) {
773 TDM_BACKEND_WRN("can't create converter");
776 composite_data->composite_buf_pp_task = pp_task;
778 for (i = 0; i < NUM_LAYERS; i++) {
780 tdm_err = sprd_pp_commit(pp_tasks[i]->pp_link);
781 if (tdm_err != HAL_TDM_ERROR_NONE) {
782 composite_data->need_done_buf_num--;
783 _tdm_sprd_capture_destroy_converter(&pp_tasks[i]);
784 tbm_surface_internal_unref(composite_data->temp_layer_buffer[i]);
785 composite_data->temp_layer_buffer[i] = NULL;
789 if (!composite_data->need_done_buf_num) {
790 TDM_BACKEND_WRN("Can't capture layers");
797 return HAL_TDM_ERROR_NONE;
801 for (i = 0; i < NUM_LAYERS; ++i) {
803 _tdm_sprd_capture_destroy_converter(&pp_tasks[i]);
807 if (composite_data) {
808 LIST_DEL(&composite_data->link);
809 if (composite_data->composite_buf_pp_task) {
810 _tdm_sprd_capture_destroy_converter(&composite_data->composite_buf_pp_task);
812 if (composite_data->temp_composite_buffer != NULL) {
813 tbm_surface_internal_unref(composite_data->temp_composite_buffer);
815 for (i = 0; i < LAYER_COUNT_PER_OUTPUT; i++) {
816 if (composite_data->temp_layer_buffer[i] != NULL) {
817 tbm_surface_internal_unref(composite_data->temp_layer_buffer[i]);
820 if (composite_data->client_buffer != NULL) {
821 tbm_surface_internal_unref(composite_data->client_buffer);
822 if (capture_data->done_func) {
823 capture_data->done_func(capture_data,
824 composite_data->client_buffer,
825 capture_data->done_user_data);
827 composite_data->client_buffer = NULL;
829 free(composite_data);
836 _tdm_sprd_capture_set_timer(tdm_sprd_capture_data *capture_data)
838 struct itimerspec timeout;
841 timeout.it_value.tv_sec = timeout.it_interval.tv_sec = 0;
842 timeout.it_value.tv_nsec = 30000000;
843 timeout.it_interval.tv_nsec = 0;
845 ret = timerfd_settime(g_capture_data->timer_fd, 0, &timeout, NULL);
847 TDM_BACKEND_ERR("timerfd_settime fail : %d", errno);
848 return HAL_TDM_ERROR_OPERATION_FAILED;
851 TDM_BACKEND_DBG("set timer %llu", timeout.it_interval.tv_nsec);
853 return HAL_TDM_ERROR_NONE;
857 _tdm_sprd_capture_stop_timer(void)
859 struct itimerspec timeout;
862 timeout.it_value.tv_sec = timeout.it_interval.tv_sec = 0;
863 timeout.it_value.tv_nsec = timeout.it_interval.tv_nsec = 0;
865 ret = timerfd_settime(g_capture_data->timer_fd, 0, &timeout, NULL);
867 TDM_BACKEND_ERR("timerfd_settime stop fail : %d", errno);
868 return HAL_TDM_ERROR_OPERATION_FAILED;
871 TDM_BACKEND_DBG("stop timer");
873 return HAL_TDM_ERROR_NONE;
878 sprd_capture_destroy(hal_tdm_capture *capture)
880 tdm_sprd_capture_data *capture_data = capture;
881 if (!_tdm_sprd_capture_check_struct(capture_data)) {
884 tdm_sprd_capture_buffer *b = NULL, *bb = NULL;
885 tdm_sprd_capture_pp_data *pp_task = NULL, *pp_tasks_next = NULL;
886 tdm_sprd_capture_composite *composite = NULL, *composite_next = NULL;
888 capture_data->removing = 1;
889 TDM_BACKEND_DBG("capture(%p) destroy", capture_data);
891 LIST_FOR_EACH_ENTRY_SAFE(pp_task, pp_tasks_next, &capture_data->pp_convert_list, link) {
892 _tdm_sprd_capture_destroy_converter(&pp_task);
895 LIST_FOR_EACH_ENTRY_SAFE(composite, composite_next, &capture_data->composite_list, link) {
896 LIST_DEL(&composite->link);
897 for (i = 0; i < LAYER_COUNT_PER_OUTPUT; i++) {
898 if (composite->temp_layer_buffer[i]) {
899 tbm_surface_internal_unref(composite->temp_layer_buffer[i]);
900 composite->temp_layer_buffer[i] = NULL;
903 if (composite->client_buffer) {
904 tbm_surface_internal_unref(composite->client_buffer);
905 if (capture_data->done_func) {
906 capture_data->done_func(capture_data,
907 composite->client_buffer,
908 capture_data->done_user_data);
910 composite->client_buffer = NULL;
912 if (composite->temp_composite_buffer) {
913 tbm_surface_internal_unref(composite->temp_composite_buffer);
914 composite->temp_composite_buffer = NULL;
918 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &capture_data->pending_buffer_list, link) {
920 if (capture_data->done_func) {
921 capture_data->done_func(capture_data,
923 capture_data->done_user_data);
928 if (g_capture_data->stream_data == capture_data) {
929 TDM_BACKEND_DBG("stream capture %p remove", capture_data);
930 g_capture_data->stream_data = NULL;
931 g_capture_data->timer_running = 0;
932 _tdm_sprd_capture_stop_timer();
935 LIST_DEL(&capture_data->link);
936 capture_data->stamp = 0;
937 tdm_sprd_output_dettach_capture(capture_data->output_data, capture_data);
942 _tdm_sprd_capture_commit_stream(tdm_sprd_capture_data *capture_data)
946 if (g_capture_data->timer_fd == -1) {
947 TDM_BACKEND_ERR("cannot support stream capture");
948 return HAL_TDM_ERROR_BAD_REQUEST;
951 if ((g_capture_data->stream_data != NULL) && (g_capture_data->stream_data != capture_data)) {
952 TDM_BACKEND_ERR("previous stream capture is working. cannot execute.");
953 return HAL_TDM_ERROR_BUSY;
956 if (g_capture_data->timer_running) {
957 TDM_BACKEND_DBG("stream capture is working");
958 return HAL_TDM_ERROR_NONE;
961 ret = _tdm_sprd_capture_set_timer(capture_data);
962 if (ret != HAL_TDM_ERROR_NONE) {
963 TDM_BACKEND_ERR("timerfd_settime fail: %d", ret);
964 return HAL_TDM_ERROR_OPERATION_FAILED;
967 g_capture_data->timer_running = 1;
968 g_capture_data->stream_data = capture_data;
970 TDM_BACKEND_DBG("stream capture start");
972 return HAL_TDM_ERROR_NONE;
976 _tdm_sprd_capture_commit_oneshot(tdm_sprd_capture_data *capture_data)
978 tdm_sprd_capture_buffer *b = NULL, *bb = NULL;
979 tbm_surface_h current_buffer = NULL;
980 hal_tdm_error tdm_err = HAL_TDM_ERROR_NONE;
981 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &capture_data->pending_buffer_list, link) {
983 current_buffer = b->buffer;
984 tbm_surface_internal_ref(b->buffer);
986 tdm_err = _tdm_sprd_capture_oneshot_composite_layers_sw(capture_data, current_buffer);
987 tbm_surface_internal_unref(current_buffer);
988 if (tdm_err != HAL_TDM_ERROR_NONE) {
989 TDM_BACKEND_ERR("capture %p composite func return err %d", tdm_err);
997 sprd_display_get_capture_capability(hal_tdm_display *display, hal_tdm_caps_capture *caps)
1000 tdm_sprd_display *display_data = NULL;
1002 if (!caps || !display) {
1003 TDM_BACKEND_ERR("invalid params");
1004 return HAL_TDM_ERROR_INVALID_PARAMETER;
1007 display_data = (tdm_sprd_display *)display;
1009 caps->capabilities = HAL_TDM_CAPTURE_CAPABILITY_OUTPUT|
1010 HAL_TDM_CAPTURE_CAPABILITY_ONESHOT;
1011 if (display_data->timer_fd != -1)
1012 caps->capabilities |= HAL_TDM_CAPTURE_CAPABILITY_STREAM;
1014 caps->format_count = NUM_CAPTURE_FORMAT;
1015 caps->formats = NULL;
1016 if (NUM_CAPTURE_FORMAT) {
1017 /* will be freed in frontend */
1018 caps->formats = calloc(1, sizeof capture_client_formats);
1019 if (!caps->formats) {
1020 TDM_BACKEND_ERR("alloc failed");
1021 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1023 for (i = 0; i < caps->format_count; i++)
1024 caps->formats[i] = capture_client_formats[i];
1029 caps->preferred_align = 2;
1031 return HAL_TDM_ERROR_NONE;
1035 sprd_output_create_capture(hal_tdm_output *output, hal_tdm_error *error)
1038 TDM_BACKEND_ERR("invalid params");
1040 *error = HAL_TDM_ERROR_INVALID_PARAMETER;
1044 tdm_sprd_capture_data *capture_data = calloc(1, sizeof(tdm_sprd_capture_data));
1045 if (!capture_data) {
1046 TDM_BACKEND_ERR("alloc failed");
1048 *error = HAL_TDM_ERROR_OUT_OF_MEMORY;
1052 if ((capture_data->display_data = tdm_sprd_output_get_display(output)) == NULL) {
1053 TDM_BACKEND_ERR("invalid params");
1055 *error = HAL_TDM_ERROR_INVALID_PARAMETER;
1059 if ((tdm_sprd_output_attach_capture(output, capture_data)) != HAL_TDM_ERROR_NONE) {
1060 TDM_BACKEND_ERR("can't attach capture to output");
1062 *error = HAL_TDM_ERROR_OPERATION_FAILED;
1065 capture_data->output_data = output;
1066 capture_data->stamp = capture_stamp++;
1067 LIST_INITHEAD(&capture_data->pending_buffer_list);
1068 LIST_INITHEAD(&capture_data->pp_convert_list);
1069 LIST_INITHEAD(&capture_data->composite_list);
1071 if (!capture_list_init) {
1072 capture_list_init = 1;
1073 LIST_INITHEAD(&capture_list);
1075 LIST_ADDTAIL(&capture_data->link, &capture_list);
1076 TDM_BACKEND_DBG("capture(%p) create", capture_data);
1078 *error = HAL_TDM_ERROR_NONE;
1080 return capture_data;
1088 sprd_capture_set_info(hal_tdm_capture *capture, hal_tdm_info_capture *info)
1090 tdm_sprd_capture_data *capture_data = capture;
1091 if (!_tdm_sprd_capture_check_struct(capture_data)) {
1092 return HAL_TDM_ERROR_INVALID_PARAMETER;
1094 if (capture_data->removing) {
1095 TDM_BACKEND_INFO("Capture removing. Skip call func");
1096 return HAL_TDM_ERROR_BUSY;
1098 TDM_BACKEND_RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
1100 capture_data->info = *info;
1101 capture_data->info_changed = 1;
1103 return HAL_TDM_ERROR_NONE;
1107 sprd_capture_attach(hal_tdm_capture *capture, tbm_surface_h buffer)
1109 tdm_sprd_capture_data *capture_data = capture;
1110 tdm_sprd_capture_buffer *b;
1111 if (!_tdm_sprd_capture_check_struct(capture_data)) {
1112 return HAL_TDM_ERROR_INVALID_PARAMETER;
1114 if (capture_data->removing) {
1115 TDM_BACKEND_INFO("Capture removing. Skip call func");
1116 return HAL_TDM_ERROR_BUSY;
1118 TDM_BACKEND_RETURN_VAL_IF_FAIL(buffer, HAL_TDM_ERROR_INVALID_PARAMETER);
1119 b = calloc(1, sizeof(tdm_sprd_capture_buffer));
1121 TDM_BACKEND_ERR("alloc failed");
1122 return HAL_TDM_ERROR_NONE;
1124 TDM_BACKEND_DBG("capture %p attach buffer %p", capture, buffer);
1125 LIST_ADDTAIL(&b->link, &capture_data->pending_buffer_list);
1129 return HAL_TDM_ERROR_NONE;
1133 sprd_capture_commit(hal_tdm_capture *capture)
1135 tdm_sprd_capture_data *capture_data = capture;
1137 if (!_tdm_sprd_capture_check_struct(capture_data)) {
1138 return HAL_TDM_ERROR_INVALID_PARAMETER;
1140 if (capture_data->removing) {
1141 TDM_BACKEND_INFO("Capture removing. Skip call func");
1142 return HAL_TDM_ERROR_BUSY;
1144 TDM_BACKEND_DBG("capture %p commit", capture);
1145 if (capture_data->info.type == HAL_TDM_CAPTURE_TYPE_ONESHOT)
1146 ret = _tdm_sprd_capture_commit_oneshot(capture_data);
1148 ret = _tdm_sprd_capture_commit_stream(capture_data);
1154 sprd_capture_set_done_handler(hal_tdm_capture *capture, hal_tdm_capture_done_handler func, void *user_data)
1156 tdm_sprd_capture_data *capture_data = capture;
1158 if (!_tdm_sprd_capture_check_struct(capture_data)) {
1159 return HAL_TDM_ERROR_INVALID_PARAMETER;
1161 if (capture_data->removing) {
1162 TDM_BACKEND_INFO("Capture removing. Skip call func");
1163 return HAL_TDM_ERROR_BUSY;
1165 TDM_BACKEND_RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
1167 capture_data->done_func = func;
1168 capture_data->done_user_data = user_data;
1169 TDM_BACKEND_DBG("capture %p set done handler func %p", capture, func);
1170 return HAL_TDM_ERROR_NONE;
1174 tdm_sprd_capture_init(tdm_sprd_display *display_data)
1176 tdm_sprd_capture_internal *capture_data_internal = calloc(1, sizeof(tdm_sprd_capture_internal));
1177 if (!capture_data_internal) {
1178 TDM_BACKEND_ERR("alloc failed");
1180 return HAL_TDM_ERROR_OUT_OF_MEMORY;
1182 capture_data_internal->timer_fd = display_data->timer_fd;
1184 g_capture_data = capture_data_internal;
1186 return HAL_TDM_ERROR_NONE;
1190 tdm_sprd_capture_deinit(tdm_sprd_display *display_data)
1192 if (g_capture_data == NULL)
1195 free(g_capture_data);
1196 g_capture_data = NULL;
1200 tdm_sprd_capture_timer_cb(tdm_sprd_display *display_data)
1202 tdm_sprd_capture_data *capture_data = NULL;
1203 tdm_sprd_capture_buffer *b = NULL, *bb = NULL;
1204 tbm_surface_h current_buffer = NULL;
1206 int expired = read(display_data->timer_fd, &buf, sizeof(uint64_t));
1208 TDM_BACKEND_ERR("read fail");
1210 g_capture_data->timer_running = 0;
1211 if (g_capture_data == NULL || g_capture_data->stream_data == NULL)
1214 capture_data = g_capture_data->stream_data;
1215 if (!_tdm_sprd_capture_check_struct(capture_data))
1218 if (capture_data->removing) {
1219 TDM_BACKEND_INFO("Capture %p Postponded removing", capture_data);
1220 _tdm_sprd_capture_stop_timer();
1221 g_capture_data->timer_running = 0;
1222 g_capture_data->stream_data = NULL;
1223 LIST_DEL(&capture_data->link);
1224 capture_data->stamp = 0;
1225 tdm_sprd_output_dettach_capture(capture_data->output_data, capture_data);
1230 if (!LIST_IS_EMPTY(&capture_data->composite_list)) {
1231 TDM_BACKEND_DBG("Converter is busy");
1234 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &capture_data->pending_buffer_list, link) {
1236 current_buffer = b->buffer;
1237 tbm_surface_internal_ref(current_buffer);
1239 _tdm_sprd_capture_oneshot_composite_layers_sw(capture_data, current_buffer);
1240 tbm_surface_internal_unref(current_buffer);