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();\
73 _tbm_surface_internal_get_time(void)
78 clock_gettime(CLOCK_MONOTONIC, &tp);
79 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
85 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
87 LIST_DEL(&debug_data->item_link);
89 if (debug_data->key) free(debug_data->key);
90 if (debug_data->value) free(debug_data->value);
95 _tbm_surface_internal_format_to_str(tbm_format format)
99 return "TBM_FORMAT_C8";
100 case TBM_FORMAT_RGB332:
101 return "TBM_FORMAT_RGB332";
102 case TBM_FORMAT_BGR233:
103 return "TBM_FORMAT_BGR233";
104 case TBM_FORMAT_XRGB4444:
105 return "TBM_FORMAT_XRGB4444";
106 case TBM_FORMAT_XBGR4444:
107 return "TBM_FORMAT_XBGR4444";
108 case TBM_FORMAT_RGBX4444:
109 return "TBM_FORMAT_RGBX4444";
110 case TBM_FORMAT_BGRX4444:
111 return "TBM_FORMAT_BGRX4444";
112 case TBM_FORMAT_ARGB4444:
113 return "TBM_FORMAT_ARGB4444";
114 case TBM_FORMAT_ABGR4444:
115 return "TBM_FORMAT_ABGR4444";
116 case TBM_FORMAT_RGBA4444:
117 return "TBM_FORMAT_RGBA4444";
118 case TBM_FORMAT_BGRA4444:
119 return "TBM_FORMAT_BGRA4444";
120 case TBM_FORMAT_XRGB1555:
121 return "TBM_FORMAT_XRGB1555";
122 case TBM_FORMAT_XBGR1555:
123 return "TBM_FORMAT_XBGR1555";
124 case TBM_FORMAT_RGBX5551:
125 return "TBM_FORMAT_RGBX5551";
126 case TBM_FORMAT_BGRX5551:
127 return "TBM_FORMAT_BGRX5551";
128 case TBM_FORMAT_ARGB1555:
129 return "TBM_FORMAT_ARGB1555";
130 case TBM_FORMAT_ABGR1555:
131 return "TBM_FORMAT_ABGR1555";
132 case TBM_FORMAT_RGBA5551:
133 return "TBM_FORMAT_RGBA5551";
134 case TBM_FORMAT_BGRA5551:
135 return "TBM_FORMAT_BGRA5551";
136 case TBM_FORMAT_RGB565:
137 return "TBM_FORMAT_RGB565";
138 case TBM_FORMAT_BGR565:
139 return "TBM_FORMAT_BGR565";
140 case TBM_FORMAT_RGB888:
141 return "TBM_FORMAT_RGB888";
142 case TBM_FORMAT_BGR888:
143 return "TBM_FORMAT_BGR888";
144 case TBM_FORMAT_XRGB8888:
145 return "TBM_FORMAT_XRGB8888";
146 case TBM_FORMAT_XBGR8888:
147 return "TBM_FORMAT_XBGR8888";
148 case TBM_FORMAT_RGBX8888:
149 return "TBM_FORMAT_RGBX8888";
150 case TBM_FORMAT_BGRX8888:
151 return "TBM_FORMAT_BGRX8888";
152 case TBM_FORMAT_ARGB8888:
153 return "TBM_FORMAT_ARGB8888";
154 case TBM_FORMAT_ABGR8888:
155 return "TBM_FORMAT_ABGR8888";
156 case TBM_FORMAT_RGBA8888:
157 return "TBM_FORMAT_RGBA8888";
158 case TBM_FORMAT_BGRA8888:
159 return "TBM_FORMAT_BGRA8888";
160 case TBM_FORMAT_XRGB2101010:
161 return "TBM_FORMAT_XRGB2101010";
162 case TBM_FORMAT_XBGR2101010:
163 return "TBM_FORMAT_XBGR2101010";
164 case TBM_FORMAT_RGBX1010102:
165 return "TBM_FORMAT_RGBX1010102";
166 case TBM_FORMAT_BGRX1010102:
167 return "TBM_FORMAT_BGRX1010102";
168 case TBM_FORMAT_ARGB2101010:
169 return "TBM_FORMAT_ARGB2101010";
170 case TBM_FORMAT_ABGR2101010:
171 return "TBM_FORMAT_ABGR2101010";
172 case TBM_FORMAT_RGBA1010102:
173 return "TBM_FORMAT_RGBA1010102";
174 case TBM_FORMAT_BGRA1010102:
175 return "TBM_FORMAT_BGRA1010102";
176 case TBM_FORMAT_YUYV:
177 return "TBM_FORMAT_YUYV";
178 case TBM_FORMAT_YVYU:
179 return "TBM_FORMAT_YVYU";
180 case TBM_FORMAT_UYVY:
181 return "TBM_FORMAT_UYVY";
182 case TBM_FORMAT_VYUY:
183 return "TBM_FORMAT_VYUY";
184 case TBM_FORMAT_AYUV:
185 return "TBM_FORMAT_AYUV";
186 case TBM_FORMAT_NV12:
187 return "TBM_FORMAT_NV12";
188 case TBM_FORMAT_NV21:
189 return "TBM_FORMAT_NV21";
190 case TBM_FORMAT_NV16:
191 return "TBM_FORMAT_NV16";
192 case TBM_FORMAT_NV61:
193 return "TBM_FORMAT_NV61";
194 case TBM_FORMAT_YUV410:
195 return "TBM_FORMAT_YUV410";
196 case TBM_FORMAT_YVU410:
197 return "TBM_FORMAT_YVU410";
198 case TBM_FORMAT_YUV411:
199 return "TBM_FORMAT_YUV411";
200 case TBM_FORMAT_YVU411:
201 return "TBM_FORMAT_YVU411";
202 case TBM_FORMAT_YUV420:
203 return "TBM_FORMAT_YUV420";
204 case TBM_FORMAT_YVU420:
205 return "TBM_FORMAT_YVU420";
206 case TBM_FORMAT_YUV422:
207 return "TBM_FORMAT_YUV422";
208 case TBM_FORMAT_YVU422:
209 return "TBM_FORMAT_YVU422";
210 case TBM_FORMAT_YUV444:
211 return "TBM_FORMAT_YUV444";
212 case TBM_FORMAT_YVU444:
213 return "TBM_FORMAT_YVU444";
214 case TBM_FORMAT_NV12MT:
215 return "TBM_FORMAT_NV12MT";
222 _tbm_surface_mutex_init(void)
224 static bool tbm_surface_mutex_init = false;
226 if (tbm_surface_mutex_init)
229 if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
230 TBM_LOG_E("fail: pthread_mutex_init for tbm_surface_lock.\n");
234 tbm_surface_mutex_init = true;
240 _tbm_surface_mutex_lock(void)
242 if (!_tbm_surface_mutex_init()) {
243 TBM_LOG_E("fail: _tbm_surface_mutex_init.\n");
247 pthread_mutex_lock(&tbm_surface_lock);
251 _tbm_surface_mutex_unlock(void)
253 pthread_mutex_unlock(&tbm_surface_lock);
257 _init_surface_bufmgr(void)
259 g_surface_bufmgr = tbm_bufmgr_init(-1);
263 _deinit_surface_bufmgr(void)
265 if (!g_surface_bufmgr)
268 tbm_bufmgr_deinit(g_surface_bufmgr);
269 g_surface_bufmgr = NULL;
274 _tbm_surface_internal_is_valid(tbm_surface_h surface)
276 tbm_surface_h old_data = NULL;
278 TBM_RETURN_VAL_IF_FAIL(g_surface_bufmgr, 0);
279 TBM_RETURN_VAL_IF_FAIL(surface, 0);
281 if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
282 LIST_FOR_EACH_ENTRY(old_data, &g_surface_bufmgr->surf_list, item_link) {
283 if (old_data == surface) {
284 TBM_TRACE("tbm_surface(%p)\n", surface);
290 TBM_LOG_E("error: No valid tbm_surface(%p)\n", surface);
296 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
297 int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
299 TBM_RETURN_VAL_IF_FAIL(surface, 0);
300 TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
302 struct _tbm_surface *surf = (struct _tbm_surface *)surface;
303 struct _tbm_bufmgr *mgr = surf->bufmgr;
306 TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
307 TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
308 TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
309 TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
311 if (!mgr->backend->surface_get_plane_data)
314 ret = mgr->backend->surface_get_plane_data(surf->info.width,
315 surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
317 /* LCOV_EXCL_START */
318 TBM_LOG_E("Fail to surface_get_plane_data. surface(%p)\n", surface);
327 _tbm_surface_internal_destroy(tbm_surface_h surface)
330 tbm_bufmgr bufmgr = surface->bufmgr;
331 tbm_user_data *old_data = NULL, *tmp = NULL;
332 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
334 /* destory the user_data_list */
335 if (!LIST_IS_EMPTY(&surface->user_data_list)) {
336 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
337 TBM_DBG("free user_data\n");
338 user_data_delete(old_data);
342 for (i = 0; i < surface->num_bos; i++) {
343 surface->bos[i]->surface = NULL;
345 tbm_bo_unref(surface->bos[i]);
346 surface->bos[i] = NULL;
349 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
350 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
351 _tbm_surface_internal_debug_data_delete(debug_old_data);
354 LIST_DEL(&surface->item_link);
359 if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
360 LIST_DELINIT(&bufmgr->surf_list);
362 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
363 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
364 _tbm_surface_internal_debug_data_delete(debug_old_data);
368 _deinit_surface_bufmgr();
373 tbm_surface_internal_is_valid(tbm_surface_h surface)
377 _tbm_surface_mutex_lock();
379 /* Return silently if surface is null. */
381 _tbm_surface_mutex_unlock();
385 ret = _tbm_surface_internal_is_valid(surface);
387 _tbm_surface_mutex_unlock();
393 tbm_surface_internal_query_supported_formats(uint32_t **formats,
396 struct _tbm_bufmgr *mgr;
398 bool bufmgr_initialized = false;
400 _tbm_surface_mutex_lock();
402 if (!g_surface_bufmgr) {
403 _init_surface_bufmgr();
404 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
405 bufmgr_initialized = true;
408 mgr = g_surface_bufmgr;
410 if (!mgr->backend->surface_supported_format)
413 ret = mgr->backend->surface_supported_format(formats, num);
415 /* LCOV_EXCL_START */
416 TBM_LOG_E("Fail to surface_supported_format.\n");
418 /* LCOV_EXCL_START */
421 TBM_TRACE("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
423 _tbm_surface_mutex_unlock();
427 /* LCOV_EXCL_START */
429 if (bufmgr_initialized) {
430 LIST_DELINIT(&g_surface_bufmgr->surf_list);
431 _deinit_surface_bufmgr();
433 _tbm_surface_mutex_unlock();
435 TBM_LOG_E("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
442 tbm_surface_internal_get_num_planes(tbm_format format)
448 case TBM_FORMAT_RGB332:
449 case TBM_FORMAT_BGR233:
450 case TBM_FORMAT_XRGB4444:
451 case TBM_FORMAT_XBGR4444:
452 case TBM_FORMAT_RGBX4444:
453 case TBM_FORMAT_BGRX4444:
454 case TBM_FORMAT_ARGB4444:
455 case TBM_FORMAT_ABGR4444:
456 case TBM_FORMAT_RGBA4444:
457 case TBM_FORMAT_BGRA4444:
458 case TBM_FORMAT_XRGB1555:
459 case TBM_FORMAT_XBGR1555:
460 case TBM_FORMAT_RGBX5551:
461 case TBM_FORMAT_BGRX5551:
462 case TBM_FORMAT_ARGB1555:
463 case TBM_FORMAT_ABGR1555:
464 case TBM_FORMAT_RGBA5551:
465 case TBM_FORMAT_BGRA5551:
466 case TBM_FORMAT_RGB565:
467 case TBM_FORMAT_BGR565:
468 case TBM_FORMAT_RGB888:
469 case TBM_FORMAT_BGR888:
470 case TBM_FORMAT_XRGB8888:
471 case TBM_FORMAT_XBGR8888:
472 case TBM_FORMAT_RGBX8888:
473 case TBM_FORMAT_BGRX8888:
474 case TBM_FORMAT_ARGB8888:
475 case TBM_FORMAT_ABGR8888:
476 case TBM_FORMAT_RGBA8888:
477 case TBM_FORMAT_BGRA8888:
478 case TBM_FORMAT_XRGB2101010:
479 case TBM_FORMAT_XBGR2101010:
480 case TBM_FORMAT_RGBX1010102:
481 case TBM_FORMAT_BGRX1010102:
482 case TBM_FORMAT_ARGB2101010:
483 case TBM_FORMAT_ABGR2101010:
484 case TBM_FORMAT_RGBA1010102:
485 case TBM_FORMAT_BGRA1010102:
486 case TBM_FORMAT_YUYV:
487 case TBM_FORMAT_YVYU:
488 case TBM_FORMAT_UYVY:
489 case TBM_FORMAT_VYUY:
490 case TBM_FORMAT_AYUV:
493 case TBM_FORMAT_NV12:
494 case TBM_FORMAT_NV12MT:
495 case TBM_FORMAT_NV21:
496 case TBM_FORMAT_NV16:
497 case TBM_FORMAT_NV61:
500 case TBM_FORMAT_YUV410:
501 case TBM_FORMAT_YVU410:
502 case TBM_FORMAT_YUV411:
503 case TBM_FORMAT_YVU411:
504 case TBM_FORMAT_YUV420:
505 case TBM_FORMAT_YVU420:
506 case TBM_FORMAT_YUV422:
507 case TBM_FORMAT_YVU422:
508 case TBM_FORMAT_YUV444:
509 case TBM_FORMAT_YVU444:
517 TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
523 tbm_surface_internal_get_bpp(tbm_format format)
530 case TBM_FORMAT_RGB332:
531 case TBM_FORMAT_BGR233:
534 case TBM_FORMAT_XRGB4444:
535 case TBM_FORMAT_XBGR4444:
536 case TBM_FORMAT_RGBX4444:
537 case TBM_FORMAT_BGRX4444:
538 case TBM_FORMAT_ARGB4444:
539 case TBM_FORMAT_ABGR4444:
540 case TBM_FORMAT_RGBA4444:
541 case TBM_FORMAT_BGRA4444:
542 case TBM_FORMAT_XRGB1555:
543 case TBM_FORMAT_XBGR1555:
544 case TBM_FORMAT_RGBX5551:
545 case TBM_FORMAT_BGRX5551:
546 case TBM_FORMAT_ARGB1555:
547 case TBM_FORMAT_ABGR1555:
548 case TBM_FORMAT_RGBA5551:
549 case TBM_FORMAT_BGRA5551:
550 case TBM_FORMAT_RGB565:
551 case TBM_FORMAT_BGR565:
554 case TBM_FORMAT_RGB888:
555 case TBM_FORMAT_BGR888:
558 case TBM_FORMAT_XRGB8888:
559 case TBM_FORMAT_XBGR8888:
560 case TBM_FORMAT_RGBX8888:
561 case TBM_FORMAT_BGRX8888:
562 case TBM_FORMAT_ARGB8888:
563 case TBM_FORMAT_ABGR8888:
564 case TBM_FORMAT_RGBA8888:
565 case TBM_FORMAT_BGRA8888:
566 case TBM_FORMAT_XRGB2101010:
567 case TBM_FORMAT_XBGR2101010:
568 case TBM_FORMAT_RGBX1010102:
569 case TBM_FORMAT_BGRX1010102:
570 case TBM_FORMAT_ARGB2101010:
571 case TBM_FORMAT_ABGR2101010:
572 case TBM_FORMAT_RGBA1010102:
573 case TBM_FORMAT_BGRA1010102:
574 case TBM_FORMAT_YUYV:
575 case TBM_FORMAT_YVYU:
576 case TBM_FORMAT_UYVY:
577 case TBM_FORMAT_VYUY:
578 case TBM_FORMAT_AYUV:
581 case TBM_FORMAT_NV12:
582 case TBM_FORMAT_NV12MT:
583 case TBM_FORMAT_NV21:
586 case TBM_FORMAT_NV16:
587 case TBM_FORMAT_NV61:
590 case TBM_FORMAT_YUV410:
591 case TBM_FORMAT_YVU410:
594 case TBM_FORMAT_YUV411:
595 case TBM_FORMAT_YVU411:
596 case TBM_FORMAT_YUV420:
597 case TBM_FORMAT_YVU420:
600 case TBM_FORMAT_YUV422:
601 case TBM_FORMAT_YVU422:
604 case TBM_FORMAT_YUV444:
605 case TBM_FORMAT_YVU444:
612 TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
618 tbm_surface_internal_create_with_flags(int width, int height,
619 int format, int flags)
621 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
622 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
624 struct _tbm_bufmgr *mgr;
625 struct _tbm_surface *surf = NULL;
629 uint32_t bo_size = 0;
632 bool bufmgr_initialized = false;
634 _tbm_surface_mutex_lock();
636 if (!g_surface_bufmgr) {
637 _init_surface_bufmgr();
638 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
639 bufmgr_initialized = true;
642 mgr = g_surface_bufmgr;
643 if (!TBM_BUFMGR_IS_VALID(mgr)) {
644 TBM_LOG_E("The bufmgr is invalid\n");
645 goto check_valid_fail;
648 surf = calloc(1, sizeof(struct _tbm_surface));
650 /* LCOV_EXCL_START */
651 TBM_LOG_E("fail to alloc surf\n");
652 goto alloc_surf_fail;
657 surf->info.width = width;
658 surf->info.height = height;
659 surf->info.format = format;
660 surf->info.bpp = tbm_surface_internal_get_bpp(format);
661 surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
664 /* get size, stride and offset bo_idx */
665 for (i = 0; i < surf->info.num_planes; i++) {
666 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
667 &offset, &stride, &bo_idx)) {
668 TBM_LOG_E("fail to query plane data\n");
669 goto query_plane_data_fail;
672 surf->info.planes[i].size = size;
673 surf->info.planes[i].offset = offset;
674 surf->info.planes[i].stride = stride;
675 surf->planes_bo_idx[i] = bo_idx;
680 for (i = 0; i < surf->info.num_planes; i++) {
681 surf->info.size += surf->info.planes[i].size;
683 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
684 surf->num_bos = surf->planes_bo_idx[i] + 1;
689 for (i = 0; i < surf->num_bos; i++) {
691 for (j = 0; j < surf->info.num_planes; j++) {
692 if (surf->planes_bo_idx[j] == i)
693 bo_size += surf->info.planes[j].size;
696 if (mgr->backend->surface_bo_alloc) {
697 /* LCOV_EXCL_START */
699 void *bo_priv = NULL;
701 bo = calloc(1, sizeof(struct _tbm_bo));
703 TBM_LOG_E("fail to alloc bo struct\n");
707 bo->bufmgr = surf->bufmgr;
709 pthread_mutex_lock(&surf->bufmgr->lock);
711 bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
713 TBM_LOG_E("fail to alloc bo priv\n");
715 pthread_mutex_unlock(&surf->bufmgr->lock);
723 LIST_INITHEAD(&bo->user_data_list);
725 LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
727 pthread_mutex_unlock(&surf->bufmgr->lock);
732 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
734 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
739 _tbm_bo_set_surface(surf->bos[i], surf);
742 TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
743 _tbm_surface_internal_format_to_str(format), flags, surf);
745 LIST_INITHEAD(&surf->user_data_list);
746 LIST_INITHEAD(&surf->debug_data_list);
748 LIST_ADD(&surf->item_link, &mgr->surf_list);
750 _tbm_surface_mutex_unlock();
754 /* LCOV_EXCL_START */
756 for (j = 0; j < i; j++) {
758 tbm_bo_unref(surf->bos[j]);
760 query_plane_data_fail:
764 if (bufmgr_initialized && mgr) {
765 LIST_DELINIT(&mgr->surf_list);
766 _deinit_surface_bufmgr();
768 _tbm_surface_mutex_unlock();
770 TBM_LOG_E("error: width(%d) height(%d) format(%s) flags(%d)\n",
772 _tbm_surface_internal_format_to_str(format), flags);
779 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
780 tbm_bo *bos, int num)
782 TBM_RETURN_VAL_IF_FAIL(bos, NULL);
783 TBM_RETURN_VAL_IF_FAIL(info, NULL);
784 TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
786 struct _tbm_bufmgr *mgr;
787 struct _tbm_surface *surf = NULL;
789 bool bufmgr_initialized = false;
791 _tbm_surface_mutex_lock();
793 if (!g_surface_bufmgr) {
794 _init_surface_bufmgr();
795 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
796 bufmgr_initialized = true;
799 mgr = g_surface_bufmgr;
800 if (!TBM_BUFMGR_IS_VALID(mgr)) {
801 TBM_LOG_E("fail to validate the Bufmgr.\n");
802 goto check_valid_fail;
805 surf = calloc(1, sizeof(struct _tbm_surface));
807 /* LCOV_EXCL_START */
808 TBM_LOG_E("fail to allocate struct _tbm_surface.\n");
809 goto alloc_surf_fail;
814 surf->info.width = info->width;
815 surf->info.height = info->height;
816 surf->info.format = info->format;
818 surf->info.bpp = info->bpp;
820 surf->info.bpp = tbm_surface_internal_get_bpp(info->format);
821 surf->info.num_planes = info->num_planes;
824 /* get size, stride and offset */
825 for (i = 0; i < info->num_planes; i++) {
826 surf->info.planes[i].offset = info->planes[i].offset;
827 surf->info.planes[i].stride = info->planes[i].stride;
829 if (info->planes[i].size > 0)
830 surf->info.planes[i].size = info->planes[i].size;
832 uint32_t size = 0, offset = 0, stride = 0;
835 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx);
836 surf->info.planes[i].size = size;
840 surf->planes_bo_idx[i] = 0;
842 surf->planes_bo_idx[i] = i;
845 if (info->size > 0) {
846 surf->info.size = info->size;
849 for (i = 0; i < info->num_planes; i++)
850 surf->info.size += surf->info.planes[i].size;
853 surf->flags = TBM_BO_DEFAULT;
855 /* create only one bo */
857 for (i = 0; i < num; i++) {
858 if (bos[i] == NULL) {
859 TBM_LOG_E("bos[%d] is null.\n", i);
863 surf->bos[i] = tbm_bo_ref(bos[i]);
864 _tbm_bo_set_surface(bos[i], surf);
867 TBM_TRACE("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
868 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
870 LIST_INITHEAD(&surf->user_data_list);
871 LIST_INITHEAD(&surf->debug_data_list);
873 LIST_ADD(&surf->item_link, &mgr->surf_list);
875 _tbm_surface_mutex_unlock();
879 /* LCOV_EXCL_START */
881 for (i = 0; i < num; i++) {
883 tbm_bo_unref(surf->bos[i]);
888 if (bufmgr_initialized && mgr) {
889 LIST_DELINIT(&mgr->surf_list);
890 _deinit_surface_bufmgr();
892 _tbm_surface_mutex_unlock();
894 TBM_LOG_E("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
895 info->width, info->height,
896 _tbm_surface_internal_format_to_str(info->format), num);
903 tbm_surface_internal_destroy(tbm_surface_h surface)
905 _tbm_surface_mutex_lock();
907 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
911 if (surface->refcnt > 0) {
912 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
913 _tbm_surface_mutex_unlock();
917 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
919 if (surface->refcnt == 0)
920 _tbm_surface_internal_destroy(surface);
922 _tbm_surface_mutex_unlock();
926 tbm_surface_internal_ref(tbm_surface_h surface)
928 _tbm_surface_mutex_lock();
930 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
934 TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
936 _tbm_surface_mutex_unlock();
940 tbm_surface_internal_unref(tbm_surface_h surface)
942 _tbm_surface_mutex_lock();
944 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
948 if (surface->refcnt > 0) {
949 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
950 _tbm_surface_mutex_unlock();
954 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
956 if (surface->refcnt == 0)
957 _tbm_surface_internal_destroy(surface);
959 _tbm_surface_mutex_unlock();
963 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
965 struct _tbm_surface *surf;
968 _tbm_surface_mutex_lock();
970 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
972 surf = (struct _tbm_surface *)surface;
975 TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
977 _tbm_surface_mutex_unlock();
983 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
985 struct _tbm_surface *surf;
988 _tbm_surface_mutex_lock();
990 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
991 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
993 surf = (struct _tbm_surface *)surface;
994 bo = surf->bos[bo_idx];
996 TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
998 _tbm_surface_mutex_unlock();
1004 tbm_surface_internal_get_size(tbm_surface_h surface)
1006 struct _tbm_surface *surf;
1009 _tbm_surface_mutex_lock();
1011 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1013 surf = (struct _tbm_surface *)surface;
1014 size = surf->info.size;
1016 TBM_TRACE("tbm_surface(%p) size(%u)\n", surface, size);
1018 _tbm_surface_mutex_unlock();
1024 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1025 uint32_t *size, uint32_t *offset, uint32_t *pitch)
1027 struct _tbm_surface *surf;
1029 _tbm_surface_mutex_lock();
1031 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1032 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1034 surf = (struct _tbm_surface *)surface;
1036 if (plane_idx >= surf->info.num_planes) {
1037 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1038 _tbm_surface_mutex_unlock();
1043 *size = surf->info.planes[plane_idx].size;
1046 *offset = surf->info.planes[plane_idx].offset;
1049 *pitch = surf->info.planes[plane_idx].stride;
1051 TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1052 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1053 surf->info.planes[plane_idx].stride);
1055 _tbm_surface_mutex_unlock();
1061 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1062 tbm_surface_info_s *info, int map)
1064 struct _tbm_surface *surf;
1065 tbm_bo_handle bo_handles[4];
1068 _tbm_surface_mutex_lock();
1070 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1072 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1074 surf = (struct _tbm_surface *)surface;
1076 memset(info, 0x00, sizeof(tbm_surface_info_s));
1077 info->width = surf->info.width;
1078 info->height = surf->info.height;
1079 info->format = surf->info.format;
1080 info->bpp = surf->info.bpp;
1081 info->size = surf->info.size;
1082 info->num_planes = surf->info.num_planes;
1085 for (i = 0; i < surf->num_bos; i++) {
1086 _tbm_surface_mutex_unlock();
1087 bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1088 _tbm_surface_mutex_lock();
1089 if (bo_handles[i].ptr == NULL) {
1090 for (j = 0; j < i; j++)
1091 tbm_bo_unmap(surf->bos[j]);
1093 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1094 _tbm_surface_mutex_unlock();
1099 for (i = 0; i < surf->num_bos; i++) {
1100 bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1101 if (bo_handles[i].ptr == NULL) {
1102 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1103 _tbm_surface_mutex_unlock();
1109 for (i = 0; i < surf->info.num_planes; i++) {
1110 info->planes[i].size = surf->info.planes[i].size;
1111 info->planes[i].offset = surf->info.planes[i].offset;
1112 info->planes[i].stride = surf->info.planes[i].stride;
1114 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1115 info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1116 surf->info.planes[i].offset;
1119 TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1121 _tbm_surface_mutex_unlock();
1127 tbm_surface_internal_unmap(tbm_surface_h surface)
1129 struct _tbm_surface *surf;
1132 _tbm_surface_mutex_lock();
1134 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1136 surf = (struct _tbm_surface *)surface;
1138 for (i = 0; i < surf->num_bos; i++)
1139 tbm_bo_unmap(surf->bos[i]);
1141 TBM_TRACE("tbm_surface(%p)\n", surface);
1143 _tbm_surface_mutex_unlock();
1147 tbm_surface_internal_get_width(tbm_surface_h surface)
1149 struct _tbm_surface *surf;
1152 _tbm_surface_mutex_lock();
1154 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1156 surf = (struct _tbm_surface *)surface;
1157 width = surf->info.width;
1159 TBM_TRACE("tbm_surface(%p) width(%u)\n", surface, width);
1161 _tbm_surface_mutex_unlock();
1167 tbm_surface_internal_get_height(tbm_surface_h surface)
1169 struct _tbm_surface *surf;
1170 unsigned int height;
1172 _tbm_surface_mutex_lock();
1174 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1176 surf = (struct _tbm_surface *)surface;
1177 height = surf->info.height;
1179 TBM_TRACE("tbm_surface(%p) height(%u)\n", surface, height);
1181 _tbm_surface_mutex_unlock();
1188 tbm_surface_internal_get_format(tbm_surface_h surface)
1190 struct _tbm_surface *surf;
1193 _tbm_surface_mutex_lock();
1195 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1197 surf = (struct _tbm_surface *)surface;
1198 format = surf->info.format;
1200 TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1202 _tbm_surface_mutex_unlock();
1208 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1210 struct _tbm_surface *surf;
1213 _tbm_surface_mutex_lock();
1215 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1216 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1218 surf = (struct _tbm_surface *)surface;
1219 bo_idx = surf->planes_bo_idx[plane_idx];
1221 TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1223 _tbm_surface_mutex_unlock();
1229 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1230 tbm_data_free data_free_func)
1232 tbm_user_data *data;
1234 _tbm_surface_mutex_lock();
1236 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1238 /* check if the data according to the key exist if so, return false. */
1239 data = user_data_lookup(&surface->user_data_list, key);
1241 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1242 _tbm_surface_mutex_unlock();
1246 data = user_data_create(key, data_free_func);
1248 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1249 _tbm_surface_mutex_unlock();
1253 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1255 LIST_ADD(&data->item_link, &surface->user_data_list);
1257 _tbm_surface_mutex_unlock();
1263 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1266 tbm_user_data *old_data;
1268 _tbm_surface_mutex_lock();
1270 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1272 old_data = user_data_lookup(&surface->user_data_list, key);
1274 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1275 _tbm_surface_mutex_unlock();
1279 if (old_data->data && old_data->free_func)
1280 old_data->free_func(old_data->data);
1282 old_data->data = data;
1284 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1286 _tbm_surface_mutex_unlock();
1292 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1295 tbm_user_data *old_data;
1297 _tbm_surface_mutex_lock();
1299 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1302 TBM_LOG_E("error: tbm_surface(%p) key(%lu)\n", surface, key);
1303 _tbm_surface_mutex_unlock();
1308 old_data = user_data_lookup(&surface->user_data_list, key);
1310 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1311 _tbm_surface_mutex_unlock();
1315 *data = old_data->data;
1317 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1319 _tbm_surface_mutex_unlock();
1325 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1328 tbm_user_data *old_data = (void *)0;
1330 _tbm_surface_mutex_lock();
1332 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1334 old_data = user_data_lookup(&surface->user_data_list, key);
1336 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1337 _tbm_surface_mutex_unlock();
1341 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1343 user_data_delete(old_data);
1345 _tbm_surface_mutex_unlock();
1350 /* LCOV_EXCL_START */
1352 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1354 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1356 return surface->debug_pid;
1360 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1362 _tbm_surface_mutex_lock();
1364 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1366 surface->debug_pid = pid;
1368 _tbm_surface_mutex_unlock();
1371 static tbm_surface_debug_data *
1372 _tbm_surface_internal_debug_data_create(char *key, char *value)
1374 tbm_surface_debug_data *debug_data = NULL;
1376 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1380 if (key) debug_data->key = strdup(key);
1381 if (value) debug_data->value = strdup(value);
1387 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1389 tbm_surface_debug_data *debug_data = NULL;
1390 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1391 tbm_bufmgr bufmgr = NULL;
1393 _tbm_surface_mutex_lock();
1395 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1396 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1398 bufmgr = surface->bufmgr;
1400 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1402 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1403 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1405 if (!strcmp(old_data->key, key)) {
1406 if (old_data->value && value && !strncmp(old_data->value, value, strlen(old_data->value))) {
1407 TBM_TRACE("tbm_surface(%p) Already exist key(%s) and value(%s)!\n", surface, key, value);
1408 goto add_debug_key_list;
1411 if (old_data->value)
1412 free(old_data->value);
1415 old_data->value = strdup(value);
1417 old_data->value = NULL;
1419 goto add_debug_key_list;
1425 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1427 TBM_LOG_E("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1428 _tbm_surface_mutex_unlock();
1432 TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1434 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1437 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1438 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1439 if (!strcmp(old_data->key, key)) {
1440 _tbm_surface_mutex_unlock();
1446 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1447 LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1449 _tbm_surface_mutex_unlock();
1455 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1457 tbm_surface_debug_data *old_data = NULL;
1459 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1461 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1462 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1463 if (!strcmp(old_data->key, key))
1464 return old_data->value;
1471 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1472 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1474 struct _tbm_surface_dump_buf_info {
1484 tbm_surface_info_s info;
1486 struct list_head link;
1489 struct _tbm_surface_dump_info {
1490 char *path; // copy???
1493 struct list_head *link;
1494 struct list_head surface_list; /* link of surface */
1497 static tbm_surface_dump_info *g_dump_info = NULL;
1498 static const char *dump_postfix[2] = {"png", "yuv"};
1499 static double scale_factor;
1502 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1503 void *data2, int size2, void *data3, int size3)
1505 FILE *fp = fopen(file, "w+");
1506 TBM_RETURN_IF_FAIL(fp != NULL);
1507 unsigned int *blocks;
1509 blocks = (unsigned int *)data1;
1510 fwrite(blocks, 1, size1, fp);
1513 blocks = (unsigned int *)data2;
1514 fwrite(blocks, 1, size2, fp);
1518 blocks = (unsigned int *)data3;
1519 fwrite(blocks, 1, size3, fp);
1526 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height)
1528 unsigned int *blocks = (unsigned int *)data;
1529 FILE *fp = fopen(file, "wb");
1530 TBM_RETURN_IF_FAIL(fp != NULL);
1531 const int pixel_size = 4; // RGBA
1532 png_bytep *row_pointers;
1535 png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1538 TBM_LOG_E("fail to create a png write structure.\n");
1543 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1545 TBM_LOG_E("fail to create a png info structure.\n");
1546 png_destroy_write_struct(&pPngStruct, NULL);
1551 png_init_io(pPngStruct, fp);
1552 png_set_IHDR(pPngStruct,
1557 PNG_COLOR_TYPE_RGBA,
1559 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1561 png_set_bgr(pPngStruct);
1562 png_write_info(pPngStruct, pPngInfo);
1564 row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1565 if (!row_pointers) {
1566 TBM_LOG_E("fail to allocate the png row_pointers.\n");
1567 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1572 for (y = 0; y < height; ++y) {
1576 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1578 TBM_LOG_E("fail to allocate the png row.\n");
1579 for (x = 0; x < y; x++)
1580 png_free(pPngStruct, row_pointers[x]);
1581 png_free(pPngStruct, row_pointers);
1582 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1586 row_pointers[y] = (png_bytep)row;
1588 for (x = 0; x < width; ++x) {
1589 unsigned int curBlock = blocks[y * width + x];
1591 row[x * pixel_size] = (curBlock & 0xFF);
1592 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1593 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1594 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1598 png_write_image(pPngStruct, row_pointers);
1599 png_write_end(pPngStruct, pPngInfo);
1601 for (y = 0; y < height; y++)
1602 png_free(pPngStruct, row_pointers[y]);
1603 png_free(pPngStruct, row_pointers);
1605 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1611 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1613 TBM_RETURN_IF_FAIL(path != NULL);
1614 TBM_RETURN_IF_FAIL(w > 0);
1615 TBM_RETURN_IF_FAIL(h > 0);
1616 TBM_RETURN_IF_FAIL(count > 0);
1618 tbm_surface_dump_buf_info *buf_info = NULL;
1619 tbm_surface_h tbm_surface;
1620 tbm_surface_info_s info;
1625 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1629 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1630 TBM_RETURN_IF_FAIL(g_dump_info);
1632 LIST_INITHEAD(&g_dump_info->surface_list);
1633 g_dump_info->count = 0;
1634 g_dump_info->dump_max = count;
1636 /* get buffer size */
1637 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1638 if (tbm_surface == NULL) {
1639 TBM_LOG_E("tbm_surface_create fail\n");
1645 if (TBM_SURFACE_ERROR_NONE != tbm_surface_map(tbm_surface,
1646 TBM_SURF_OPTION_READ, &info)) {
1647 TBM_LOG_E("tbm_surface_map fail\n");
1648 tbm_surface_destroy(tbm_surface);
1653 buffer_size = info.planes[0].stride * h;
1655 tbm_surface_unmap(tbm_surface);
1656 tbm_surface_destroy(tbm_surface);
1658 /* create dump lists */
1659 for (i = 0; i < count; i++) {
1662 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1663 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1665 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1667 TBM_LOG_E("fail to allocate the tbm_bo[%d]\n", i);
1672 buf_info->index = i;
1674 buf_info->size = buffer_size;
1676 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1679 g_dump_info->path = path;
1680 g_dump_info->link = &g_dump_info->surface_list;
1684 TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1689 /* free resources */
1690 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1691 tbm_surface_dump_buf_info *tmp;
1693 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1694 tbm_bo_unref(buf_info->bo);
1695 LIST_DEL(&buf_info->link);
1700 TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1709 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
1711 TBM_RETURN_IF_FAIL(scale > 0.0);
1713 tbm_surface_internal_dump_start(path, (int)(scale * w), (int)(scale * h), count);
1715 scale_factor = scale;
1719 tbm_surface_internal_dump_end(void)
1721 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1722 tbm_bo_handle bo_handle;
1727 if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1734 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1737 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1738 if (bo_handle.ptr == NULL) {
1739 tbm_bo_unref(buf_info->bo);
1740 LIST_DEL(&buf_info->link);
1745 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1746 TBM_LOG_I("Dump File.. %s generated.\n", file);
1748 if (buf_info->dirty) {
1749 void *ptr1 = NULL, *ptr2 = NULL;
1751 switch (buf_info->info.format) {
1752 case TBM_FORMAT_ARGB8888:
1753 case TBM_FORMAT_XRGB8888:
1754 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1755 buf_info->info.planes[0].stride >> 2,
1756 buf_info->info.height);
1758 case TBM_FORMAT_YVU420:
1759 case TBM_FORMAT_YUV420:
1760 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1761 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1762 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1763 buf_info->info.planes[0].stride * buf_info->info.height,
1765 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1767 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1769 case TBM_FORMAT_NV12:
1770 case TBM_FORMAT_NV21:
1771 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1772 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1773 buf_info->info.planes[0].stride * buf_info->info.height,
1775 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1778 case TBM_FORMAT_YUYV:
1779 case TBM_FORMAT_UYVY:
1780 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1781 buf_info->info.planes[0].stride * buf_info->info.height,
1785 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1788 } else if (buf_info->dirty_shm)
1789 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1790 buf_info->shm_stride >> 2,
1793 tbm_bo_unmap(buf_info->bo);
1794 tbm_bo_unref(buf_info->bo);
1795 LIST_DEL(&buf_info->link);
1802 TBM_LOG_I("Dump End..\n");
1805 static pixman_format_code_t
1806 _tbm_surface_internal_pixman_format_get(tbm_format format)
1809 case TBM_FORMAT_ARGB8888:
1810 return PIXMAN_a8r8g8b8;
1811 case TBM_FORMAT_XRGB8888:
1812 return PIXMAN_x8r8g8b8;
1821 * This function supports only if a buffer has below formats.
1822 * - TBM_FORMAT_ARGB8888
1823 * - TBM_FORMAT_XRGB8888
1825 static tbm_surface_error_e
1826 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
1827 int format, int src_stride, int src_w, int src_h,
1828 int dst_stride, int dst_w, int dst_h)
1830 pixman_image_t *src_img = NULL, *dst_img = NULL;
1831 pixman_format_code_t pixman_format;
1832 pixman_transform_t t;
1833 struct pixman_f_transform ft;
1834 double scale_x, scale_y;
1836 TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
1837 TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
1839 pixman_format = _tbm_surface_internal_pixman_format_get(format);
1840 TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
1843 src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
1844 (uint32_t*)src_ptr, src_stride);
1845 TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
1848 dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
1849 (uint32_t*)dst_ptr, dst_stride);
1850 TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
1852 pixman_f_transform_init_identity(&ft);
1854 scale_x = (double)src_w / dst_w;
1855 scale_y = (double)src_h / dst_h;
1857 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
1858 pixman_f_transform_translate(&ft, NULL, 0, 0);
1859 pixman_transform_from_pixman_f_transform(&t, &ft);
1860 pixman_image_set_transform(src_img, &t);
1862 pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
1863 0, 0, 0, 0, 0, 0, dst_w, dst_h);
1865 pixman_image_unref(src_img);
1866 pixman_image_unref(dst_img);
1868 return TBM_SURFACE_ERROR_NONE;
1872 pixman_image_unref(src_img);
1874 return TBM_SURFACE_ERROR_INVALID_OPERATION;
1878 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1880 TBM_RETURN_IF_FAIL(surface != NULL);
1881 TBM_RETURN_IF_FAIL(type != NULL);
1883 tbm_surface_dump_buf_info *buf_info;
1884 struct list_head *next_link;
1885 tbm_surface_info_s info;
1886 tbm_bo_handle bo_handle;
1887 const char *postfix;
1893 next_link = g_dump_info->link->next;
1894 TBM_RETURN_IF_FAIL(next_link != NULL);
1896 if (next_link == &g_dump_info->surface_list) {
1897 next_link = next_link->next;
1898 TBM_RETURN_IF_FAIL(next_link != NULL);
1901 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1902 TBM_RETURN_IF_FAIL(buf_info != NULL);
1904 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1905 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1907 if (scale_factor > 0.0) {
1910 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
1911 TBM_LOG_W("Dump with scale skip. unsupported format(%s)\n",
1912 _tbm_surface_internal_format_to_str(info.format));
1913 tbm_surface_unmap(surface);
1917 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
1919 buf_info->info.width = info.width * scale_factor;
1920 buf_info->info.height = info.height * scale_factor;
1921 buf_info->info.format = info.format;
1922 buf_info->info.bpp = tbm_surface_internal_get_bpp(buf_info->info.format);
1923 buf_info->info.num_planes = 1;
1924 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
1925 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
1927 if (buf_info->info.size > buf_info->size) {
1928 TBM_LOG_W("Dump with scale skip. surface over created buffer size(%u, %d)\n",
1929 buf_info->info.size, buf_info->size);
1930 tbm_surface_unmap(surface);
1934 if (info.size > buf_info->size) {
1935 TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1936 info.size, buf_info->size);
1937 tbm_surface_unmap(surface);
1941 /* make the file information */
1942 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1945 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1946 postfix = dump_postfix[0];
1948 postfix = dump_postfix[1];
1951 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1952 if (!bo_handle.ptr) {
1953 TBM_LOG_E("fail to map bo");
1954 tbm_surface_unmap(surface);
1957 memset(bo_handle.ptr, 0x00, buf_info->size);
1959 switch (info.format) {
1960 case TBM_FORMAT_ARGB8888:
1961 case TBM_FORMAT_XRGB8888:
1962 snprintf(buf_info->name, sizeof(buf_info->name),
1963 "%10.3f_%03d_%p-%s.%s",
1964 _tbm_surface_internal_get_time(),
1965 g_dump_info->count++, surface, type, postfix);
1967 if (scale_factor > 0.0) {
1968 ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
1970 buf_info->info.format,
1971 info.planes[0].stride,
1972 info.width, info.height,
1973 buf_info->info.planes[0].stride,
1974 buf_info->info.width,
1975 buf_info->info.height);
1976 if (ret != TBM_SURFACE_ERROR_NONE) {
1977 TBM_LOG_E("fail to scale buffer");
1978 tbm_bo_unmap(buf_info->bo);
1979 tbm_surface_unmap(surface);
1983 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1985 case TBM_FORMAT_YVU420:
1986 case TBM_FORMAT_YUV420:
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));
1995 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1996 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1998 case TBM_FORMAT_NV12:
1999 case TBM_FORMAT_NV21:
2000 snprintf(buf_info->name, sizeof(buf_info->name),
2001 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
2002 _tbm_surface_internal_get_time(),
2003 g_dump_info->count++, type, info.planes[0].stride,
2004 info.height, FOURCC_STR(info.format), postfix);
2005 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2006 bo_handle.ptr += info.planes[0].stride * info.height;
2007 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2009 case TBM_FORMAT_YUYV:
2010 case TBM_FORMAT_UYVY:
2011 snprintf(buf_info->name, sizeof(buf_info->name),
2012 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
2013 _tbm_surface_internal_get_time(),
2014 g_dump_info->count++, type, info.planes[0].stride,
2015 info.height, FOURCC_STR(info.format), postfix);
2016 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2019 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2020 tbm_bo_unmap(buf_info->bo);
2021 tbm_surface_unmap(surface);
2025 tbm_bo_unmap(buf_info->bo);
2027 tbm_surface_unmap(surface);
2029 buf_info->dirty = 1;
2030 buf_info->dirty_shm = 0;
2032 if (g_dump_info->count == 1000)
2033 g_dump_info->count = 0;
2035 g_dump_info->link = next_link;
2037 TBM_LOG_I("Dump %s \n", buf_info->name);
2040 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2043 TBM_RETURN_IF_FAIL(ptr != NULL);
2044 TBM_RETURN_IF_FAIL(w > 0);
2045 TBM_RETURN_IF_FAIL(h > 0);
2046 TBM_RETURN_IF_FAIL(stride > 0);
2047 TBM_RETURN_IF_FAIL(type != NULL);
2049 tbm_surface_dump_buf_info *buf_info;
2050 struct list_head *next_link;
2051 tbm_bo_handle bo_handle;
2052 int ret, size, dw = 0, dh = 0, dstride = 0;
2057 next_link = g_dump_info->link->next;
2058 TBM_RETURN_IF_FAIL(next_link != NULL);
2060 if (next_link == &g_dump_info->surface_list) {
2061 next_link = next_link->next;
2062 TBM_RETURN_IF_FAIL(next_link != NULL);
2065 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2066 TBM_RETURN_IF_FAIL(buf_info != NULL);
2068 if (scale_factor > 0.0) {
2071 dw = w * scale_factor;
2072 dh = h * scale_factor;
2074 size = dstride * dh;
2078 if (size > buf_info->size) {
2079 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2080 size, buf_info->size);
2085 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2086 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2088 memset(bo_handle.ptr, 0x00, buf_info->size);
2089 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2091 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2092 _tbm_surface_internal_get_time(),
2093 g_dump_info->count++, type, dump_postfix[0]);
2094 if (scale_factor > 0.0) {
2095 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2096 TBM_FORMAT_ARGB8888, stride,
2097 w, h, dstride, dw, dh);
2098 if (ret != TBM_SURFACE_ERROR_NONE) {
2099 TBM_LOG_E("fail to scale buffer");
2100 tbm_bo_unmap(buf_info->bo);
2103 buf_info->shm_stride = dstride;
2104 buf_info->shm_h = dh;
2106 memcpy(bo_handle.ptr, ptr, size);
2107 buf_info->shm_stride = stride;
2108 buf_info->shm_h = h;
2111 tbm_bo_unmap(buf_info->bo);
2113 buf_info->dirty = 0;
2114 buf_info->dirty_shm = 1;
2116 if (g_dump_info->count == 1000)
2117 g_dump_info->count = 0;
2119 g_dump_info->link = next_link;
2121 TBM_LOG_I("Dump %s \n", buf_info->name);
2125 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2127 TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2128 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2129 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2131 tbm_surface_info_s info;
2132 const char *postfix;
2136 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2137 TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2139 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2140 postfix = dump_postfix[0];
2142 postfix = dump_postfix[1];
2144 if (strcmp(postfix, type)) {
2145 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2146 tbm_surface_unmap(surface);
2150 snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2152 if (!access(file, 0)) {
2153 TBM_LOG_E("can't capture buffer, exist file %s", file);
2154 tbm_surface_unmap(surface);
2158 switch (info.format) {
2159 case TBM_FORMAT_ARGB8888:
2160 case TBM_FORMAT_XRGB8888:
2161 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2162 info.planes[0].stride >> 2,
2165 case TBM_FORMAT_YVU420:
2166 case TBM_FORMAT_YUV420:
2167 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2168 info.planes[0].stride * info.height,
2170 info.planes[1].stride * (info.height >> 1),
2172 info.planes[2].stride * (info.height >> 1));
2174 case TBM_FORMAT_NV12:
2175 case TBM_FORMAT_NV21:
2176 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2177 info.planes[0].stride * info.height,
2179 info.planes[1].stride * (info.height >> 1),
2182 case TBM_FORMAT_YUYV:
2183 case TBM_FORMAT_UYVY:
2184 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2185 info.planes[0].stride * info.height,
2189 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2190 tbm_surface_unmap(surface);
2194 tbm_surface_unmap(surface);
2196 TBM_TRACE("Capture %s \n", file);
2202 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2203 const char *path, const char *name, const char *type)
2205 TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2206 TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2207 TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2208 TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2209 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2210 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2214 if (strcmp(dump_postfix[0], type)) {
2215 TBM_LOG_E("Not supported type:%s'", type);
2219 if (!access(file, 0)) {
2220 TBM_LOG_E("can't capture buffer, exist file %s", file);
2224 snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2226 _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2228 TBM_TRACE("Capture %s \n", file);