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)
1716 tbm_surface_internal_dump_start(path, w, h, count);
1717 scale_factor = scale;
1721 tbm_surface_internal_dump_end(void)
1723 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1724 tbm_bo_handle bo_handle;
1729 if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1736 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1739 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1740 if (bo_handle.ptr == NULL) {
1741 tbm_bo_unref(buf_info->bo);
1742 LIST_DEL(&buf_info->link);
1747 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1748 TBM_LOG_I("Dump File.. %s generated.\n", file);
1750 if (buf_info->dirty) {
1751 void *ptr1 = NULL, *ptr2 = NULL;
1753 switch (buf_info->info.format) {
1754 case TBM_FORMAT_ARGB8888:
1755 case TBM_FORMAT_XRGB8888:
1756 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1757 buf_info->info.planes[0].stride >> 2,
1758 buf_info->info.height);
1760 case TBM_FORMAT_YVU420:
1761 case TBM_FORMAT_YUV420:
1762 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1763 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1764 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1765 buf_info->info.planes[0].stride * buf_info->info.height,
1767 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1769 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1771 case TBM_FORMAT_NV12:
1772 case TBM_FORMAT_NV21:
1773 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1774 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1775 buf_info->info.planes[0].stride * buf_info->info.height,
1777 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1780 case TBM_FORMAT_YUYV:
1781 case TBM_FORMAT_UYVY:
1782 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1783 buf_info->info.planes[0].stride * buf_info->info.height,
1787 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1790 } else if (buf_info->dirty_shm)
1791 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1792 buf_info->shm_stride >> 2,
1795 tbm_bo_unmap(buf_info->bo);
1796 tbm_bo_unref(buf_info->bo);
1797 LIST_DEL(&buf_info->link);
1804 TBM_LOG_I("Dump End..\n");
1807 static pixman_format_code_t
1808 _tbm_surface_internal_pixman_format_get(tbm_format format)
1811 case TBM_FORMAT_ARGB8888:
1812 return PIXMAN_a8r8g8b8;
1813 case TBM_FORMAT_XRGB8888:
1814 return PIXMAN_x8r8g8b8;
1823 * This function supports only if a buffer has below formats.
1824 * - TBM_FORMAT_ARGB8888
1825 * - TBM_FORMAT_XRGB8888
1827 static tbm_surface_error_e
1828 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
1829 int format, int src_stride, int src_w, int src_h,
1830 int dst_stride, int dst_w, int dst_h)
1832 pixman_image_t *src_img = NULL, *dst_img = NULL;
1833 pixman_format_code_t pixman_format;
1834 pixman_transform_t t;
1835 struct pixman_f_transform ft;
1836 double scale_x, scale_y;
1838 TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
1839 TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
1841 pixman_format = _tbm_surface_internal_pixman_format_get(format);
1842 TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
1845 src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
1846 (uint32_t*)src_ptr, src_stride);
1847 TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
1850 dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
1851 (uint32_t*)dst_ptr, dst_stride);
1852 TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
1854 pixman_f_transform_init_identity(&ft);
1856 scale_x = (double)src_w / dst_w;
1857 scale_y = (double)src_h / dst_h;
1859 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
1860 pixman_f_transform_translate(&ft, NULL, 0, 0);
1861 pixman_transform_from_pixman_f_transform(&t, &ft);
1862 pixman_image_set_transform(src_img, &t);
1864 pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
1865 0, 0, 0, 0, 0, 0, dst_w, dst_h);
1867 pixman_image_unref(src_img);
1868 pixman_image_unref(dst_img);
1870 return TBM_SURFACE_ERROR_NONE;
1874 pixman_image_unref(src_img);
1876 return TBM_SURFACE_ERROR_INVALID_OPERATION;
1880 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1882 TBM_RETURN_IF_FAIL(surface != NULL);
1883 TBM_RETURN_IF_FAIL(type != NULL);
1885 tbm_surface_dump_buf_info *buf_info;
1886 struct list_head *next_link;
1887 tbm_surface_info_s info;
1888 tbm_bo_handle bo_handle;
1889 const char *postfix;
1895 next_link = g_dump_info->link->next;
1896 TBM_RETURN_IF_FAIL(next_link != NULL);
1898 if (next_link == &g_dump_info->surface_list) {
1899 next_link = next_link->next;
1900 TBM_RETURN_IF_FAIL(next_link != NULL);
1903 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1904 TBM_RETURN_IF_FAIL(buf_info != NULL);
1906 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1907 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1909 if (scale_factor > 0.0) {
1912 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
1913 TBM_LOG_W("Dump with scale skip. unsupported format(%s)\n",
1914 _tbm_surface_internal_format_to_str(info.format));
1915 tbm_surface_unmap(surface);
1919 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
1921 buf_info->info.width = info.width * scale_factor;
1922 buf_info->info.height = info.height * scale_factor;
1923 buf_info->info.format = info.format;
1924 buf_info->info.bpp = tbm_surface_internal_get_bpp(buf_info->info.format);
1925 buf_info->info.num_planes = 1;
1926 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
1927 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
1929 if (buf_info->info.size > buf_info->size) {
1930 TBM_LOG_W("Dump with scale skip. surface over created buffer size(%u, %d)\n",
1931 buf_info->info.size, buf_info->size);
1932 tbm_surface_unmap(surface);
1936 if (info.size > buf_info->size) {
1937 TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1938 info.size, buf_info->size);
1939 tbm_surface_unmap(surface);
1943 /* make the file information */
1944 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1947 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1948 postfix = dump_postfix[0];
1950 postfix = dump_postfix[1];
1953 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1954 if (!bo_handle.ptr) {
1955 TBM_LOG_E("fail to map bo");
1956 tbm_surface_unmap(surface);
1959 memset(bo_handle.ptr, 0x00, buf_info->size);
1961 switch (info.format) {
1962 case TBM_FORMAT_ARGB8888:
1963 case TBM_FORMAT_XRGB8888:
1964 snprintf(buf_info->name, sizeof(buf_info->name),
1965 "%10.3f_%03d_%p-%s.%s",
1966 _tbm_surface_internal_get_time(),
1967 g_dump_info->count++, surface, type, postfix);
1969 if (scale_factor > 0.0) {
1970 ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
1972 buf_info->info.format,
1973 info.planes[0].stride,
1974 info.width, info.height,
1975 buf_info->info.planes[0].stride,
1976 buf_info->info.width,
1977 buf_info->info.height);
1978 if (ret != TBM_SURFACE_ERROR_NONE) {
1979 TBM_LOG_E("fail to scale buffer");
1980 tbm_bo_unmap(buf_info->bo);
1981 tbm_surface_unmap(surface);
1985 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1987 case TBM_FORMAT_YVU420:
1988 case TBM_FORMAT_YUV420:
1989 snprintf(buf_info->name, sizeof(buf_info->name),
1990 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1991 _tbm_surface_internal_get_time(),
1992 g_dump_info->count++, type, info.planes[0].stride,
1993 info.height, FOURCC_STR(info.format), postfix);
1994 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1995 bo_handle.ptr += info.planes[0].stride * info.height;
1996 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1997 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1998 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2000 case TBM_FORMAT_NV12:
2001 case TBM_FORMAT_NV21:
2002 snprintf(buf_info->name, sizeof(buf_info->name),
2003 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
2004 _tbm_surface_internal_get_time(),
2005 g_dump_info->count++, type, info.planes[0].stride,
2006 info.height, FOURCC_STR(info.format), postfix);
2007 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2008 bo_handle.ptr += info.planes[0].stride * info.height;
2009 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2011 case TBM_FORMAT_YUYV:
2012 case TBM_FORMAT_UYVY:
2013 snprintf(buf_info->name, sizeof(buf_info->name),
2014 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
2015 _tbm_surface_internal_get_time(),
2016 g_dump_info->count++, type, info.planes[0].stride,
2017 info.height, FOURCC_STR(info.format), postfix);
2018 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2021 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2022 tbm_bo_unmap(buf_info->bo);
2023 tbm_surface_unmap(surface);
2027 tbm_bo_unmap(buf_info->bo);
2029 tbm_surface_unmap(surface);
2031 buf_info->dirty = 1;
2032 buf_info->dirty_shm = 0;
2034 if (g_dump_info->count == 1000)
2035 g_dump_info->count = 0;
2037 g_dump_info->link = next_link;
2039 TBM_LOG_I("Dump %s \n", buf_info->name);
2042 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2045 TBM_RETURN_IF_FAIL(ptr != NULL);
2046 TBM_RETURN_IF_FAIL(w > 0);
2047 TBM_RETURN_IF_FAIL(h > 0);
2048 TBM_RETURN_IF_FAIL(stride > 0);
2049 TBM_RETURN_IF_FAIL(type != NULL);
2051 tbm_surface_dump_buf_info *buf_info;
2052 struct list_head *next_link;
2053 tbm_bo_handle bo_handle;
2054 int ret, size, dw = 0, dh = 0, dstride = 0;
2059 next_link = g_dump_info->link->next;
2060 TBM_RETURN_IF_FAIL(next_link != NULL);
2062 if (next_link == &g_dump_info->surface_list) {
2063 next_link = next_link->next;
2064 TBM_RETURN_IF_FAIL(next_link != NULL);
2067 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2068 TBM_RETURN_IF_FAIL(buf_info != NULL);
2070 if (scale_factor > 0.0) {
2073 dw = w * scale_factor;
2074 dh = h * scale_factor;
2076 size = dstride * dh;
2080 if (size > buf_info->size) {
2081 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2082 size, buf_info->size);
2087 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2088 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2090 memset(bo_handle.ptr, 0x00, buf_info->size);
2091 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2093 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2094 _tbm_surface_internal_get_time(),
2095 g_dump_info->count++, type, dump_postfix[0]);
2096 if (scale_factor > 0.0) {
2097 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2098 TBM_FORMAT_ARGB8888, stride,
2099 w, h, dstride, dw, dh);
2100 if (ret != TBM_SURFACE_ERROR_NONE) {
2101 TBM_LOG_E("fail to scale buffer");
2102 tbm_bo_unmap(buf_info->bo);
2105 buf_info->shm_stride = dstride;
2106 buf_info->shm_h = dh;
2108 memcpy(bo_handle.ptr, ptr, size);
2109 buf_info->shm_stride = stride;
2110 buf_info->shm_h = h;
2113 tbm_bo_unmap(buf_info->bo);
2115 buf_info->dirty = 0;
2116 buf_info->dirty_shm = 1;
2118 if (g_dump_info->count == 1000)
2119 g_dump_info->count = 0;
2121 g_dump_info->link = next_link;
2123 TBM_LOG_I("Dump %s \n", buf_info->name);
2127 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2129 TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2130 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2131 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2133 tbm_surface_info_s info;
2134 const char *postfix;
2138 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2139 TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2141 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2142 postfix = dump_postfix[0];
2144 postfix = dump_postfix[1];
2146 if (strcmp(postfix, type)) {
2147 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2148 tbm_surface_unmap(surface);
2152 snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2154 if (!access(file, 0)) {
2155 TBM_LOG_E("can't capture buffer, exist file %s", file);
2156 tbm_surface_unmap(surface);
2160 switch (info.format) {
2161 case TBM_FORMAT_ARGB8888:
2162 case TBM_FORMAT_XRGB8888:
2163 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2164 info.planes[0].stride >> 2,
2167 case TBM_FORMAT_YVU420:
2168 case TBM_FORMAT_YUV420:
2169 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2170 info.planes[0].stride * info.height,
2172 info.planes[1].stride * (info.height >> 1),
2174 info.planes[2].stride * (info.height >> 1));
2176 case TBM_FORMAT_NV12:
2177 case TBM_FORMAT_NV21:
2178 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2179 info.planes[0].stride * info.height,
2181 info.planes[1].stride * (info.height >> 1),
2184 case TBM_FORMAT_YUYV:
2185 case TBM_FORMAT_UYVY:
2186 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2187 info.planes[0].stride * info.height,
2191 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2192 tbm_surface_unmap(surface);
2196 tbm_surface_unmap(surface);
2198 TBM_TRACE("Capture %s \n", file);
2204 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2205 const char *path, const char *name, const char *type)
2207 TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2208 TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2209 TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2210 TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2211 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2212 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2216 if (strcmp(dump_postfix[0], type)) {
2217 TBM_LOG_E("Not supported type:%s'", type);
2221 if (!access(file, 0)) {
2222 TBM_LOG_E("can't capture buffer, exist file %s", file);
2226 snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2228 _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2230 TBM_TRACE("Capture %s \n", file);