1 /**************************************************************************
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
37 #include "tbm_bufmgr.h"
38 #include "tbm_bufmgr_int.h"
39 #include "tbm_surface_internal.h"
44 #define TBM_SURFACE_MAGIC 0xBF021234
46 static tbm_bufmgr g_surface_bufmgr;
47 static pthread_mutex_t tbm_surface_lock = PTHREAD_MUTEX_INITIALIZER;
48 void _tbm_surface_mutex_unlock(void);
51 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
53 TBM_ERR("'%s' failed.\n", #cond);\
54 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
55 _tbm_surface_mutex_unlock();\
60 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
62 TBM_ERR("'%s' failed.\n", #cond);\
63 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
64 _tbm_surface_mutex_unlock();\
71 _tbm_surface_internal_get_time(void)
76 clock_gettime(CLOCK_MONOTONIC, &tp);
77 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
83 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
85 LIST_DEL(&debug_data->item_link);
87 if (debug_data->key) free(debug_data->key);
88 if (debug_data->value) free(debug_data->value);
93 _tbm_surface_internal_format_to_str(tbm_format format)
97 return "TBM_FORMAT_C8";
98 case TBM_FORMAT_RGB332:
99 return "TBM_FORMAT_RGB332";
100 case TBM_FORMAT_BGR233:
101 return "TBM_FORMAT_BGR233";
102 case TBM_FORMAT_XRGB4444:
103 return "TBM_FORMAT_XRGB4444";
104 case TBM_FORMAT_XBGR4444:
105 return "TBM_FORMAT_XBGR4444";
106 case TBM_FORMAT_RGBX4444:
107 return "TBM_FORMAT_RGBX4444";
108 case TBM_FORMAT_BGRX4444:
109 return "TBM_FORMAT_BGRX4444";
110 case TBM_FORMAT_ARGB4444:
111 return "TBM_FORMAT_ARGB4444";
112 case TBM_FORMAT_ABGR4444:
113 return "TBM_FORMAT_ABGR4444";
114 case TBM_FORMAT_RGBA4444:
115 return "TBM_FORMAT_RGBA4444";
116 case TBM_FORMAT_BGRA4444:
117 return "TBM_FORMAT_BGRA4444";
118 case TBM_FORMAT_XRGB1555:
119 return "TBM_FORMAT_XRGB1555";
120 case TBM_FORMAT_XBGR1555:
121 return "TBM_FORMAT_XBGR1555";
122 case TBM_FORMAT_RGBX5551:
123 return "TBM_FORMAT_RGBX5551";
124 case TBM_FORMAT_BGRX5551:
125 return "TBM_FORMAT_BGRX5551";
126 case TBM_FORMAT_ARGB1555:
127 return "TBM_FORMAT_ARGB1555";
128 case TBM_FORMAT_ABGR1555:
129 return "TBM_FORMAT_ABGR1555";
130 case TBM_FORMAT_RGBA5551:
131 return "TBM_FORMAT_RGBA5551";
132 case TBM_FORMAT_BGRA5551:
133 return "TBM_FORMAT_BGRA5551";
134 case TBM_FORMAT_RGB565:
135 return "TBM_FORMAT_RGB565";
136 case TBM_FORMAT_BGR565:
137 return "TBM_FORMAT_BGR565";
138 case TBM_FORMAT_RGB888:
139 return "TBM_FORMAT_RGB888";
140 case TBM_FORMAT_BGR888:
141 return "TBM_FORMAT_BGR888";
142 case TBM_FORMAT_XRGB8888:
143 return "TBM_FORMAT_XRGB8888";
144 case TBM_FORMAT_XBGR8888:
145 return "TBM_FORMAT_XBGR8888";
146 case TBM_FORMAT_RGBX8888:
147 return "TBM_FORMAT_RGBX8888";
148 case TBM_FORMAT_BGRX8888:
149 return "TBM_FORMAT_BGRX8888";
150 case TBM_FORMAT_ARGB8888:
151 return "TBM_FORMAT_ARGB8888";
152 case TBM_FORMAT_ABGR8888:
153 return "TBM_FORMAT_ABGR8888";
154 case TBM_FORMAT_RGBA8888:
155 return "TBM_FORMAT_RGBA8888";
156 case TBM_FORMAT_BGRA8888:
157 return "TBM_FORMAT_BGRA8888";
158 case TBM_FORMAT_XRGB2101010:
159 return "TBM_FORMAT_XRGB2101010";
160 case TBM_FORMAT_XBGR2101010:
161 return "TBM_FORMAT_XBGR2101010";
162 case TBM_FORMAT_RGBX1010102:
163 return "TBM_FORMAT_RGBX1010102";
164 case TBM_FORMAT_BGRX1010102:
165 return "TBM_FORMAT_BGRX1010102";
166 case TBM_FORMAT_ARGB2101010:
167 return "TBM_FORMAT_ARGB2101010";
168 case TBM_FORMAT_ABGR2101010:
169 return "TBM_FORMAT_ABGR2101010";
170 case TBM_FORMAT_RGBA1010102:
171 return "TBM_FORMAT_RGBA1010102";
172 case TBM_FORMAT_BGRA1010102:
173 return "TBM_FORMAT_BGRA1010102";
174 case TBM_FORMAT_YUYV:
175 return "TBM_FORMAT_YUYV";
176 case TBM_FORMAT_YVYU:
177 return "TBM_FORMAT_YVYU";
178 case TBM_FORMAT_UYVY:
179 return "TBM_FORMAT_UYVY";
180 case TBM_FORMAT_VYUY:
181 return "TBM_FORMAT_VYUY";
182 case TBM_FORMAT_AYUV:
183 return "TBM_FORMAT_AYUV";
184 case TBM_FORMAT_NV12:
185 return "TBM_FORMAT_NV12";
186 case TBM_FORMAT_NV21:
187 return "TBM_FORMAT_NV21";
188 case TBM_FORMAT_NV16:
189 return "TBM_FORMAT_NV16";
190 case TBM_FORMAT_NV61:
191 return "TBM_FORMAT_NV61";
192 case TBM_FORMAT_YUV410:
193 return "TBM_FORMAT_YUV410";
194 case TBM_FORMAT_YVU410:
195 return "TBM_FORMAT_YVU410";
196 case TBM_FORMAT_YUV411:
197 return "TBM_FORMAT_YUV411";
198 case TBM_FORMAT_YVU411:
199 return "TBM_FORMAT_YVU411";
200 case TBM_FORMAT_YUV420:
201 return "TBM_FORMAT_YUV420";
202 case TBM_FORMAT_YVU420:
203 return "TBM_FORMAT_YVU420";
204 case TBM_FORMAT_YUV422:
205 return "TBM_FORMAT_YUV422";
206 case TBM_FORMAT_YVU422:
207 return "TBM_FORMAT_YVU422";
208 case TBM_FORMAT_YUV444:
209 return "TBM_FORMAT_YUV444";
210 case TBM_FORMAT_YVU444:
211 return "TBM_FORMAT_YVU444";
212 case TBM_FORMAT_NV12MT:
213 return "TBM_FORMAT_NV12MT";
220 _tbm_surface_mutex_lock(void)
222 pthread_mutex_lock(&tbm_surface_lock);
226 _tbm_surface_mutex_unlock(void)
228 pthread_mutex_unlock(&tbm_surface_lock);
232 _init_surface_bufmgr(void)
234 g_surface_bufmgr = tbm_bufmgr_init(-1);
238 _deinit_surface_bufmgr(void)
240 if (!g_surface_bufmgr)
243 tbm_bufmgr_deinit(g_surface_bufmgr);
244 g_surface_bufmgr = NULL;
249 _tbm_surface_internal_magic_check(tbm_surface_h surface)
251 if (surface->magic != TBM_SURFACE_MAGIC)
258 _tbm_surface_internal_is_valid(tbm_surface_h surface)
261 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
262 TBM_ERR("error: No valid tbm_surface is NULL\n");
266 if (!_tbm_surface_internal_magic_check(surface)) {
267 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
268 TBM_ERR("error: No valid tbm_surface(%p)\n", surface);
276 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
277 int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
279 TBM_RETURN_VAL_IF_FAIL(surface, 0);
280 TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
282 struct _tbm_surface *surf = (struct _tbm_surface *)surface;
283 struct _tbm_bufmgr *bufmgr = surf->bufmgr;
287 TBM_RETURN_VAL_IF_FAIL(bufmgr != NULL, 0);
288 TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
289 TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
290 TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
292 if (bufmgr->use_hal_tbm) {
293 error = (tbm_error_e)hal_tbm_bufmgr_get_plane_data(bufmgr->hal_bufmgr, (hal_tbm_format)surf->info.format,
294 plane_idx, surf->info.width, surf->info.height, size, offset, pitch, bo_idx);
295 /* LCOV_EXCL_START */
296 if (error == TBM_ERROR_NOT_SUPPORTED) {
297 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
299 } else if (error != TBM_ERROR_NONE) {
300 TBM_ERR("Fail to surface_get_plane_data. surface(%p) error(%d)\n", surface, error);
301 _tbm_set_last_result(error);
306 } else if (bufmgr->backend_module_data) {
307 if (!bufmgr->bufmgr_func->bufmgr_get_plane_data) {
308 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
312 error = bufmgr->bufmgr_func->bufmgr_get_plane_data(bufmgr->bufmgr_data, surf->info.format, plane_idx,
313 surf->info.width, surf->info.height, size, offset, pitch, bo_idx);
314 if (error != TBM_ERROR_NONE) {
315 /* LCOV_EXCL_START */
316 TBM_ERR("Fail to surface_get_plane_data. surface(%p) error(%d)\n", surface, error);
317 _tbm_set_last_result(error);
323 if (!bufmgr->backend->surface_get_plane_data) {
324 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
328 ret = bufmgr->backend->surface_get_plane_data(surf->info.width,
329 surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
331 /* LCOV_EXCL_START */
332 TBM_ERR("Fail to surface_get_plane_data. surface(%p)\n", surface);
333 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
343 _tbm_surface_internal_destroy(tbm_surface_h surface)
346 tbm_bufmgr bufmgr = surface->bufmgr;
347 tbm_user_data *old_data = NULL, *tmp = NULL;
348 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
349 tbm_surface_destroy_func_info *func_info = NULL, *func_next = NULL;
351 if (!LIST_IS_EMPTY(&surface->destroy_funcs)) {
352 LIST_FOR_EACH_ENTRY_SAFE(func_info, func_next, &surface->destroy_funcs, item_link) {
353 func_info->destroy_func(surface, func_info->user_data);
355 TBM_DBG("free destroy_funcs %p\n", surface);
356 LIST_FOR_EACH_ENTRY_SAFE(func_info, func_next, &surface->destroy_funcs, item_link) {
357 LIST_DEL(&func_info->item_link);
362 /* destory the user_data_list */
363 if (!LIST_IS_EMPTY(&surface->user_data_list)) {
364 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
365 TBM_DBG("free user_data\n");
366 user_data_delete(old_data);
370 for (i = 0; i < surface->num_bos; i++) {
371 surface->bos[i]->surface = NULL;
373 tbm_bo_unref(surface->bos[i]);
374 surface->bos[i] = NULL;
377 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
378 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
379 _tbm_surface_internal_debug_data_delete(debug_old_data);
382 LIST_DEL(&surface->item_link);
388 if (bufmgr && LIST_IS_EMPTY(&bufmgr->surf_list)) {
389 LIST_DELINIT(&bufmgr->surf_list);
391 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
392 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
393 _tbm_surface_internal_debug_data_delete(debug_old_data);
397 _deinit_surface_bufmgr();
401 /* LCOV_EXCL_START */
403 _tbm_surface_check_file_is_symbolic_link(const char* path)
410 if (stat(path, &sb) != 0)
413 if (S_ISLNK(sb.st_mode))
421 _tbm_surface_internal_get_num_planes(tbm_format format)
427 case TBM_FORMAT_RGB332:
428 case TBM_FORMAT_BGR233:
429 case TBM_FORMAT_XRGB4444:
430 case TBM_FORMAT_XBGR4444:
431 case TBM_FORMAT_RGBX4444:
432 case TBM_FORMAT_BGRX4444:
433 case TBM_FORMAT_ARGB4444:
434 case TBM_FORMAT_ABGR4444:
435 case TBM_FORMAT_RGBA4444:
436 case TBM_FORMAT_BGRA4444:
437 case TBM_FORMAT_XRGB1555:
438 case TBM_FORMAT_XBGR1555:
439 case TBM_FORMAT_RGBX5551:
440 case TBM_FORMAT_BGRX5551:
441 case TBM_FORMAT_ARGB1555:
442 case TBM_FORMAT_ABGR1555:
443 case TBM_FORMAT_RGBA5551:
444 case TBM_FORMAT_BGRA5551:
445 case TBM_FORMAT_RGB565:
446 case TBM_FORMAT_BGR565:
447 case TBM_FORMAT_RGB888:
448 case TBM_FORMAT_BGR888:
449 case TBM_FORMAT_XRGB8888:
450 case TBM_FORMAT_XBGR8888:
451 case TBM_FORMAT_RGBX8888:
452 case TBM_FORMAT_BGRX8888:
453 case TBM_FORMAT_ARGB8888:
454 case TBM_FORMAT_ABGR8888:
455 case TBM_FORMAT_RGBA8888:
456 case TBM_FORMAT_BGRA8888:
457 case TBM_FORMAT_XRGB2101010:
458 case TBM_FORMAT_XBGR2101010:
459 case TBM_FORMAT_RGBX1010102:
460 case TBM_FORMAT_BGRX1010102:
461 case TBM_FORMAT_ARGB2101010:
462 case TBM_FORMAT_ABGR2101010:
463 case TBM_FORMAT_RGBA1010102:
464 case TBM_FORMAT_BGRA1010102:
465 case TBM_FORMAT_YUYV:
466 case TBM_FORMAT_YVYU:
467 case TBM_FORMAT_UYVY:
468 case TBM_FORMAT_VYUY:
469 case TBM_FORMAT_AYUV:
472 case TBM_FORMAT_NV12:
473 case TBM_FORMAT_NV12MT:
474 case TBM_FORMAT_NV21:
475 case TBM_FORMAT_NV16:
476 case TBM_FORMAT_NV61:
479 case TBM_FORMAT_YUV410:
480 case TBM_FORMAT_YVU410:
481 case TBM_FORMAT_YUV411:
482 case TBM_FORMAT_YVU411:
483 case TBM_FORMAT_YUV420:
484 case TBM_FORMAT_YVU420:
485 case TBM_FORMAT_YUV422:
486 case TBM_FORMAT_YVU422:
487 case TBM_FORMAT_YUV444:
488 case TBM_FORMAT_YVU444:
493 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
501 _tbm_surface_internal_get_bpp(tbm_format format)
508 case TBM_FORMAT_RGB332:
509 case TBM_FORMAT_BGR233:
512 case TBM_FORMAT_XRGB4444:
513 case TBM_FORMAT_XBGR4444:
514 case TBM_FORMAT_RGBX4444:
515 case TBM_FORMAT_BGRX4444:
516 case TBM_FORMAT_ARGB4444:
517 case TBM_FORMAT_ABGR4444:
518 case TBM_FORMAT_RGBA4444:
519 case TBM_FORMAT_BGRA4444:
520 case TBM_FORMAT_XRGB1555:
521 case TBM_FORMAT_XBGR1555:
522 case TBM_FORMAT_RGBX5551:
523 case TBM_FORMAT_BGRX5551:
524 case TBM_FORMAT_ARGB1555:
525 case TBM_FORMAT_ABGR1555:
526 case TBM_FORMAT_RGBA5551:
527 case TBM_FORMAT_BGRA5551:
528 case TBM_FORMAT_RGB565:
529 case TBM_FORMAT_BGR565:
532 case TBM_FORMAT_RGB888:
533 case TBM_FORMAT_BGR888:
536 case TBM_FORMAT_XRGB8888:
537 case TBM_FORMAT_XBGR8888:
538 case TBM_FORMAT_RGBX8888:
539 case TBM_FORMAT_BGRX8888:
540 case TBM_FORMAT_ARGB8888:
541 case TBM_FORMAT_ABGR8888:
542 case TBM_FORMAT_RGBA8888:
543 case TBM_FORMAT_BGRA8888:
544 case TBM_FORMAT_XRGB2101010:
545 case TBM_FORMAT_XBGR2101010:
546 case TBM_FORMAT_RGBX1010102:
547 case TBM_FORMAT_BGRX1010102:
548 case TBM_FORMAT_ARGB2101010:
549 case TBM_FORMAT_ABGR2101010:
550 case TBM_FORMAT_RGBA1010102:
551 case TBM_FORMAT_BGRA1010102:
552 case TBM_FORMAT_YUYV:
553 case TBM_FORMAT_YVYU:
554 case TBM_FORMAT_UYVY:
555 case TBM_FORMAT_VYUY:
556 case TBM_FORMAT_AYUV:
559 case TBM_FORMAT_NV12:
560 case TBM_FORMAT_NV12MT:
561 case TBM_FORMAT_NV21:
564 case TBM_FORMAT_NV16:
565 case TBM_FORMAT_NV61:
568 case TBM_FORMAT_YUV410:
569 case TBM_FORMAT_YVU410:
572 case TBM_FORMAT_YUV411:
573 case TBM_FORMAT_YVU411:
574 case TBM_FORMAT_YUV420:
575 case TBM_FORMAT_YVU420:
578 case TBM_FORMAT_YUV422:
579 case TBM_FORMAT_YVU422:
582 case TBM_FORMAT_YUV444:
583 case TBM_FORMAT_YVU444:
587 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
595 tbm_surface_internal_is_valid(tbm_surface_h surface)
599 _tbm_surface_mutex_lock();
600 _tbm_set_last_result(TBM_ERROR_NONE);
602 /* Return silently if surface is null. */
604 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
605 _tbm_surface_mutex_unlock();
609 ret = _tbm_surface_internal_is_valid(surface);
611 _tbm_surface_mutex_unlock();
617 tbm_surface_internal_query_supported_formats(uint32_t **formats,
620 struct _tbm_bufmgr *bufmgr;
622 bool bufmgr_initialized = false;
625 _tbm_surface_mutex_lock();
626 _tbm_set_last_result(TBM_ERROR_NONE);
628 TBM_SURFACE_RETURN_VAL_IF_FAIL(formats, 0);
629 TBM_SURFACE_RETURN_VAL_IF_FAIL(num, 0);
631 if (!g_surface_bufmgr) {
632 _init_surface_bufmgr();
633 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
634 bufmgr_initialized = true;
637 bufmgr = g_surface_bufmgr;
639 if (bufmgr->use_hal_tbm) {
640 error = (tbm_error_e)hal_tbm_bufmgr_get_supported_formats(bufmgr->hal_bufmgr, formats, num);
641 /* LCOV_EXCL_START */
642 if (error == TBM_ERROR_NOT_SUPPORTED) {
643 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
645 } else if (error != TBM_ERROR_NONE) {
646 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
651 } else if (bufmgr->backend_module_data) {
652 if (!bufmgr->bufmgr_func->bufmgr_get_supported_formats) {
653 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
657 error = bufmgr->bufmgr_func->bufmgr_get_supported_formats(bufmgr->bufmgr_data, formats, num);
658 if (error != TBM_ERROR_NONE) {
659 /* LCOV_EXCL_START */
660 TBM_ERR("Fail to surface_supported_format. error(%d)\n", error);
662 /* LCOV_EXCL_START */
666 if (!bufmgr->backend->surface_supported_format) {
667 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
671 ret = bufmgr->backend->surface_supported_format(formats, num);
673 /* LCOV_EXCL_START */
674 TBM_ERR("Fail to surface_supported_format.\n");
675 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
677 /* LCOV_EXCL_START */
681 TBM_TRACE_SURFACE_INTERNAL("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
683 if (bufmgr_initialized) {
684 LIST_DELINIT(&g_surface_bufmgr->surf_list);
685 _deinit_surface_bufmgr();
688 _tbm_surface_mutex_unlock();
692 /* LCOV_EXCL_START */
694 if (bufmgr_initialized) {
695 LIST_DELINIT(&g_surface_bufmgr->surf_list);
696 _deinit_surface_bufmgr();
698 _tbm_surface_mutex_unlock();
700 TBM_ERR("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
707 tbm_surface_internal_get_num_planes(tbm_format format)
711 _tbm_surface_mutex_lock();
712 _tbm_set_last_result(TBM_ERROR_NONE);
714 num_planes = _tbm_surface_internal_get_num_planes(format);
716 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
717 _tbm_surface_mutex_unlock();
721 TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
723 _tbm_surface_mutex_unlock();
729 tbm_surface_internal_get_bpp(tbm_format format)
733 _tbm_surface_mutex_lock();
734 _tbm_set_last_result(TBM_ERROR_NONE);
736 bpp = _tbm_surface_internal_get_bpp(format);
738 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
739 _tbm_surface_mutex_unlock();
743 _tbm_surface_mutex_unlock();
745 TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
751 tbm_surface_internal_create_with_flags(int width, int height,
752 int format, int flags)
754 struct _tbm_bufmgr *bufmgr;
755 struct _tbm_surface *surf = NULL;
759 uint32_t bo_size = 0;
762 bool bufmgr_initialized = false;
765 _tbm_surface_mutex_lock();
766 _tbm_set_last_result(TBM_ERROR_NONE);
768 TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, NULL);
769 TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, NULL);
771 if (!g_surface_bufmgr) {
772 _init_surface_bufmgr();
773 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
774 bufmgr_initialized = true;
777 bufmgr = g_surface_bufmgr;
778 if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
779 TBM_ERR("The bufmgr is invalid\n");
780 goto check_valid_fail;
783 surf = calloc(1, sizeof(struct _tbm_surface));
785 /* LCOV_EXCL_START */
786 TBM_ERR("fail to alloc surf\n");
787 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
788 goto alloc_surf_fail;
792 surf->magic = TBM_SURFACE_MAGIC;
793 surf->bufmgr = bufmgr;
794 surf->info.width = width;
795 surf->info.height = height;
796 surf->info.format = format;
797 surf->info.bpp = _tbm_surface_internal_get_bpp(format);
798 if (!surf->info.bpp) {
799 TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
802 surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
803 if (!surf->info.num_planes) {
804 TBM_ERR("fail to get num_planes. error(%s)\n", tbm_error_str(tbm_get_last_error()));
805 goto num_planes_fail;
809 /* get size, stride and offset bo_idx */
810 for (i = 0; i < surf->info.num_planes; i++) {
811 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
812 &offset, &stride, &bo_idx)) {
813 TBM_ERR("fail to query plane data\n");
814 goto query_plane_data_fail;
817 surf->info.planes[i].size = size;
818 surf->info.planes[i].offset = offset;
819 surf->info.planes[i].stride = stride;
820 surf->planes_bo_idx[i] = bo_idx;
825 for (i = 0; i < surf->info.num_planes; i++) {
826 surf->info.size += surf->info.planes[i].size;
828 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
829 surf->num_bos = surf->planes_bo_idx[i] + 1;
834 for (i = 0; i < surf->num_bos; i++) {
836 for (j = 0; j < surf->info.num_planes; j++) {
837 if (surf->planes_bo_idx[j] == i)
838 bo_size += surf->info.planes[j].size;
841 if (bufmgr->use_hal_tbm) {
842 surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, flags, &error);
843 if (error == TBM_ERROR_NOT_SUPPORTED) {
844 if (flags & TBM_BO_TILED) {
845 surf->bos[i] = tbm_bo_alloc_with_tiled_format(bufmgr, width, height, surf->info.bpp/8, format, flags, i, &error);
846 if (error == TBM_ERROR_NOT_SUPPORTED) {
847 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
848 } else if (error != TBM_ERROR_NONE) {
849 TBM_ERR("fail to alloc bo idx:%d\n", i);
853 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
857 TBM_ERR("fail to alloc bo idx:%d\n", i);
860 } else if (error != TBM_ERROR_NONE) {
861 TBM_ERR("fail to alloc bo idx:%d\n", i);
864 } else if (bufmgr->backend_module_data) {
865 if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
866 /* LCOV_EXCL_START */
867 surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, flags, &error);
869 TBM_ERR("fail to tbm_bo_alloc_with_format idx:%d\n", i);
873 } else if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format && (flags & TBM_BO_TILED)) {
874 /* LCOV_EXCL_START */
875 surf->bos[i] = tbm_bo_alloc_with_tiled_format(bufmgr, width, height, surf->info.bpp/8, format, flags, i, &error);
877 TBM_ERR("fail to tbm_bo_alloc_with_tiled_format idx:%d\n", i);
882 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
884 TBM_ERR("fail to alloc bo idx:%d\n", i);
889 if (bufmgr->backend->surface_bo_alloc) {
890 /* LCOV_EXCL_START */
891 surf->bos[i] = tbm_bo_alloc_with_surface(bufmgr, width, height, format, flags, i);
893 TBM_ERR("fail to tbm_bo_alloc_with_surface idx:%d\n", i);
898 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
900 TBM_ERR("fail to alloc bo idx:%d\n", i);
906 _tbm_bo_set_surface(surf->bos[i], surf);
909 TBM_TRACE_SURFACE_INTERNAL("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
910 _tbm_surface_internal_format_to_str(format), flags, surf);
912 LIST_INITHEAD(&surf->user_data_list);
913 LIST_INITHEAD(&surf->debug_data_list);
914 LIST_INITHEAD(&surf->destroy_funcs);
916 LIST_ADD(&surf->item_link, &bufmgr->surf_list);
918 _tbm_surface_mutex_unlock();
922 /* LCOV_EXCL_START */
924 for (j = 0; j < i; j++) {
926 tbm_bo_unref(surf->bos[j]);
928 query_plane_data_fail:
934 if (bufmgr_initialized && bufmgr) {
935 LIST_DELINIT(&bufmgr->surf_list);
936 _deinit_surface_bufmgr();
938 _tbm_surface_mutex_unlock();
940 TBM_ERR("error: width(%d) height(%d) format(%s) flags(%d)\n",
942 _tbm_surface_internal_format_to_str(format), flags);
949 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
950 tbm_bo *bos, int num)
952 struct _tbm_bufmgr *bufmgr;
953 struct _tbm_surface *surf = NULL;
955 bool bufmgr_initialized = false;
957 _tbm_surface_mutex_lock();
958 _tbm_set_last_result(TBM_ERROR_NONE);
960 TBM_SURFACE_RETURN_VAL_IF_FAIL(bos, NULL);
961 TBM_SURFACE_RETURN_VAL_IF_FAIL(info, NULL);
962 TBM_SURFACE_RETURN_VAL_IF_FAIL(info->num_planes > 0, NULL);
963 TBM_SURFACE_RETURN_VAL_IF_FAIL(num > 0, NULL);
964 TBM_SURFACE_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
966 if (!g_surface_bufmgr) {
967 _init_surface_bufmgr();
968 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
969 bufmgr_initialized = true;
972 bufmgr = g_surface_bufmgr;
973 if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
974 TBM_ERR("fail to validate the Bufmgr.\n");
975 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
976 goto check_valid_fail;
979 surf = calloc(1, sizeof(struct _tbm_surface));
981 /* LCOV_EXCL_START */
982 TBM_ERR("fail to allocate struct _tbm_surface.\n");
983 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
984 goto alloc_surf_fail;
988 surf->magic = TBM_SURFACE_MAGIC;
989 surf->bufmgr = bufmgr;
990 surf->info.width = info->width;
991 surf->info.height = info->height;
992 surf->info.format = info->format;
994 surf->info.bpp = info->bpp;
996 surf->info.bpp = _tbm_surface_internal_get_bpp(info->format);
997 if (!surf->info.bpp) {
998 TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1002 surf->info.num_planes = info->num_planes;
1005 /* get size, stride and offset */
1006 for (i = 0; i < info->num_planes; i++) {
1007 surf->info.planes[i].offset = info->planes[i].offset;
1008 surf->info.planes[i].stride = info->planes[i].stride;
1010 if (info->planes[i].size > 0)
1011 surf->info.planes[i].size = info->planes[i].size;
1013 uint32_t size = 0, offset = 0, stride = 0;
1016 if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
1017 TBM_ERR("fail to get plane_data. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1018 goto plane_data_fail;
1020 surf->info.planes[i].size = size;
1024 surf->planes_bo_idx[i] = 0;
1026 surf->planes_bo_idx[i] = i;
1029 if (info->size > 0) {
1030 surf->info.size = info->size;
1032 surf->info.size = 0;
1033 for (i = 0; i < info->num_planes; i++)
1034 surf->info.size += surf->info.planes[i].size;
1037 surf->flags = TBM_BO_DEFAULT;
1039 /* create only one bo */
1040 surf->num_bos = num;
1041 for (i = 0; i < num; i++) {
1042 if (bos[i] == NULL) {
1043 TBM_ERR("bos[%d] is null.\n", i);
1044 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1048 surf->bos[i] = tbm_bo_ref(bos[i]);
1049 _tbm_bo_set_surface(bos[i], surf);
1052 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
1053 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
1055 LIST_INITHEAD(&surf->user_data_list);
1056 LIST_INITHEAD(&surf->debug_data_list);
1057 LIST_INITHEAD(&surf->destroy_funcs);
1059 LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1061 _tbm_surface_mutex_unlock();
1065 /* LCOV_EXCL_START */
1069 for (i = 0; i < num; i++) {
1071 tbm_bo_unref(surf->bos[i]);
1076 if (bufmgr_initialized && bufmgr) {
1077 LIST_DELINIT(&bufmgr->surf_list);
1078 _deinit_surface_bufmgr();
1080 _tbm_surface_mutex_unlock();
1082 TBM_ERR("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
1083 info->width, info->height,
1084 _tbm_surface_internal_format_to_str(info->format), num);
1085 /* LCOV_EXCL_STOP */
1091 tbm_surface_internal_destroy(tbm_surface_h surface)
1093 _tbm_surface_mutex_lock();
1094 _tbm_set_last_result(TBM_ERROR_NONE);
1096 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1100 if (surface->refcnt > 0) {
1101 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1102 _tbm_surface_mutex_unlock();
1106 TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1108 if (surface->refcnt == 0)
1109 _tbm_surface_internal_destroy(surface);
1111 _tbm_surface_mutex_unlock();
1115 tbm_surface_internal_ref(tbm_surface_h surface)
1117 _tbm_surface_mutex_lock();
1118 _tbm_set_last_result(TBM_ERROR_NONE);
1120 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1124 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1126 _tbm_surface_mutex_unlock();
1130 tbm_surface_internal_unref(tbm_surface_h surface)
1132 _tbm_surface_mutex_lock();
1133 _tbm_set_last_result(TBM_ERROR_NONE);
1135 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1139 if (surface->refcnt > 0) {
1140 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1141 _tbm_surface_mutex_unlock();
1145 TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1147 if (surface->refcnt == 0)
1148 _tbm_surface_internal_destroy(surface);
1150 _tbm_surface_mutex_unlock();
1154 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1156 struct _tbm_surface *surf;
1159 _tbm_surface_mutex_lock();
1160 _tbm_set_last_result(TBM_ERROR_NONE);
1162 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1164 surf = (struct _tbm_surface *)surface;
1165 num = surf->num_bos;
1168 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1170 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)\n", surface, num);
1172 _tbm_surface_mutex_unlock();
1178 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1180 struct _tbm_surface *surf;
1183 _tbm_surface_mutex_lock();
1184 _tbm_set_last_result(TBM_ERROR_NONE);
1186 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1187 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1189 surf = (struct _tbm_surface *)surface;
1190 bo = surf->bos[bo_idx];
1192 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
1194 _tbm_surface_mutex_unlock();
1200 tbm_surface_internal_get_size(tbm_surface_h surface)
1202 struct _tbm_surface *surf;
1205 _tbm_surface_mutex_lock();
1206 _tbm_set_last_result(TBM_ERROR_NONE);
1208 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1210 surf = (struct _tbm_surface *)surface;
1211 size = surf->info.size;
1213 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)\n", surface, size);
1215 _tbm_surface_mutex_unlock();
1221 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1222 uint32_t *size, uint32_t *offset, uint32_t *pitch)
1224 struct _tbm_surface *surf;
1226 _tbm_surface_mutex_lock();
1227 _tbm_set_last_result(TBM_ERROR_NONE);
1229 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1230 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1232 surf = (struct _tbm_surface *)surface;
1234 if (plane_idx >= surf->info.num_planes) {
1235 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1236 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1237 _tbm_surface_mutex_unlock();
1242 *size = surf->info.planes[plane_idx].size;
1245 *offset = surf->info.planes[plane_idx].offset;
1248 *pitch = surf->info.planes[plane_idx].stride;
1250 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1251 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1252 surf->info.planes[plane_idx].stride);
1254 _tbm_surface_mutex_unlock();
1260 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1261 tbm_surface_info_s *info, int map)
1263 struct _tbm_surface *surf;
1264 tbm_bo_handle bo_handles[4];
1267 int planes_bo_idx[TBM_SURF_PLANE_MAX];
1270 _tbm_surface_mutex_lock();
1271 _tbm_set_last_result(TBM_ERROR_NONE);
1273 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1275 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1277 surf = (struct _tbm_surface *)surface;
1279 memset(info, 0x00, sizeof(tbm_surface_info_s));
1280 info->width = surf->info.width;
1281 info->height = surf->info.height;
1282 info->format = surf->info.format;
1283 info->bpp = surf->info.bpp;
1284 info->size = surf->info.size;
1285 info->num_planes = surf->info.num_planes;
1287 for (i = 0; i < surf->info.num_planes; i++) {
1288 info->planes[i].size = surf->info.planes[i].size;
1289 info->planes[i].offset = surf->info.planes[i].offset;
1290 info->planes[i].stride = surf->info.planes[i].stride;
1291 planes_bo_idx[i] = surf->planes_bo_idx[i];
1294 for (i = 0; i < surf->num_bos; i++)
1295 bos[i] = surf->bos[i];
1297 num_bos = surf->num_bos;
1300 _tbm_surface_mutex_unlock();
1301 for (i = 0; i < num_bos; i++) {
1302 bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1303 if (bo_handles[i].ptr == NULL) {
1304 for (j = 0; j < i; j++)
1305 tbm_bo_unmap(bos[j]);
1307 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1311 _tbm_surface_mutex_lock();
1313 for (i = 0; i < num_bos; i++) {
1314 bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1315 if (bo_handles[i].ptr == NULL) {
1316 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1317 _tbm_surface_mutex_unlock();
1323 for (i = 0; i < info->num_planes; i++) {
1324 if (bo_handles[planes_bo_idx[i]].ptr)
1325 info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1328 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1330 _tbm_surface_mutex_unlock();
1336 tbm_surface_internal_unmap(tbm_surface_h surface)
1338 struct _tbm_surface *surf;
1341 _tbm_surface_mutex_lock();
1342 _tbm_set_last_result(TBM_ERROR_NONE);
1344 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1346 surf = (struct _tbm_surface *)surface;
1348 for (i = 0; i < surf->num_bos; i++)
1349 tbm_bo_unmap(surf->bos[i]);
1351 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1353 _tbm_surface_mutex_unlock();
1357 tbm_surface_internal_get_width(tbm_surface_h surface)
1359 struct _tbm_surface *surf;
1362 _tbm_surface_mutex_lock();
1363 _tbm_set_last_result(TBM_ERROR_NONE);
1365 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1367 surf = (struct _tbm_surface *)surface;
1368 width = surf->info.width;
1370 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1372 _tbm_surface_mutex_unlock();
1378 tbm_surface_internal_get_height(tbm_surface_h surface)
1380 struct _tbm_surface *surf;
1381 unsigned int height;
1383 _tbm_surface_mutex_lock();
1384 _tbm_set_last_result(TBM_ERROR_NONE);
1386 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1388 surf = (struct _tbm_surface *)surface;
1389 height = surf->info.height;
1391 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1393 _tbm_surface_mutex_unlock();
1400 tbm_surface_internal_get_format(tbm_surface_h surface)
1402 struct _tbm_surface *surf;
1405 _tbm_surface_mutex_lock();
1406 _tbm_set_last_result(TBM_ERROR_NONE);
1408 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1410 surf = (struct _tbm_surface *)surface;
1411 format = surf->info.format;
1413 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1415 _tbm_surface_mutex_unlock();
1421 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1423 struct _tbm_surface *surf;
1426 _tbm_surface_mutex_lock();
1427 _tbm_set_last_result(TBM_ERROR_NONE);
1429 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1430 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1432 surf = (struct _tbm_surface *)surface;
1433 bo_idx = surf->planes_bo_idx[plane_idx];
1435 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1437 _tbm_surface_mutex_unlock();
1443 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1444 tbm_data_free data_free_func)
1446 tbm_user_data *data;
1448 _tbm_surface_mutex_lock();
1449 _tbm_set_last_result(TBM_ERROR_NONE);
1451 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1453 /* check if the data according to the key exist if so, return false. */
1454 data = user_data_lookup(&surface->user_data_list, key);
1456 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1457 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1458 _tbm_surface_mutex_unlock();
1462 data = user_data_create(key, data_free_func);
1464 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1465 _tbm_surface_mutex_unlock();
1469 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1471 LIST_ADD(&data->item_link, &surface->user_data_list);
1473 _tbm_surface_mutex_unlock();
1479 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1482 tbm_user_data *old_data;
1484 _tbm_surface_mutex_lock();
1485 _tbm_set_last_result(TBM_ERROR_NONE);
1487 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1489 old_data = user_data_lookup(&surface->user_data_list, key);
1491 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1492 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1493 _tbm_surface_mutex_unlock();
1497 if (old_data->data && old_data->free_func)
1498 old_data->free_func(old_data->data);
1500 old_data->data = data;
1502 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1504 _tbm_surface_mutex_unlock();
1510 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1513 tbm_user_data *old_data;
1515 _tbm_surface_mutex_lock();
1516 _tbm_set_last_result(TBM_ERROR_NONE);
1518 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1521 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1522 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1523 _tbm_surface_mutex_unlock();
1528 old_data = user_data_lookup(&surface->user_data_list, key);
1530 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1531 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1532 _tbm_surface_mutex_unlock();
1536 *data = old_data->data;
1538 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1540 _tbm_surface_mutex_unlock();
1546 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1549 tbm_user_data *old_data = (void *)0;
1551 _tbm_surface_mutex_lock();
1552 _tbm_set_last_result(TBM_ERROR_NONE);
1554 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1556 old_data = user_data_lookup(&surface->user_data_list, key);
1558 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1559 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1560 _tbm_surface_mutex_unlock();
1564 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1566 user_data_delete(old_data);
1568 _tbm_surface_mutex_unlock();
1573 /* LCOV_EXCL_START */
1575 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1577 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1579 return surface->debug_pid;
1583 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1585 _tbm_surface_mutex_lock();
1586 _tbm_set_last_result(TBM_ERROR_NONE);
1588 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1590 surface->debug_pid = pid;
1592 _tbm_surface_mutex_unlock();
1595 static tbm_surface_debug_data *
1596 _tbm_surface_internal_debug_data_create(char *key, char *value)
1598 tbm_surface_debug_data *debug_data = NULL;
1600 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1602 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1603 TBM_ERR("fail to allocate the debug_data.");
1607 if (key) debug_data->key = strdup(key);
1608 if (value) debug_data->value = strdup(value);
1614 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1616 if (!debug_data->value && !value)
1619 if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1622 if (debug_data->value)
1623 free(debug_data->value);
1626 debug_data->value = strdup(value);
1628 debug_data->value = NULL;
1631 static tbm_surface_debug_data *
1632 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1634 tbm_surface_debug_data *debug_data = NULL;
1636 if (LIST_IS_EMPTY(list))
1639 LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
1640 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
1648 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1650 tbm_surface_debug_data *debug_data = NULL;
1651 tbm_bufmgr bufmgr = NULL;
1653 _tbm_surface_mutex_lock();
1654 _tbm_set_last_result(TBM_ERROR_NONE);
1656 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1657 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1659 bufmgr = surface->bufmgr;
1661 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1663 debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
1665 _tbm_surface_internal_debug_data_value_update(debug_data, value);
1667 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1669 TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1670 _tbm_surface_mutex_unlock();
1674 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1677 /* add new debug key to list */
1678 debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
1680 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1682 LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
1685 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1687 _tbm_surface_mutex_unlock();
1693 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1695 tbm_surface_debug_data *old_data = NULL;
1697 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1699 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1700 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1701 if (!strcmp(old_data->key, key))
1702 return old_data->value;
1709 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1710 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1712 struct _tbm_surface_dump_buf_info {
1722 tbm_surface_info_s info;
1724 struct list_head link;
1727 struct _tbm_surface_dump_info {
1728 char *path; // copy???
1731 struct list_head *link;
1732 struct list_head surface_list; /* link of surface */
1735 static tbm_surface_dump_info *g_dump_info = NULL;
1736 static const char *dump_postfix[2] = {"png", "yuv"};
1737 static double scale_factor;
1740 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1741 void *data2, int size2, void *data3, int size3)
1744 unsigned int *blocks;
1746 if (_tbm_surface_check_file_is_symbolic_link(file))
1747 TBM_ERR("%s is symbolic link\n", file);
1749 fp = fopen(file, "w+");
1750 TBM_RETURN_IF_FAIL(fp != NULL);
1752 blocks = (unsigned int *)data1;
1753 fwrite(blocks, 1, size1, fp);
1756 blocks = (unsigned int *)data2;
1757 fwrite(blocks, 1, size2, fp);
1761 blocks = (unsigned int *)data3;
1762 fwrite(blocks, 1, size3, fp);
1769 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
1771 unsigned int *blocks = (unsigned int *)data;
1774 png_bytep *row_pointers;
1777 if (_tbm_surface_check_file_is_symbolic_link(file))
1778 TBM_ERR("%s is symbolic link\n", file);
1780 fp = fopen(file, "wb");
1781 TBM_RETURN_IF_FAIL(fp != NULL);
1783 png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1786 TBM_ERR("fail to create a png write structure.\n");
1791 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1793 TBM_ERR("fail to create a png info structure.\n");
1794 png_destroy_write_struct(&pPngStruct, NULL);
1799 if (setjmp(png_jmpbuf(pPngStruct))) {
1800 /* if png has problem of writing the file, we get here */
1801 TBM_ERR("fail to write png file.\n");
1802 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1807 png_init_io(pPngStruct, fp);
1808 if (format == TBM_FORMAT_XRGB8888) {
1810 png_set_IHDR(pPngStruct,
1817 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1820 png_set_IHDR(pPngStruct,
1825 PNG_COLOR_TYPE_RGBA,
1827 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1830 png_set_bgr(pPngStruct);
1831 png_write_info(pPngStruct, pPngInfo);
1833 row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1834 if (!row_pointers) {
1835 TBM_ERR("fail to allocate the png row_pointers.\n");
1836 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1841 for (y = 0; y < height; ++y) {
1845 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1847 TBM_ERR("fail to allocate the png row.\n");
1848 for (x = 0; x < y; x++)
1849 png_free(pPngStruct, row_pointers[x]);
1850 png_free(pPngStruct, row_pointers);
1851 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1855 row_pointers[y] = (png_bytep)row;
1857 for (x = 0; x < width; ++x) {
1858 unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
1860 if (pixel_size == 3) { // XRGB8888
1861 row[x * pixel_size] = (curBlock & 0xFF);
1862 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1863 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1864 } else { // ARGB8888
1865 row[x * pixel_size] = (curBlock & 0xFF);
1866 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1867 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1868 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1873 png_write_image(pPngStruct, row_pointers);
1874 png_write_end(pPngStruct, pPngInfo);
1876 for (y = 0; y < height; y++)
1877 png_free(pPngStruct, row_pointers[y]);
1878 png_free(pPngStruct, row_pointers);
1880 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1886 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1888 TBM_RETURN_IF_FAIL(path != NULL);
1889 TBM_RETURN_IF_FAIL(w > 0);
1890 TBM_RETURN_IF_FAIL(h > 0);
1891 TBM_RETURN_IF_FAIL(count > 0);
1893 tbm_surface_dump_buf_info *buf_info = NULL;
1894 tbm_surface_h tbm_surface;
1895 tbm_surface_info_s info;
1900 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
1904 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1905 TBM_RETURN_IF_FAIL(g_dump_info);
1907 LIST_INITHEAD(&g_dump_info->surface_list);
1908 g_dump_info->count = 0;
1909 g_dump_info->dump_max = count;
1911 /* get buffer size */
1912 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1913 if (tbm_surface == NULL) {
1914 TBM_ERR("tbm_surface_create fail\n");
1920 if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
1921 TBM_ERR("tbm_surface_get_info fail\n");
1922 tbm_surface_destroy(tbm_surface);
1927 buffer_size = info.size;
1928 tbm_surface_destroy(tbm_surface);
1930 /* create dump lists */
1931 for (i = 0; i < count; i++) {
1934 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1935 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1937 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1939 TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
1944 buf_info->index = i;
1946 buf_info->size = buffer_size;
1948 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1951 g_dump_info->path = path;
1952 g_dump_info->link = &g_dump_info->surface_list;
1956 TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1961 /* free resources */
1962 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1963 tbm_surface_dump_buf_info *tmp;
1965 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1966 tbm_bo_unref(buf_info->bo);
1967 LIST_DEL(&buf_info->link);
1972 TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
1981 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
1988 tbm_surface_internal_dump_start(path, w, h, count);
1989 scale_factor = scale;
1993 tbm_surface_internal_dump_end(void)
1995 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1996 tbm_bo_handle bo_handle;
2001 if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2008 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2011 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2012 if (bo_handle.ptr == NULL) {
2013 tbm_bo_unref(buf_info->bo);
2014 LIST_DEL(&buf_info->link);
2019 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2020 TBM_INFO("Dump File.. %s generated.\n", file);
2022 if (buf_info->dirty) {
2023 void *ptr1 = NULL, *ptr2 = NULL;
2025 switch (buf_info->info.format) {
2026 case TBM_FORMAT_ARGB8888:
2027 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2028 buf_info->info.planes[0].stride >> 2,
2029 buf_info->info.height,
2030 buf_info->info.planes[0].stride,
2031 TBM_FORMAT_ARGB8888);
2033 case TBM_FORMAT_XRGB8888:
2034 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2035 buf_info->info.planes[0].stride >> 2,
2036 buf_info->info.height,
2037 buf_info->info.planes[0].stride,
2038 TBM_FORMAT_XRGB8888);
2040 case TBM_FORMAT_YVU420:
2041 case TBM_FORMAT_YUV420:
2042 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2043 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2044 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2045 buf_info->info.planes[0].stride * buf_info->info.height,
2047 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2049 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2051 case TBM_FORMAT_NV12:
2052 case TBM_FORMAT_NV21:
2053 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2054 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2055 buf_info->info.planes[0].stride * buf_info->info.height,
2057 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2060 case TBM_FORMAT_YUYV:
2061 case TBM_FORMAT_UYVY:
2062 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2063 buf_info->info.planes[0].stride * buf_info->info.height,
2067 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2070 } else if (buf_info->dirty_shm)
2071 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2072 buf_info->shm_stride >> 2,
2074 buf_info->shm_stride, 0);
2076 tbm_bo_unmap(buf_info->bo);
2077 tbm_bo_unref(buf_info->bo);
2078 LIST_DEL(&buf_info->link);
2085 TBM_INFO("Dump End..\n");
2088 static pixman_format_code_t
2089 _tbm_surface_internal_pixman_format_get(tbm_format format)
2092 case TBM_FORMAT_ARGB8888:
2093 return PIXMAN_a8r8g8b8;
2094 case TBM_FORMAT_XRGB8888:
2095 return PIXMAN_x8r8g8b8;
2104 * This function supports only if a buffer has below formats.
2105 * - TBM_FORMAT_ARGB8888
2106 * - TBM_FORMAT_XRGB8888
2108 static tbm_surface_error_e
2109 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2110 int format, int src_stride, int src_w, int src_h,
2111 int dst_stride, int dst_w, int dst_h)
2113 pixman_image_t *src_img = NULL, *dst_img = NULL;
2114 pixman_format_code_t pixman_format;
2115 pixman_transform_t t;
2116 struct pixman_f_transform ft;
2117 double scale_x, scale_y;
2119 TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2120 TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2122 pixman_format = _tbm_surface_internal_pixman_format_get(format);
2123 TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2126 src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2127 (uint32_t*)src_ptr, src_stride);
2128 TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2131 dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2132 (uint32_t*)dst_ptr, dst_stride);
2133 TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2135 pixman_f_transform_init_identity(&ft);
2137 scale_x = (double)src_w / dst_w;
2138 scale_y = (double)src_h / dst_h;
2140 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2141 pixman_f_transform_translate(&ft, NULL, 0, 0);
2142 pixman_transform_from_pixman_f_transform(&t, &ft);
2143 pixman_image_set_transform(src_img, &t);
2145 pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2146 0, 0, 0, 0, 0, 0, dst_w, dst_h);
2148 pixman_image_unref(src_img);
2149 pixman_image_unref(dst_img);
2151 return TBM_SURFACE_ERROR_NONE;
2155 pixman_image_unref(src_img);
2157 return TBM_SURFACE_ERROR_INVALID_OPERATION;
2160 #define MAX_BOS 4 // This value is came from bos[4] in struct _tbm_surface
2161 #define KEY_LEN 5 // "_XXXX"
2162 #define KEYS_LEN KEY_LEN * MAX_BOS
2164 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2166 char *keys, temp_key[KEY_LEN + 1];
2167 struct _tbm_surface *surf;
2171 _tbm_surface_mutex_lock();
2173 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2175 surf = (struct _tbm_surface *)surface;
2177 num_bos = surf->num_bos;
2178 if (num_bos > MAX_BOS)
2181 keys = calloc(KEYS_LEN + 1, sizeof(char));
2183 TBM_ERR("Failed to alloc memory");
2184 _tbm_surface_mutex_unlock();
2188 for (i = 0; i < num_bos; i++) {
2189 memset(temp_key, 0x00, KEY_LEN + 1);
2191 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2192 strncat(keys, temp_key, KEY_LEN + 1);
2195 _tbm_surface_mutex_unlock();
2200 static void _tbm_surface_internal_put_keys(char *keys)
2207 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2209 TBM_RETURN_IF_FAIL(surface != NULL);
2210 TBM_RETURN_IF_FAIL(type != NULL);
2212 tbm_surface_dump_buf_info *buf_info;
2213 struct list_head *next_link;
2214 tbm_surface_info_s info;
2215 tbm_bo_handle bo_handle;
2216 const char *postfix;
2217 const char *format = NULL;
2224 next_link = g_dump_info->link->next;
2225 TBM_RETURN_IF_FAIL(next_link != NULL);
2227 if (next_link == &g_dump_info->surface_list) {
2228 next_link = next_link->next;
2229 TBM_RETURN_IF_FAIL(next_link != NULL);
2232 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2233 TBM_RETURN_IF_FAIL(buf_info != NULL);
2235 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2236 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2238 if (scale_factor > 0.0) {
2241 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
2242 TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2243 _tbm_surface_internal_format_to_str(info.format));
2244 tbm_surface_unmap(surface);
2248 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2250 buf_info->info.width = info.width * scale_factor;
2251 buf_info->info.height = info.height * scale_factor;
2252 buf_info->info.format = info.format;
2253 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2254 if (!buf_info->info.bpp) {
2255 TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2256 tbm_surface_unmap(surface);
2259 buf_info->info.num_planes = 1;
2260 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2261 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2263 if (buf_info->info.size > buf_info->size) {
2264 TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2265 buf_info->info.size, buf_info->size);
2266 tbm_surface_unmap(surface);
2270 if (info.size > buf_info->size) {
2271 TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2272 info.size, buf_info->size);
2273 tbm_surface_unmap(surface);
2277 /* make the file information */
2278 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2281 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) {
2282 postfix = dump_postfix[0];
2283 format = _tbm_surface_internal_format_to_str(info.format);
2285 postfix = dump_postfix[1];
2287 keys = _tbm_surface_internal_get_keys(surface);
2289 TBM_ERR("fail to get keys");
2290 tbm_surface_unmap(surface);
2295 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2296 if (!bo_handle.ptr) {
2297 TBM_ERR("fail to map bo");
2298 _tbm_surface_internal_put_keys(keys);
2299 tbm_surface_unmap(surface);
2302 memset(bo_handle.ptr, 0x00, buf_info->size);
2304 switch (info.format) {
2305 case TBM_FORMAT_ARGB8888:
2306 case TBM_FORMAT_XRGB8888:
2307 snprintf(buf_info->name, sizeof(buf_info->name),
2308 "%10.3f_%03d%s_%p_%s-%s.%s",
2309 _tbm_surface_internal_get_time(),
2310 g_dump_info->count++, keys, surface, format, type, postfix);
2312 if (scale_factor > 0.0) {
2313 ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2315 buf_info->info.format,
2316 info.planes[0].stride,
2317 info.width, info.height,
2318 buf_info->info.planes[0].stride,
2319 buf_info->info.width,
2320 buf_info->info.height);
2321 if (ret != TBM_SURFACE_ERROR_NONE) {
2322 TBM_ERR("fail to scale buffer");
2323 tbm_bo_unmap(buf_info->bo);
2324 _tbm_surface_internal_put_keys(keys);
2325 tbm_surface_unmap(surface);
2329 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2331 case TBM_FORMAT_YVU420:
2332 case TBM_FORMAT_YUV420:
2333 snprintf(buf_info->name, sizeof(buf_info->name),
2334 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2335 _tbm_surface_internal_get_time(),
2336 g_dump_info->count++, keys, type, info.planes[0].stride,
2337 info.height, FOURCC_STR(info.format), postfix);
2338 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2339 bo_handle.ptr += info.planes[0].stride * info.height;
2340 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2341 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2342 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2344 case TBM_FORMAT_NV12:
2345 case TBM_FORMAT_NV21:
2346 snprintf(buf_info->name, sizeof(buf_info->name),
2347 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2348 _tbm_surface_internal_get_time(),
2349 g_dump_info->count++, keys, type, info.planes[0].stride,
2350 info.height, FOURCC_STR(info.format), postfix);
2351 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2352 bo_handle.ptr += info.planes[0].stride * info.height;
2353 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2355 case TBM_FORMAT_YUYV:
2356 case TBM_FORMAT_UYVY:
2357 snprintf(buf_info->name, sizeof(buf_info->name),
2358 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2359 _tbm_surface_internal_get_time(),
2360 g_dump_info->count++, keys, type, info.planes[0].stride,
2361 info.height, FOURCC_STR(info.format), postfix);
2362 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2365 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2366 tbm_bo_unmap(buf_info->bo);
2367 _tbm_surface_internal_put_keys(keys);
2368 tbm_surface_unmap(surface);
2372 tbm_bo_unmap(buf_info->bo);
2374 _tbm_surface_internal_put_keys(keys);
2376 tbm_surface_unmap(surface);
2378 buf_info->dirty = 1;
2379 buf_info->dirty_shm = 0;
2381 if (g_dump_info->count == 1000)
2382 g_dump_info->count = 0;
2384 g_dump_info->link = next_link;
2386 TBM_INFO("Dump %s \n", buf_info->name);
2389 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2392 TBM_RETURN_IF_FAIL(ptr != NULL);
2393 TBM_RETURN_IF_FAIL(w > 0);
2394 TBM_RETURN_IF_FAIL(h > 0);
2395 TBM_RETURN_IF_FAIL(stride > 0);
2396 TBM_RETURN_IF_FAIL(type != NULL);
2398 tbm_surface_dump_buf_info *buf_info;
2399 struct list_head *next_link;
2400 tbm_bo_handle bo_handle;
2401 int ret, size, dw = 0, dh = 0, dstride = 0;
2406 next_link = g_dump_info->link->next;
2407 TBM_RETURN_IF_FAIL(next_link != NULL);
2409 if (next_link == &g_dump_info->surface_list) {
2410 next_link = next_link->next;
2411 TBM_RETURN_IF_FAIL(next_link != NULL);
2414 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2415 TBM_RETURN_IF_FAIL(buf_info != NULL);
2417 if (scale_factor > 0.0) {
2420 dw = w * scale_factor;
2421 dh = h * scale_factor;
2423 size = dstride * dh;
2427 if (size > buf_info->size) {
2428 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2429 size, buf_info->size);
2434 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2435 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2437 memset(bo_handle.ptr, 0x00, buf_info->size);
2438 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2440 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2441 _tbm_surface_internal_get_time(),
2442 g_dump_info->count++, type, dump_postfix[0]);
2443 if (scale_factor > 0.0) {
2444 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2445 TBM_FORMAT_ARGB8888, stride,
2446 w, h, dstride, dw, dh);
2447 if (ret != TBM_SURFACE_ERROR_NONE) {
2448 TBM_ERR("fail to scale buffer");
2449 tbm_bo_unmap(buf_info->bo);
2452 buf_info->shm_stride = dstride;
2453 buf_info->shm_h = dh;
2455 memcpy(bo_handle.ptr, ptr, size);
2456 buf_info->shm_stride = stride;
2457 buf_info->shm_h = h;
2460 tbm_bo_unmap(buf_info->bo);
2462 buf_info->dirty = 0;
2463 buf_info->dirty_shm = 1;
2465 if (g_dump_info->count == 1000)
2466 g_dump_info->count = 0;
2468 g_dump_info->link = next_link;
2470 TBM_INFO("Dump %s \n", buf_info->name);
2474 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2476 TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2477 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2478 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2480 tbm_surface_info_s info;
2481 const char *postfix;
2485 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2486 TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2488 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2489 postfix = dump_postfix[0];
2491 postfix = dump_postfix[1];
2493 if (strcmp(postfix, type)) {
2494 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2495 tbm_surface_unmap(surface);
2499 snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2501 if (!access(file, 0)) {
2502 TBM_ERR("can't capture buffer, exist file %s", file);
2503 tbm_surface_unmap(surface);
2507 switch (info.format) {
2508 case TBM_FORMAT_ARGB8888:
2509 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2512 info.planes[0].stride,
2513 TBM_FORMAT_ARGB8888);
2515 case TBM_FORMAT_XRGB8888:
2516 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2519 info.planes[0].stride,
2520 TBM_FORMAT_XRGB8888);
2522 case TBM_FORMAT_YVU420:
2523 case TBM_FORMAT_YUV420:
2524 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2525 info.planes[0].stride * info.height,
2527 info.planes[1].stride * (info.height >> 1),
2529 info.planes[2].stride * (info.height >> 1));
2531 case TBM_FORMAT_NV12:
2532 case TBM_FORMAT_NV21:
2533 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2534 info.planes[0].stride * info.height,
2536 info.planes[1].stride * (info.height >> 1),
2539 case TBM_FORMAT_YUYV:
2540 case TBM_FORMAT_UYVY:
2541 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2542 info.planes[0].stride * info.height,
2546 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2547 tbm_surface_unmap(surface);
2551 tbm_surface_unmap(surface);
2553 TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2559 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2560 const char *path, const char *name, const char *type)
2562 TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2563 TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2564 TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2565 TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2566 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2567 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2571 if (strcmp(dump_postfix[0], type)) {
2572 TBM_ERR("Not supported type:%s'", type);
2576 snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2578 if (!access(file, 0)) {
2579 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2583 _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2585 TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2591 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2593 struct _tbm_surface *surf;
2595 _tbm_surface_mutex_lock();
2596 _tbm_set_last_result(TBM_ERROR_NONE);
2598 TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2599 TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2600 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2602 surf = (struct _tbm_surface *)surface;
2606 surf->damage.width = width;
2607 surf->damage.height = height;
2609 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2610 surface, x, y, width, height);
2612 _tbm_surface_mutex_unlock();
2618 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2620 struct _tbm_surface *surf;
2622 _tbm_surface_mutex_lock();
2623 _tbm_set_last_result(TBM_ERROR_NONE);
2625 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2627 surf = (struct _tbm_surface *)surface;
2629 if (x) *x = surf->damage.x;
2630 if (y) *y = surf->damage.y;
2631 if (width) *width = surf->damage.width;
2632 if (height) *height = surf->damage.height;
2634 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2635 surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2637 _tbm_surface_mutex_unlock();
2643 tbm_surface_internal_add_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2645 struct _tbm_surface *surf;
2646 tbm_surface_destroy_func_info *func_info = NULL;
2648 _tbm_surface_mutex_lock();
2649 _tbm_set_last_result(TBM_ERROR_NONE);
2651 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2652 TBM_SURFACE_RETURN_VAL_IF_FAIL(func != NULL, 0);
2654 surf = (struct _tbm_surface *)surface;
2655 LIST_FOR_EACH_ENTRY(func_info, &surf->destroy_funcs, item_link) {
2656 if (func_info->destroy_func == func && func_info->user_data == user_data) {
2657 TBM_ERR("can't add twice");
2658 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
2659 _tbm_surface_mutex_unlock();
2664 func_info = calloc(1, sizeof(tbm_surface_destroy_func_info));
2665 if (func_info == NULL) {
2666 TBM_ERR("alloc failed");
2667 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2668 _tbm_surface_mutex_unlock();
2672 func_info->destroy_func = func;
2673 func_info->user_data = user_data;
2675 LIST_ADDTAIL(&func_info->item_link, &surf->destroy_funcs);
2677 _tbm_surface_mutex_unlock();
2683 tbm_surface_internal_remove_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2685 struct _tbm_surface *surf;
2686 tbm_surface_destroy_func_info *func_info = NULL, *next = NULL;
2688 _tbm_surface_mutex_lock();
2689 _tbm_set_last_result(TBM_ERROR_NONE);
2691 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
2692 TBM_SURFACE_RETURN_IF_FAIL(func != NULL);
2694 surf = (struct _tbm_surface *)surface;
2695 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &surf->destroy_funcs, item_link) {
2696 if (func_info->destroy_func != func || func_info->user_data != user_data)
2699 LIST_DEL(&func_info->item_link);
2702 _tbm_surface_mutex_unlock();
2707 _tbm_surface_mutex_unlock();