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 static tbm_bufmgr g_surface_bufmgr;
45 static pthread_mutex_t tbm_surface_lock;
46 void _tbm_surface_mutex_unlock(void);
48 #define C(b, m) (((b) >> (m)) & 0xFF)
49 #define B(c, s) ((((unsigned int)(c)) & 0xff) << (s))
50 #define FOURCC(a, b, c, d) (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
51 #define FOURCC_STR(id) C(id, 0), C(id, 8), C(id, 16), C(id, 24)
52 #define FOURCC_ID(str) FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3])
55 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
57 TBM_LOG_E("'%s' failed.\n", #cond);\
58 _tbm_surface_mutex_unlock();\
63 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
65 TBM_LOG_E("'%s' failed.\n", #cond);\
66 _tbm_surface_mutex_unlock();\
74 _tbm_surface_internal_get_time(void)
79 clock_gettime(CLOCK_MONOTONIC, &tp);
80 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
86 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
88 LIST_DEL(&debug_data->item_link);
90 if (debug_data->key) free(debug_data->key);
91 if (debug_data->value) free(debug_data->value);
96 _tbm_surface_internal_format_to_str(tbm_format format)
100 return "TBM_FORMAT_C8";
101 case TBM_FORMAT_RGB332:
102 return "TBM_FORMAT_RGB332";
103 case TBM_FORMAT_BGR233:
104 return "TBM_FORMAT_BGR233";
105 case TBM_FORMAT_XRGB4444:
106 return "TBM_FORMAT_XRGB4444";
107 case TBM_FORMAT_XBGR4444:
108 return "TBM_FORMAT_XBGR4444";
109 case TBM_FORMAT_RGBX4444:
110 return "TBM_FORMAT_RGBX4444";
111 case TBM_FORMAT_BGRX4444:
112 return "TBM_FORMAT_BGRX4444";
113 case TBM_FORMAT_ARGB4444:
114 return "TBM_FORMAT_ARGB4444";
115 case TBM_FORMAT_ABGR4444:
116 return "TBM_FORMAT_ABGR4444";
117 case TBM_FORMAT_RGBA4444:
118 return "TBM_FORMAT_RGBA4444";
119 case TBM_FORMAT_BGRA4444:
120 return "TBM_FORMAT_BGRA4444";
121 case TBM_FORMAT_XRGB1555:
122 return "TBM_FORMAT_XRGB1555";
123 case TBM_FORMAT_XBGR1555:
124 return "TBM_FORMAT_XBGR1555";
125 case TBM_FORMAT_RGBX5551:
126 return "TBM_FORMAT_RGBX5551";
127 case TBM_FORMAT_BGRX5551:
128 return "TBM_FORMAT_BGRX5551";
129 case TBM_FORMAT_ARGB1555:
130 return "TBM_FORMAT_ARGB1555";
131 case TBM_FORMAT_ABGR1555:
132 return "TBM_FORMAT_ABGR1555";
133 case TBM_FORMAT_RGBA5551:
134 return "TBM_FORMAT_RGBA5551";
135 case TBM_FORMAT_BGRA5551:
136 return "TBM_FORMAT_BGRA5551";
137 case TBM_FORMAT_RGB565:
138 return "TBM_FORMAT_RGB565";
139 case TBM_FORMAT_BGR565:
140 return "TBM_FORMAT_BGR565";
141 case TBM_FORMAT_RGB888:
142 return "TBM_FORMAT_RGB888";
143 case TBM_FORMAT_BGR888:
144 return "TBM_FORMAT_BGR888";
145 case TBM_FORMAT_XRGB8888:
146 return "TBM_FORMAT_XRGB8888";
147 case TBM_FORMAT_XBGR8888:
148 return "TBM_FORMAT_XBGR8888";
149 case TBM_FORMAT_RGBX8888:
150 return "TBM_FORMAT_RGBX8888";
151 case TBM_FORMAT_BGRX8888:
152 return "TBM_FORMAT_BGRX8888";
153 case TBM_FORMAT_ARGB8888:
154 return "TBM_FORMAT_ARGB8888";
155 case TBM_FORMAT_ABGR8888:
156 return "TBM_FORMAT_ABGR8888";
157 case TBM_FORMAT_RGBA8888:
158 return "TBM_FORMAT_RGBA8888";
159 case TBM_FORMAT_BGRA8888:
160 return "TBM_FORMAT_BGRA8888";
161 case TBM_FORMAT_XRGB2101010:
162 return "TBM_FORMAT_XRGB2101010";
163 case TBM_FORMAT_XBGR2101010:
164 return "TBM_FORMAT_XBGR2101010";
165 case TBM_FORMAT_RGBX1010102:
166 return "TBM_FORMAT_RGBX1010102";
167 case TBM_FORMAT_BGRX1010102:
168 return "TBM_FORMAT_BGRX1010102";
169 case TBM_FORMAT_ARGB2101010:
170 return "TBM_FORMAT_ARGB2101010";
171 case TBM_FORMAT_ABGR2101010:
172 return "TBM_FORMAT_ABGR2101010";
173 case TBM_FORMAT_RGBA1010102:
174 return "TBM_FORMAT_RGBA1010102";
175 case TBM_FORMAT_BGRA1010102:
176 return "TBM_FORMAT_BGRA1010102";
177 case TBM_FORMAT_YUYV:
178 return "TBM_FORMAT_YUYV";
179 case TBM_FORMAT_YVYU:
180 return "TBM_FORMAT_YVYU";
181 case TBM_FORMAT_UYVY:
182 return "TBM_FORMAT_UYVY";
183 case TBM_FORMAT_VYUY:
184 return "TBM_FORMAT_VYUY";
185 case TBM_FORMAT_AYUV:
186 return "TBM_FORMAT_AYUV";
187 case TBM_FORMAT_NV12:
188 return "TBM_FORMAT_NV12";
189 case TBM_FORMAT_NV21:
190 return "TBM_FORMAT_NV21";
191 case TBM_FORMAT_NV16:
192 return "TBM_FORMAT_NV16";
193 case TBM_FORMAT_NV61:
194 return "TBM_FORMAT_NV61";
195 case TBM_FORMAT_YUV410:
196 return "TBM_FORMAT_YUV410";
197 case TBM_FORMAT_YVU410:
198 return "TBM_FORMAT_YVU410";
199 case TBM_FORMAT_YUV411:
200 return "TBM_FORMAT_YUV411";
201 case TBM_FORMAT_YVU411:
202 return "TBM_FORMAT_YVU411";
203 case TBM_FORMAT_YUV420:
204 return "TBM_FORMAT_YUV420";
205 case TBM_FORMAT_YVU420:
206 return "TBM_FORMAT_YVU420";
207 case TBM_FORMAT_YUV422:
208 return "TBM_FORMAT_YUV422";
209 case TBM_FORMAT_YVU422:
210 return "TBM_FORMAT_YVU422";
211 case TBM_FORMAT_YUV444:
212 return "TBM_FORMAT_YUV444";
213 case TBM_FORMAT_YVU444:
214 return "TBM_FORMAT_YVU444";
215 case TBM_FORMAT_NV12MT:
216 return "TBM_FORMAT_NV12MT";
224 _tbm_surface_mutex_init(void)
226 static bool tbm_surface_mutex_init = false;
228 if (tbm_surface_mutex_init)
231 if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
232 TBM_LOG_E("fail: pthread_mutex_init for tbm_surface_lock.\n");
236 tbm_surface_mutex_init = true;
242 _tbm_surface_mutex_lock(void)
244 if (!_tbm_surface_mutex_init()) {
245 TBM_LOG_E("fail: _tbm_surface_mutex_init.\n");
249 pthread_mutex_lock(&tbm_surface_lock);
253 _tbm_surface_mutex_unlock(void)
255 pthread_mutex_unlock(&tbm_surface_lock);
259 _init_surface_bufmgr(void)
261 g_surface_bufmgr = tbm_bufmgr_init(-1);
265 _deinit_surface_bufmgr(void)
267 if (!g_surface_bufmgr)
270 tbm_bufmgr_deinit(g_surface_bufmgr);
271 g_surface_bufmgr = NULL;
275 _tbm_surface_internal_is_valid(tbm_surface_h surface)
277 tbm_surface_h old_data = NULL;
279 TBM_RETURN_VAL_IF_FAIL(g_surface_bufmgr, 0);
280 TBM_RETURN_VAL_IF_FAIL(surface, 0);
282 if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
283 LIST_FOR_EACH_ENTRY(old_data, &g_surface_bufmgr->surf_list, item_link) {
284 if (old_data == surface) {
285 TBM_TRACE("tbm_surface(%p)\n", surface);
291 TBM_LOG_E("error: No valid tbm_surface(%p)\n", surface);
297 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
298 int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
300 TBM_RETURN_VAL_IF_FAIL(surface, 0);
301 TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
303 struct _tbm_surface *surf = (struct _tbm_surface *)surface;
304 struct _tbm_bufmgr *mgr = surf->bufmgr;
307 TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
308 TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
309 TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
310 TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
312 if (!mgr->backend->surface_get_plane_data)
315 ret = mgr->backend->surface_get_plane_data(surf->info.width,
316 surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
318 TBM_LOG_E("Fail to surface_get_plane_data. surface(%p)\n", surface);
326 _tbm_surface_internal_destroy(tbm_surface_h surface)
329 tbm_bufmgr bufmgr = surface->bufmgr;
330 tbm_user_data *old_data = NULL, *tmp = NULL;
331 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
333 /* destory the user_data_list */
334 if (!LIST_IS_EMPTY(&surface->user_data_list)) {
335 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
336 TBM_DBG("free user_data\n");
337 user_data_delete(old_data);
341 for (i = 0; i < surface->num_bos; i++) {
342 surface->bos[i]->surface = NULL;
344 tbm_bo_unref(surface->bos[i]);
345 surface->bos[i] = NULL;
348 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
349 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
350 _tbm_surface_internal_debug_data_delete(debug_old_data);
353 LIST_DEL(&surface->item_link);
358 if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
359 LIST_DELINIT(&bufmgr->surf_list);
361 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
362 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
363 _tbm_surface_internal_debug_data_delete(debug_old_data);
367 _deinit_surface_bufmgr();
372 tbm_surface_internal_is_valid(tbm_surface_h surface)
376 _tbm_surface_mutex_lock();
378 /* Return silently if surface is null. */
380 _tbm_surface_mutex_unlock();
384 ret = _tbm_surface_internal_is_valid(surface);
386 _tbm_surface_mutex_unlock();
392 tbm_surface_internal_query_supported_formats(uint32_t **formats,
395 struct _tbm_bufmgr *mgr;
397 bool bufmgr_initialized = false;
399 _tbm_surface_mutex_lock();
401 if (!g_surface_bufmgr) {
402 _init_surface_bufmgr();
403 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
404 bufmgr_initialized = true;
407 mgr = g_surface_bufmgr;
409 if (!mgr->backend->surface_supported_format)
412 ret = mgr->backend->surface_supported_format(formats, num);
414 TBM_LOG_E("Fail to surface_supported_format.\n");
418 TBM_TRACE("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
420 _tbm_surface_mutex_unlock();
425 if (bufmgr_initialized) {
426 LIST_DELINIT(&g_surface_bufmgr->surf_list);
427 _deinit_surface_bufmgr();
429 _tbm_surface_mutex_unlock();
431 TBM_LOG_E("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
437 tbm_surface_internal_get_num_planes(tbm_format format)
443 case TBM_FORMAT_RGB332:
444 case TBM_FORMAT_BGR233:
445 case TBM_FORMAT_XRGB4444:
446 case TBM_FORMAT_XBGR4444:
447 case TBM_FORMAT_RGBX4444:
448 case TBM_FORMAT_BGRX4444:
449 case TBM_FORMAT_ARGB4444:
450 case TBM_FORMAT_ABGR4444:
451 case TBM_FORMAT_RGBA4444:
452 case TBM_FORMAT_BGRA4444:
453 case TBM_FORMAT_XRGB1555:
454 case TBM_FORMAT_XBGR1555:
455 case TBM_FORMAT_RGBX5551:
456 case TBM_FORMAT_BGRX5551:
457 case TBM_FORMAT_ARGB1555:
458 case TBM_FORMAT_ABGR1555:
459 case TBM_FORMAT_RGBA5551:
460 case TBM_FORMAT_BGRA5551:
461 case TBM_FORMAT_RGB565:
462 case TBM_FORMAT_BGR565:
463 case TBM_FORMAT_RGB888:
464 case TBM_FORMAT_BGR888:
465 case TBM_FORMAT_XRGB8888:
466 case TBM_FORMAT_XBGR8888:
467 case TBM_FORMAT_RGBX8888:
468 case TBM_FORMAT_BGRX8888:
469 case TBM_FORMAT_ARGB8888:
470 case TBM_FORMAT_ABGR8888:
471 case TBM_FORMAT_RGBA8888:
472 case TBM_FORMAT_BGRA8888:
473 case TBM_FORMAT_XRGB2101010:
474 case TBM_FORMAT_XBGR2101010:
475 case TBM_FORMAT_RGBX1010102:
476 case TBM_FORMAT_BGRX1010102:
477 case TBM_FORMAT_ARGB2101010:
478 case TBM_FORMAT_ABGR2101010:
479 case TBM_FORMAT_RGBA1010102:
480 case TBM_FORMAT_BGRA1010102:
481 case TBM_FORMAT_YUYV:
482 case TBM_FORMAT_YVYU:
483 case TBM_FORMAT_UYVY:
484 case TBM_FORMAT_VYUY:
485 case TBM_FORMAT_AYUV:
488 case TBM_FORMAT_NV12:
489 case TBM_FORMAT_NV12MT:
490 case TBM_FORMAT_NV21:
491 case TBM_FORMAT_NV16:
492 case TBM_FORMAT_NV61:
495 case TBM_FORMAT_YUV410:
496 case TBM_FORMAT_YVU410:
497 case TBM_FORMAT_YUV411:
498 case TBM_FORMAT_YVU411:
499 case TBM_FORMAT_YUV420:
500 case TBM_FORMAT_YVU420:
501 case TBM_FORMAT_YUV422:
502 case TBM_FORMAT_YVU422:
503 case TBM_FORMAT_YUV444:
504 case TBM_FORMAT_YVU444:
512 TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
518 tbm_surface_internal_get_bpp(tbm_format format)
525 case TBM_FORMAT_RGB332:
526 case TBM_FORMAT_BGR233:
529 case TBM_FORMAT_XRGB4444:
530 case TBM_FORMAT_XBGR4444:
531 case TBM_FORMAT_RGBX4444:
532 case TBM_FORMAT_BGRX4444:
533 case TBM_FORMAT_ARGB4444:
534 case TBM_FORMAT_ABGR4444:
535 case TBM_FORMAT_RGBA4444:
536 case TBM_FORMAT_BGRA4444:
537 case TBM_FORMAT_XRGB1555:
538 case TBM_FORMAT_XBGR1555:
539 case TBM_FORMAT_RGBX5551:
540 case TBM_FORMAT_BGRX5551:
541 case TBM_FORMAT_ARGB1555:
542 case TBM_FORMAT_ABGR1555:
543 case TBM_FORMAT_RGBA5551:
544 case TBM_FORMAT_BGRA5551:
545 case TBM_FORMAT_RGB565:
546 case TBM_FORMAT_BGR565:
549 case TBM_FORMAT_RGB888:
550 case TBM_FORMAT_BGR888:
553 case TBM_FORMAT_XRGB8888:
554 case TBM_FORMAT_XBGR8888:
555 case TBM_FORMAT_RGBX8888:
556 case TBM_FORMAT_BGRX8888:
557 case TBM_FORMAT_ARGB8888:
558 case TBM_FORMAT_ABGR8888:
559 case TBM_FORMAT_RGBA8888:
560 case TBM_FORMAT_BGRA8888:
561 case TBM_FORMAT_XRGB2101010:
562 case TBM_FORMAT_XBGR2101010:
563 case TBM_FORMAT_RGBX1010102:
564 case TBM_FORMAT_BGRX1010102:
565 case TBM_FORMAT_ARGB2101010:
566 case TBM_FORMAT_ABGR2101010:
567 case TBM_FORMAT_RGBA1010102:
568 case TBM_FORMAT_BGRA1010102:
569 case TBM_FORMAT_YUYV:
570 case TBM_FORMAT_YVYU:
571 case TBM_FORMAT_UYVY:
572 case TBM_FORMAT_VYUY:
573 case TBM_FORMAT_AYUV:
576 case TBM_FORMAT_NV12:
577 case TBM_FORMAT_NV12MT:
578 case TBM_FORMAT_NV21:
581 case TBM_FORMAT_NV16:
582 case TBM_FORMAT_NV61:
585 case TBM_FORMAT_YUV410:
586 case TBM_FORMAT_YVU410:
589 case TBM_FORMAT_YUV411:
590 case TBM_FORMAT_YVU411:
591 case TBM_FORMAT_YUV420:
592 case TBM_FORMAT_YVU420:
595 case TBM_FORMAT_YUV422:
596 case TBM_FORMAT_YVU422:
599 case TBM_FORMAT_YUV444:
600 case TBM_FORMAT_YVU444:
607 TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
613 tbm_surface_internal_create_with_flags(int width, int height,
614 int format, int flags)
616 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
617 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
619 struct _tbm_bufmgr *mgr;
620 struct _tbm_surface *surf = NULL;
624 uint32_t bo_size = 0;
627 bool bufmgr_initialized = false;
629 _tbm_surface_mutex_lock();
631 if (!g_surface_bufmgr) {
632 _init_surface_bufmgr();
633 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
634 bufmgr_initialized = true;
637 mgr = g_surface_bufmgr;
638 if (!TBM_BUFMGR_IS_VALID(mgr)) {
639 TBM_LOG_E("The bufmgr is invalid\n");
640 goto check_valid_fail;
643 surf = calloc(1, sizeof(struct _tbm_surface));
645 TBM_LOG_E("fail to alloc surf\n");
646 goto alloc_surf_fail;
650 surf->info.width = width;
651 surf->info.height = height;
652 surf->info.format = format;
653 surf->info.bpp = tbm_surface_internal_get_bpp(format);
654 surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
657 /* get size, stride and offset bo_idx */
658 for (i = 0; i < surf->info.num_planes; i++) {
659 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
660 &offset, &stride, &bo_idx)) {
661 TBM_LOG_E("fail to query plane data\n");
662 goto query_plane_data_fail;
665 surf->info.planes[i].size = size;
666 surf->info.planes[i].offset = offset;
667 surf->info.planes[i].stride = stride;
668 surf->planes_bo_idx[i] = bo_idx;
673 for (i = 0; i < surf->info.num_planes; i++) {
674 surf->info.size += surf->info.planes[i].size;
676 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
677 surf->num_bos = surf->planes_bo_idx[i] + 1;
682 for (i = 0; i < surf->num_bos; i++) {
684 for (j = 0; j < surf->info.num_planes; j++) {
685 if (surf->planes_bo_idx[j] == i)
686 bo_size += surf->info.planes[j].size;
689 if (mgr->backend->surface_bo_alloc) {
690 /* LCOV_EXCL_START */
692 void *bo_priv = NULL;
694 bo = calloc(1, sizeof(struct _tbm_bo));
696 TBM_LOG_E("fail to alloc bo struct\n");
700 bo->bufmgr = surf->bufmgr;
702 pthread_mutex_lock(&surf->bufmgr->lock);
704 bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
706 TBM_LOG_E("fail to alloc bo priv\n");
708 pthread_mutex_unlock(&surf->bufmgr->lock);
716 LIST_INITHEAD(&bo->user_data_list);
718 LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
720 pthread_mutex_unlock(&surf->bufmgr->lock);
725 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
727 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
732 _tbm_bo_set_surface(surf->bos[i], surf);
735 TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
736 _tbm_surface_internal_format_to_str(format), flags, surf);
738 LIST_INITHEAD(&surf->user_data_list);
739 LIST_INITHEAD(&surf->debug_data_list);
741 LIST_ADD(&surf->item_link, &mgr->surf_list);
743 _tbm_surface_mutex_unlock();
748 for (j = 0; j < i; j++) {
750 tbm_bo_unref(surf->bos[j]);
752 query_plane_data_fail:
756 if (bufmgr_initialized && mgr) {
757 LIST_DELINIT(&mgr->surf_list);
758 _deinit_surface_bufmgr();
760 _tbm_surface_mutex_unlock();
762 TBM_LOG_E("error: width(%d) height(%d) format(%s) flags(%d)\n",
764 _tbm_surface_internal_format_to_str(format), flags);
770 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
771 tbm_bo *bos, int num)
773 TBM_RETURN_VAL_IF_FAIL(bos, NULL);
774 TBM_RETURN_VAL_IF_FAIL(info, NULL);
775 TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
777 struct _tbm_bufmgr *mgr;
778 struct _tbm_surface *surf = NULL;
780 bool bufmgr_initialized = false;
782 _tbm_surface_mutex_lock();
784 if (!g_surface_bufmgr) {
785 _init_surface_bufmgr();
786 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
787 bufmgr_initialized = true;
790 mgr = g_surface_bufmgr;
791 if (!TBM_BUFMGR_IS_VALID(mgr)) {
792 TBM_LOG_E("fail to validate the Bufmgr.\n");
793 goto check_valid_fail;
796 surf = calloc(1, sizeof(struct _tbm_surface));
798 TBM_LOG_E("fail to allocate struct _tbm_surface.\n");
799 goto alloc_surf_fail;
803 surf->info.width = info->width;
804 surf->info.height = info->height;
805 surf->info.format = info->format;
807 surf->info.bpp = info->bpp;
809 surf->info.bpp = tbm_surface_internal_get_bpp(info->format);
810 surf->info.num_planes = info->num_planes;
813 /* get size, stride and offset */
814 for (i = 0; i < info->num_planes; i++) {
815 surf->info.planes[i].offset = info->planes[i].offset;
816 surf->info.planes[i].stride = info->planes[i].stride;
818 if (info->planes[i].size > 0)
819 surf->info.planes[i].size = info->planes[i].size;
821 uint32_t size = 0, offset = 0, stride = 0;
824 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx);
825 surf->info.planes[i].size = size;
829 surf->planes_bo_idx[i] = 0;
831 surf->planes_bo_idx[i] = i;
834 if (info->size > 0) {
835 surf->info.size = info->size;
838 for (i = 0; i < info->num_planes; i++)
839 surf->info.size += surf->info.planes[i].size;
842 surf->flags = TBM_BO_DEFAULT;
844 /* create only one bo */
846 for (i = 0; i < num; i++) {
847 if (bos[i] == NULL) {
848 TBM_LOG_E("bos[%d] is null.\n", i);
852 surf->bos[i] = tbm_bo_ref(bos[i]);
853 _tbm_bo_set_surface(bos[i], surf);
856 TBM_TRACE("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
857 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
859 LIST_INITHEAD(&surf->user_data_list);
860 LIST_INITHEAD(&surf->debug_data_list);
862 LIST_ADD(&surf->item_link, &mgr->surf_list);
864 _tbm_surface_mutex_unlock();
869 for (i = 0; i < num; i++) {
871 tbm_bo_unref(surf->bos[i]);
876 if (bufmgr_initialized && mgr) {
877 LIST_DELINIT(&mgr->surf_list);
878 _deinit_surface_bufmgr();
880 _tbm_surface_mutex_unlock();
882 TBM_LOG_E("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
883 info->width, info->height,
884 _tbm_surface_internal_format_to_str(info->format), num);
890 tbm_surface_internal_destroy(tbm_surface_h surface)
892 _tbm_surface_mutex_lock();
894 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
898 if (surface->refcnt > 0) {
899 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
900 _tbm_surface_mutex_unlock();
904 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
906 if (surface->refcnt == 0)
907 _tbm_surface_internal_destroy(surface);
909 _tbm_surface_mutex_unlock();
913 tbm_surface_internal_ref(tbm_surface_h surface)
915 _tbm_surface_mutex_lock();
917 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
921 TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
923 _tbm_surface_mutex_unlock();
927 tbm_surface_internal_unref(tbm_surface_h surface)
929 _tbm_surface_mutex_lock();
931 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
935 if (surface->refcnt > 0) {
936 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
937 _tbm_surface_mutex_unlock();
941 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
943 if (surface->refcnt == 0)
944 _tbm_surface_internal_destroy(surface);
946 _tbm_surface_mutex_unlock();
950 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
952 struct _tbm_surface *surf;
955 _tbm_surface_mutex_lock();
957 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
959 surf = (struct _tbm_surface *)surface;
962 TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
964 _tbm_surface_mutex_unlock();
970 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
972 struct _tbm_surface *surf;
975 _tbm_surface_mutex_lock();
977 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
978 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
980 surf = (struct _tbm_surface *)surface;
981 bo = surf->bos[bo_idx];
983 TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
985 _tbm_surface_mutex_unlock();
991 tbm_surface_internal_get_size(tbm_surface_h surface)
993 struct _tbm_surface *surf;
996 _tbm_surface_mutex_lock();
998 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1000 surf = (struct _tbm_surface *)surface;
1001 size = surf->info.size;
1003 TBM_TRACE("tbm_surface(%p) size(%u)\n", surface, size);
1005 _tbm_surface_mutex_unlock();
1011 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1012 uint32_t *size, uint32_t *offset, uint32_t *pitch)
1014 struct _tbm_surface *surf;
1016 _tbm_surface_mutex_lock();
1018 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1019 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1021 surf = (struct _tbm_surface *)surface;
1023 if (plane_idx >= surf->info.num_planes) {
1024 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1025 _tbm_surface_mutex_unlock();
1030 *size = surf->info.planes[plane_idx].size;
1033 *offset = surf->info.planes[plane_idx].offset;
1036 *pitch = surf->info.planes[plane_idx].stride;
1038 TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1039 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1040 surf->info.planes[plane_idx].stride);
1042 _tbm_surface_mutex_unlock();
1048 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1049 tbm_surface_info_s *info, int map)
1051 struct _tbm_surface *surf;
1052 tbm_bo_handle bo_handles[4];
1055 _tbm_surface_mutex_lock();
1057 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1059 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1061 surf = (struct _tbm_surface *)surface;
1063 memset(info, 0x00, sizeof(tbm_surface_info_s));
1064 info->width = surf->info.width;
1065 info->height = surf->info.height;
1066 info->format = surf->info.format;
1067 info->bpp = surf->info.bpp;
1068 info->size = surf->info.size;
1069 info->num_planes = surf->info.num_planes;
1072 for (i = 0; i < surf->num_bos; i++) {
1073 _tbm_surface_mutex_unlock();
1074 bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1075 _tbm_surface_mutex_lock();
1076 if (bo_handles[i].ptr == NULL) {
1077 for (j = 0; j < i; j++)
1078 tbm_bo_unmap(surf->bos[j]);
1080 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1081 _tbm_surface_mutex_unlock();
1086 for (i = 0; i < surf->num_bos; i++) {
1087 bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1088 if (bo_handles[i].ptr == NULL) {
1089 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1090 _tbm_surface_mutex_unlock();
1096 for (i = 0; i < surf->info.num_planes; i++) {
1097 info->planes[i].size = surf->info.planes[i].size;
1098 info->planes[i].offset = surf->info.planes[i].offset;
1099 info->planes[i].stride = surf->info.planes[i].stride;
1101 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1102 info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1103 surf->info.planes[i].offset;
1106 TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1108 _tbm_surface_mutex_unlock();
1114 tbm_surface_internal_unmap(tbm_surface_h surface)
1116 struct _tbm_surface *surf;
1119 _tbm_surface_mutex_lock();
1121 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1123 surf = (struct _tbm_surface *)surface;
1125 for (i = 0; i < surf->num_bos; i++)
1126 tbm_bo_unmap(surf->bos[i]);
1128 TBM_TRACE("tbm_surface(%p)\n", surface);
1130 _tbm_surface_mutex_unlock();
1134 tbm_surface_internal_get_width(tbm_surface_h surface)
1136 struct _tbm_surface *surf;
1139 _tbm_surface_mutex_lock();
1141 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1143 surf = (struct _tbm_surface *)surface;
1144 width = surf->info.width;
1146 TBM_TRACE("tbm_surface(%p) width(%u)\n", surface, width);
1148 _tbm_surface_mutex_unlock();
1154 tbm_surface_internal_get_height(tbm_surface_h surface)
1156 struct _tbm_surface *surf;
1157 unsigned int height;
1159 _tbm_surface_mutex_lock();
1161 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1163 surf = (struct _tbm_surface *)surface;
1164 height = surf->info.height;
1166 TBM_TRACE("tbm_surface(%p) height(%u)\n", surface, height);
1168 _tbm_surface_mutex_unlock();
1175 tbm_surface_internal_get_format(tbm_surface_h surface)
1177 struct _tbm_surface *surf;
1180 _tbm_surface_mutex_lock();
1182 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1184 surf = (struct _tbm_surface *)surface;
1185 format = surf->info.format;
1187 TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1189 _tbm_surface_mutex_unlock();
1195 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1197 struct _tbm_surface *surf;
1200 _tbm_surface_mutex_lock();
1202 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1203 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1205 surf = (struct _tbm_surface *)surface;
1206 bo_idx = surf->planes_bo_idx[plane_idx];
1208 TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1210 _tbm_surface_mutex_unlock();
1216 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1217 tbm_data_free data_free_func)
1219 tbm_user_data *data;
1221 _tbm_surface_mutex_lock();
1223 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1225 /* check if the data according to the key exist if so, return false. */
1226 data = user_data_lookup(&surface->user_data_list, key);
1228 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1229 _tbm_surface_mutex_unlock();
1233 data = user_data_create(key, data_free_func);
1235 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1236 _tbm_surface_mutex_unlock();
1240 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1242 LIST_ADD(&data->item_link, &surface->user_data_list);
1244 _tbm_surface_mutex_unlock();
1250 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1253 tbm_user_data *old_data;
1255 _tbm_surface_mutex_lock();
1257 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1259 old_data = user_data_lookup(&surface->user_data_list, key);
1261 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1262 _tbm_surface_mutex_unlock();
1266 if (old_data->data && old_data->free_func)
1267 old_data->free_func(old_data->data);
1269 old_data->data = data;
1271 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1273 _tbm_surface_mutex_unlock();
1279 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1282 tbm_user_data *old_data;
1284 _tbm_surface_mutex_lock();
1286 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1289 TBM_LOG_E("error: tbm_surface(%p) key(%lu)\n", surface, key);
1290 _tbm_surface_mutex_unlock();
1295 old_data = user_data_lookup(&surface->user_data_list, key);
1297 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1298 _tbm_surface_mutex_unlock();
1302 *data = old_data->data;
1304 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1306 _tbm_surface_mutex_unlock();
1312 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1315 tbm_user_data *old_data = (void *)0;
1317 _tbm_surface_mutex_lock();
1319 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1321 old_data = user_data_lookup(&surface->user_data_list, key);
1323 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1324 _tbm_surface_mutex_unlock();
1328 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1330 user_data_delete(old_data);
1332 _tbm_surface_mutex_unlock();
1337 /* LCOV_EXCL_START */
1339 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1341 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1343 return surface->debug_pid;
1347 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1349 _tbm_surface_mutex_lock();
1351 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1353 surface->debug_pid = pid;
1355 _tbm_surface_mutex_unlock();
1358 static tbm_surface_debug_data *
1359 _tbm_surface_internal_debug_data_create(char *key, char *value)
1361 tbm_surface_debug_data *debug_data = NULL;
1363 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1367 if (key) debug_data->key = strdup(key);
1368 if (value) debug_data->value = strdup(value);
1374 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1376 tbm_surface_debug_data *debug_data = NULL;
1377 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1378 tbm_bufmgr bufmgr = NULL;
1380 _tbm_surface_mutex_lock();
1382 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1383 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1385 bufmgr = surface->bufmgr;
1387 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1389 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1390 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1392 if (!strcmp(old_data->key, key)) {
1393 if (old_data->value && value && !strncmp(old_data->value, value, strlen(old_data->value))) {
1394 TBM_TRACE("tbm_surface(%p) Already exist key(%s) and value(%s)!\n", surface, key, value);
1395 goto add_debug_key_list;
1398 if (old_data->value)
1399 free(old_data->value);
1402 old_data->value = strdup(value);
1404 old_data->value = NULL;
1406 goto add_debug_key_list;
1412 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1414 TBM_LOG_E("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1415 _tbm_surface_mutex_unlock();
1419 TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1421 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1424 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1425 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1426 if (!strcmp(old_data->key, key)) {
1427 _tbm_surface_mutex_unlock();
1433 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1434 LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1436 _tbm_surface_mutex_unlock();
1442 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1444 tbm_surface_debug_data *old_data = NULL;
1446 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1448 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1449 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1450 if (!strcmp(old_data->key, key))
1451 return old_data->value;
1458 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1459 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1461 struct _tbm_surface_dump_buf_info {
1471 tbm_surface_info_s info;
1473 struct list_head link;
1476 struct _tbm_surface_dump_info {
1477 char *path; // copy???
1480 struct list_head *link;
1481 struct list_head surface_list; /* link of surface */
1484 static tbm_surface_dump_info *g_dump_info = NULL;
1485 static const char *dump_postfix[2] = {"png", "yuv"};
1486 static double scale_factor;
1489 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1490 void *data2, int size2, void *data3, int size3)
1492 FILE *fp = fopen(file, "w+");
1493 TBM_RETURN_IF_FAIL(fp != NULL);
1494 unsigned int *blocks;
1496 blocks = (unsigned int *)data1;
1497 fwrite(blocks, 1, size1, fp);
1500 blocks = (unsigned int *)data2;
1501 fwrite(blocks, 1, size2, fp);
1505 blocks = (unsigned int *)data3;
1506 fwrite(blocks, 1, size3, fp);
1513 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height)
1515 unsigned int *blocks = (unsigned int *)data;
1516 FILE *fp = fopen(file, "wb");
1517 TBM_RETURN_IF_FAIL(fp != NULL);
1518 const int pixel_size = 4; // RGBA
1519 png_bytep *row_pointers;
1522 png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1525 TBM_LOG_E("fail to create a png write structure.\n");
1530 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1532 TBM_LOG_E("fail to create a png info structure.\n");
1533 png_destroy_write_struct(&pPngStruct, NULL);
1538 png_init_io(pPngStruct, fp);
1539 png_set_IHDR(pPngStruct,
1544 PNG_COLOR_TYPE_RGBA,
1546 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1548 png_set_bgr(pPngStruct);
1549 png_write_info(pPngStruct, pPngInfo);
1551 row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1552 if (!row_pointers) {
1553 TBM_LOG_E("fail to allocate the png row_pointers.\n");
1554 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1559 for (y = 0; y < height; ++y) {
1563 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1565 TBM_LOG_E("fail to allocate the png row.\n");
1566 for (x = 0; x < y; x++)
1567 png_free(pPngStruct, row_pointers[x]);
1568 png_free(pPngStruct, row_pointers);
1569 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1573 row_pointers[y] = (png_bytep)row;
1575 for (x = 0; x < width; ++x) {
1576 unsigned int curBlock = blocks[y * width + x];
1578 row[x * pixel_size] = (curBlock & 0xFF);
1579 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1580 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1581 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1585 png_write_image(pPngStruct, row_pointers);
1586 png_write_end(pPngStruct, pPngInfo);
1588 for (y = 0; y < height; y++)
1589 png_free(pPngStruct, row_pointers[y]);
1590 png_free(pPngStruct, row_pointers);
1592 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1598 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1600 TBM_RETURN_IF_FAIL(path != NULL);
1601 TBM_RETURN_IF_FAIL(w > 0);
1602 TBM_RETURN_IF_FAIL(h > 0);
1603 TBM_RETURN_IF_FAIL(count > 0);
1605 tbm_surface_dump_buf_info *buf_info = NULL;
1606 tbm_surface_h tbm_surface;
1607 tbm_surface_info_s info;
1612 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1616 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1617 TBM_RETURN_IF_FAIL(g_dump_info);
1619 LIST_INITHEAD(&g_dump_info->surface_list);
1620 g_dump_info->count = 0;
1621 g_dump_info->dump_max = count;
1623 /* get buffer size */
1624 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1625 if (tbm_surface == NULL) {
1626 TBM_LOG_E("tbm_surface_create fail\n");
1632 if (TBM_SURFACE_ERROR_NONE != tbm_surface_map(tbm_surface,
1633 TBM_SURF_OPTION_READ, &info)) {
1634 TBM_LOG_E("tbm_surface_map fail\n");
1635 tbm_surface_destroy(tbm_surface);
1640 buffer_size = info.planes[0].stride * h;
1642 tbm_surface_unmap(tbm_surface);
1643 tbm_surface_destroy(tbm_surface);
1645 /* create dump lists */
1646 for (i = 0; i < count; i++) {
1649 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1650 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1652 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1654 TBM_LOG_E("fail to allocate the tbm_bo[%d]\n", i);
1659 buf_info->index = i;
1661 buf_info->size = buffer_size;
1663 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1666 g_dump_info->path = path;
1667 g_dump_info->link = &g_dump_info->surface_list;
1671 TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1676 /* free resources */
1677 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1678 tbm_surface_dump_buf_info *tmp;
1680 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1681 tbm_bo_unref(buf_info->bo);
1682 LIST_DEL(&buf_info->link);
1687 TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1696 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
1698 TBM_RETURN_IF_FAIL(scale > 0.0);
1700 tbm_surface_internal_dump_start(path, (int)(scale * w), (int)(scale * h), count);
1702 scale_factor = scale;
1706 tbm_surface_internal_dump_end(void)
1708 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1709 tbm_bo_handle bo_handle;
1714 if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1721 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1724 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1725 if (bo_handle.ptr == NULL) {
1726 tbm_bo_unref(buf_info->bo);
1727 LIST_DEL(&buf_info->link);
1732 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1733 TBM_LOG_I("Dump File.. %s generated.\n", file);
1735 if (buf_info->dirty) {
1736 void *ptr1 = NULL, *ptr2 = NULL;
1738 switch (buf_info->info.format) {
1739 case TBM_FORMAT_ARGB8888:
1740 case TBM_FORMAT_XRGB8888:
1741 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1742 buf_info->info.planes[0].stride >> 2,
1743 buf_info->info.height);
1745 case TBM_FORMAT_YVU420:
1746 case TBM_FORMAT_YUV420:
1747 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1748 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1749 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1750 buf_info->info.planes[0].stride * buf_info->info.height,
1752 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1754 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1756 case TBM_FORMAT_NV12:
1757 case TBM_FORMAT_NV21:
1758 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1759 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1760 buf_info->info.planes[0].stride * buf_info->info.height,
1762 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1765 case TBM_FORMAT_YUYV:
1766 case TBM_FORMAT_UYVY:
1767 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1768 buf_info->info.planes[0].stride * buf_info->info.height,
1772 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1775 } else if (buf_info->dirty_shm)
1776 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1777 buf_info->shm_stride >> 2,
1780 tbm_bo_unmap(buf_info->bo);
1781 tbm_bo_unref(buf_info->bo);
1782 LIST_DEL(&buf_info->link);
1789 TBM_LOG_I("Dump End..\n");
1792 static pixman_format_code_t
1793 _tbm_surface_internal_pixman_format_get(tbm_format format)
1796 case TBM_FORMAT_ARGB8888:
1797 return PIXMAN_a8r8g8b8;
1798 case TBM_FORMAT_XRGB8888:
1799 return PIXMAN_x8r8g8b8;
1808 * This function supports only if a buffer has below formats.
1809 * - TBM_FORMAT_ARGB8888
1810 * - TBM_FORMAT_XRGB8888
1812 static tbm_surface_error_e
1813 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
1814 int format, int src_stride, int src_w, int src_h,
1815 int dst_stride, int dst_w, int dst_h)
1817 pixman_image_t *src_img = NULL, *dst_img = NULL;
1818 pixman_format_code_t pixman_format;
1819 pixman_transform_t t;
1820 struct pixman_f_transform ft;
1821 double scale_x, scale_y;
1823 TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
1824 TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
1826 pixman_format = _tbm_surface_internal_pixman_format_get(format);
1827 TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
1830 src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
1831 (uint32_t*)src_ptr, src_stride);
1832 TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
1835 dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
1836 (uint32_t*)dst_ptr, dst_stride);
1837 TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
1839 pixman_f_transform_init_identity(&ft);
1841 scale_x = (double)src_w / dst_w;
1842 scale_y = (double)src_h / dst_h;
1844 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
1845 pixman_f_transform_translate(&ft, NULL, 0, 0);
1846 pixman_transform_from_pixman_f_transform(&t, &ft);
1847 pixman_image_set_transform(src_img, &t);
1849 pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
1850 0, 0, 0, 0, 0, 0, dst_w, dst_h);
1852 pixman_image_unref(src_img);
1853 pixman_image_unref(dst_img);
1855 return TBM_SURFACE_ERROR_NONE;
1859 pixman_image_unref(src_img);
1861 return TBM_SURFACE_ERROR_INVALID_OPERATION;
1865 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1867 TBM_RETURN_IF_FAIL(surface != NULL);
1868 TBM_RETURN_IF_FAIL(type != NULL);
1870 tbm_surface_dump_buf_info *buf_info;
1871 struct list_head *next_link;
1872 tbm_surface_info_s info;
1873 tbm_bo_handle bo_handle;
1874 const char *postfix;
1880 next_link = g_dump_info->link->next;
1881 TBM_RETURN_IF_FAIL(next_link != NULL);
1883 if (next_link == &g_dump_info->surface_list) {
1884 next_link = next_link->next;
1885 TBM_RETURN_IF_FAIL(next_link != NULL);
1888 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1889 TBM_RETURN_IF_FAIL(buf_info != NULL);
1891 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1892 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1894 if (scale_factor > 0.0) {
1897 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
1898 TBM_LOG_W("Dump with scale skip. unsupported format(%s)\n",
1899 _tbm_surface_internal_format_to_str(info.format));
1900 tbm_surface_unmap(surface);
1904 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
1906 buf_info->info.width = info.width * scale_factor;
1907 buf_info->info.height = info.height * scale_factor;
1908 buf_info->info.format = info.format;
1909 buf_info->info.bpp = tbm_surface_internal_get_bpp(buf_info->info.format);
1910 buf_info->info.num_planes = 1;
1911 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
1912 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
1914 if (buf_info->info.size > buf_info->size) {
1915 TBM_LOG_W("Dump with scale skip. surface over created buffer size(%u, %d)\n",
1916 buf_info->info.size, buf_info->size);
1917 tbm_surface_unmap(surface);
1921 if (info.size > buf_info->size) {
1922 TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1923 info.size, buf_info->size);
1924 tbm_surface_unmap(surface);
1928 /* make the file information */
1929 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1932 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1933 postfix = dump_postfix[0];
1935 postfix = dump_postfix[1];
1938 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1939 if (!bo_handle.ptr) {
1940 TBM_LOG_E("fail to map bo");
1941 tbm_surface_unmap(surface);
1944 memset(bo_handle.ptr, 0x00, buf_info->size);
1946 switch (info.format) {
1947 case TBM_FORMAT_ARGB8888:
1948 case TBM_FORMAT_XRGB8888:
1949 snprintf(buf_info->name, sizeof(buf_info->name),
1950 "%10.3f_%03d_%p-%s.%s",
1951 _tbm_surface_internal_get_time(),
1952 g_dump_info->count++, surface, type, postfix);
1954 if (scale_factor > 0.0) {
1955 ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
1957 buf_info->info.format,
1958 info.planes[0].stride,
1959 info.width, info.height,
1960 buf_info->info.planes[0].stride,
1961 buf_info->info.width,
1962 buf_info->info.height);
1963 if (ret != TBM_SURFACE_ERROR_NONE) {
1964 TBM_LOG_E("fail to scale buffer");
1965 tbm_bo_unmap(buf_info->bo);
1966 tbm_surface_unmap(surface);
1970 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1972 case TBM_FORMAT_YVU420:
1973 case TBM_FORMAT_YUV420:
1974 snprintf(buf_info->name, sizeof(buf_info->name),
1975 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1976 _tbm_surface_internal_get_time(),
1977 g_dump_info->count++, type, info.planes[0].stride,
1978 info.height, FOURCC_STR(info.format), postfix);
1979 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1980 bo_handle.ptr += info.planes[0].stride * info.height;
1981 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1982 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1983 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1985 case TBM_FORMAT_NV12:
1986 case TBM_FORMAT_NV21:
1987 snprintf(buf_info->name, sizeof(buf_info->name),
1988 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1989 _tbm_surface_internal_get_time(),
1990 g_dump_info->count++, type, info.planes[0].stride,
1991 info.height, FOURCC_STR(info.format), postfix);
1992 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1993 bo_handle.ptr += info.planes[0].stride * info.height;
1994 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1996 case TBM_FORMAT_YUYV:
1997 case TBM_FORMAT_UYVY:
1998 snprintf(buf_info->name, sizeof(buf_info->name),
1999 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
2000 _tbm_surface_internal_get_time(),
2001 g_dump_info->count++, type, info.planes[0].stride,
2002 info.height, FOURCC_STR(info.format), postfix);
2003 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2006 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2007 tbm_bo_unmap(buf_info->bo);
2008 tbm_surface_unmap(surface);
2012 tbm_bo_unmap(buf_info->bo);
2014 tbm_surface_unmap(surface);
2016 buf_info->dirty = 1;
2017 buf_info->dirty_shm = 0;
2019 if (g_dump_info->count == 1000)
2020 g_dump_info->count = 0;
2022 g_dump_info->link = next_link;
2024 TBM_LOG_I("Dump %s \n", buf_info->name);
2027 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2030 TBM_RETURN_IF_FAIL(ptr != NULL);
2031 TBM_RETURN_IF_FAIL(w > 0);
2032 TBM_RETURN_IF_FAIL(h > 0);
2033 TBM_RETURN_IF_FAIL(stride > 0);
2034 TBM_RETURN_IF_FAIL(type != NULL);
2036 tbm_surface_dump_buf_info *buf_info;
2037 struct list_head *next_link;
2038 tbm_bo_handle bo_handle;
2039 int ret, size, dw = 0, dh = 0, dstride = 0;
2044 next_link = g_dump_info->link->next;
2045 TBM_RETURN_IF_FAIL(next_link != NULL);
2047 if (next_link == &g_dump_info->surface_list) {
2048 next_link = next_link->next;
2049 TBM_RETURN_IF_FAIL(next_link != NULL);
2052 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2053 TBM_RETURN_IF_FAIL(buf_info != NULL);
2055 if (scale_factor > 0.0) {
2058 dw = w * scale_factor;
2059 dh = h * scale_factor;
2061 size = dstride * dh;
2065 if (size > buf_info->size) {
2066 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2067 size, buf_info->size);
2072 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2073 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2075 memset(bo_handle.ptr, 0x00, buf_info->size);
2076 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2078 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2079 _tbm_surface_internal_get_time(),
2080 g_dump_info->count++, type, dump_postfix[0]);
2081 if (scale_factor > 0.0) {
2082 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2083 TBM_FORMAT_ARGB8888, stride,
2084 w, h, dstride, dw, dh);
2085 if (ret != TBM_SURFACE_ERROR_NONE) {
2086 TBM_LOG_E("fail to scale buffer");
2087 tbm_bo_unmap(buf_info->bo);
2090 buf_info->shm_stride = dstride;
2091 buf_info->shm_h = dh;
2093 memcpy(bo_handle.ptr, ptr, size);
2094 buf_info->shm_stride = stride;
2095 buf_info->shm_h = h;
2098 tbm_bo_unmap(buf_info->bo);
2100 buf_info->dirty = 0;
2101 buf_info->dirty_shm = 1;
2103 if (g_dump_info->count == 1000)
2104 g_dump_info->count = 0;
2106 g_dump_info->link = next_link;
2108 TBM_LOG_I("Dump %s \n", buf_info->name);
2112 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2114 TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2115 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2116 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2118 tbm_surface_info_s info;
2119 const char *postfix;
2123 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2124 TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2126 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2127 postfix = dump_postfix[0];
2129 postfix = dump_postfix[1];
2131 if (strcmp(postfix, type)) {
2132 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2133 tbm_surface_unmap(surface);
2137 snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2139 if (!access(file, 0)) {
2140 TBM_LOG_E("can't capture buffer, exist file %s", file);
2141 tbm_surface_unmap(surface);
2145 switch (info.format) {
2146 case TBM_FORMAT_ARGB8888:
2147 case TBM_FORMAT_XRGB8888:
2148 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2149 info.planes[0].stride >> 2,
2152 case TBM_FORMAT_YVU420:
2153 case TBM_FORMAT_YUV420:
2154 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2155 info.planes[0].stride * info.height,
2157 info.planes[1].stride * (info.height >> 1),
2159 info.planes[2].stride * (info.height >> 1));
2161 case TBM_FORMAT_NV12:
2162 case TBM_FORMAT_NV21:
2163 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2164 info.planes[0].stride * info.height,
2166 info.planes[1].stride * (info.height >> 1),
2169 case TBM_FORMAT_YUYV:
2170 case TBM_FORMAT_UYVY:
2171 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2172 info.planes[0].stride * info.height,
2176 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2177 tbm_surface_unmap(surface);
2181 tbm_surface_unmap(surface);
2183 TBM_TRACE("Capture %s \n", file);
2189 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2190 const char *path, const char *name, const char *type)
2192 TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2193 TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2194 TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2195 TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2196 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2197 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2201 if (strcmp(dump_postfix[0], type)) {
2202 TBM_LOG_E("Not supported type:%s'", type);
2206 if (!access(file, 0)) {
2207 TBM_LOG_E("can't capture buffer, exist file %s", file);
2211 snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2213 _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2215 TBM_TRACE("Capture %s \n", file);