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"
43 static tbm_bufmgr g_surface_bufmgr;
44 static pthread_mutex_t tbm_surface_lock;
45 void _tbm_surface_mutex_unlock(void);
47 #define C(b, m) (((b) >> (m)) & 0xFF)
48 #define B(c, s) ((((unsigned int)(c)) & 0xff) << (s))
49 #define FOURCC(a, b, c, d) (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
50 #define FOURCC_STR(id) C(id, 0), C(id, 8), C(id, 16), C(id, 24)
51 #define FOURCC_ID(str) FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3])
54 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
56 TBM_LOG_E("'%s' failed.\n", #cond);\
57 _tbm_surface_mutex_unlock();\
62 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
64 TBM_LOG_E("'%s' failed.\n", #cond);\
65 _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";
223 _tbm_surface_mutex_init(void)
225 static bool tbm_surface_mutex_init = false;
227 if (tbm_surface_mutex_init)
230 if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
231 TBM_LOG_E("fail: pthread_mutex_init for tbm_surface_lock.\n");
235 tbm_surface_mutex_init = true;
241 _tbm_surface_mutex_lock(void)
243 if (!_tbm_surface_mutex_init()) {
244 TBM_LOG_E("fail: _tbm_surface_mutex_init.\n");
248 pthread_mutex_lock(&tbm_surface_lock);
252 _tbm_surface_mutex_unlock(void)
254 pthread_mutex_unlock(&tbm_surface_lock);
258 _init_surface_bufmgr(void)
260 g_surface_bufmgr = tbm_bufmgr_init(-1);
264 _deinit_surface_bufmgr(void)
266 if (!g_surface_bufmgr)
269 tbm_bufmgr_deinit(g_surface_bufmgr);
270 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 TBM_LOG_E("Fail to surface_get_plane_data. surface(%p)\n", surface);
325 _tbm_surface_internal_destroy(tbm_surface_h surface)
328 tbm_bufmgr bufmgr = surface->bufmgr;
329 tbm_user_data *old_data = NULL, *tmp = NULL;
330 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
332 /* destory the user_data_list */
333 if (!LIST_IS_EMPTY(&surface->user_data_list)) {
334 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
335 TBM_DBG("free user_data\n");
336 user_data_delete(old_data);
340 for (i = 0; i < surface->num_bos; i++) {
341 surface->bos[i]->surface = NULL;
343 tbm_bo_unref(surface->bos[i]);
344 surface->bos[i] = NULL;
347 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
348 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
349 _tbm_surface_internal_debug_data_delete(debug_old_data);
352 LIST_DEL(&surface->item_link);
357 if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
358 LIST_DELINIT(&bufmgr->surf_list);
360 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
361 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
362 _tbm_surface_internal_debug_data_delete(debug_old_data);
366 _deinit_surface_bufmgr();
371 tbm_surface_internal_is_valid(tbm_surface_h surface)
375 _tbm_surface_mutex_lock();
377 /* Return silently if surface is null. */
379 _tbm_surface_mutex_unlock();
383 ret = _tbm_surface_internal_is_valid(surface);
385 _tbm_surface_mutex_unlock();
391 tbm_surface_internal_query_supported_formats(uint32_t **formats,
394 struct _tbm_bufmgr *mgr;
396 bool bufmgr_initialized = false;
398 _tbm_surface_mutex_lock();
400 if (!g_surface_bufmgr) {
401 _init_surface_bufmgr();
402 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
403 bufmgr_initialized = true;
406 mgr = g_surface_bufmgr;
408 if (!mgr->backend->surface_supported_format)
411 ret = mgr->backend->surface_supported_format(formats, num);
413 TBM_LOG_E("Fail to surface_supported_format.\n");
417 TBM_TRACE("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
419 _tbm_surface_mutex_unlock();
424 if (bufmgr_initialized) {
425 LIST_DELINIT(&g_surface_bufmgr->surf_list);
426 _deinit_surface_bufmgr();
428 _tbm_surface_mutex_unlock();
430 TBM_LOG_E("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
436 tbm_surface_internal_get_num_planes(tbm_format format)
442 case TBM_FORMAT_RGB332:
443 case TBM_FORMAT_BGR233:
444 case TBM_FORMAT_XRGB4444:
445 case TBM_FORMAT_XBGR4444:
446 case TBM_FORMAT_RGBX4444:
447 case TBM_FORMAT_BGRX4444:
448 case TBM_FORMAT_ARGB4444:
449 case TBM_FORMAT_ABGR4444:
450 case TBM_FORMAT_RGBA4444:
451 case TBM_FORMAT_BGRA4444:
452 case TBM_FORMAT_XRGB1555:
453 case TBM_FORMAT_XBGR1555:
454 case TBM_FORMAT_RGBX5551:
455 case TBM_FORMAT_BGRX5551:
456 case TBM_FORMAT_ARGB1555:
457 case TBM_FORMAT_ABGR1555:
458 case TBM_FORMAT_RGBA5551:
459 case TBM_FORMAT_BGRA5551:
460 case TBM_FORMAT_RGB565:
461 case TBM_FORMAT_BGR565:
462 case TBM_FORMAT_RGB888:
463 case TBM_FORMAT_BGR888:
464 case TBM_FORMAT_XRGB8888:
465 case TBM_FORMAT_XBGR8888:
466 case TBM_FORMAT_RGBX8888:
467 case TBM_FORMAT_BGRX8888:
468 case TBM_FORMAT_ARGB8888:
469 case TBM_FORMAT_ABGR8888:
470 case TBM_FORMAT_RGBA8888:
471 case TBM_FORMAT_BGRA8888:
472 case TBM_FORMAT_XRGB2101010:
473 case TBM_FORMAT_XBGR2101010:
474 case TBM_FORMAT_RGBX1010102:
475 case TBM_FORMAT_BGRX1010102:
476 case TBM_FORMAT_ARGB2101010:
477 case TBM_FORMAT_ABGR2101010:
478 case TBM_FORMAT_RGBA1010102:
479 case TBM_FORMAT_BGRA1010102:
480 case TBM_FORMAT_YUYV:
481 case TBM_FORMAT_YVYU:
482 case TBM_FORMAT_UYVY:
483 case TBM_FORMAT_VYUY:
484 case TBM_FORMAT_AYUV:
487 case TBM_FORMAT_NV12:
488 case TBM_FORMAT_NV12MT:
489 case TBM_FORMAT_NV21:
490 case TBM_FORMAT_NV16:
491 case TBM_FORMAT_NV61:
494 case TBM_FORMAT_YUV410:
495 case TBM_FORMAT_YVU410:
496 case TBM_FORMAT_YUV411:
497 case TBM_FORMAT_YVU411:
498 case TBM_FORMAT_YUV420:
499 case TBM_FORMAT_YVU420:
500 case TBM_FORMAT_YUV422:
501 case TBM_FORMAT_YVU422:
502 case TBM_FORMAT_YUV444:
503 case TBM_FORMAT_YVU444:
511 TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
517 tbm_surface_internal_get_bpp(tbm_format format)
524 case TBM_FORMAT_RGB332:
525 case TBM_FORMAT_BGR233:
528 case TBM_FORMAT_XRGB4444:
529 case TBM_FORMAT_XBGR4444:
530 case TBM_FORMAT_RGBX4444:
531 case TBM_FORMAT_BGRX4444:
532 case TBM_FORMAT_ARGB4444:
533 case TBM_FORMAT_ABGR4444:
534 case TBM_FORMAT_RGBA4444:
535 case TBM_FORMAT_BGRA4444:
536 case TBM_FORMAT_XRGB1555:
537 case TBM_FORMAT_XBGR1555:
538 case TBM_FORMAT_RGBX5551:
539 case TBM_FORMAT_BGRX5551:
540 case TBM_FORMAT_ARGB1555:
541 case TBM_FORMAT_ABGR1555:
542 case TBM_FORMAT_RGBA5551:
543 case TBM_FORMAT_BGRA5551:
544 case TBM_FORMAT_RGB565:
545 case TBM_FORMAT_BGR565:
548 case TBM_FORMAT_RGB888:
549 case TBM_FORMAT_BGR888:
552 case TBM_FORMAT_XRGB8888:
553 case TBM_FORMAT_XBGR8888:
554 case TBM_FORMAT_RGBX8888:
555 case TBM_FORMAT_BGRX8888:
556 case TBM_FORMAT_ARGB8888:
557 case TBM_FORMAT_ABGR8888:
558 case TBM_FORMAT_RGBA8888:
559 case TBM_FORMAT_BGRA8888:
560 case TBM_FORMAT_XRGB2101010:
561 case TBM_FORMAT_XBGR2101010:
562 case TBM_FORMAT_RGBX1010102:
563 case TBM_FORMAT_BGRX1010102:
564 case TBM_FORMAT_ARGB2101010:
565 case TBM_FORMAT_ABGR2101010:
566 case TBM_FORMAT_RGBA1010102:
567 case TBM_FORMAT_BGRA1010102:
568 case TBM_FORMAT_YUYV:
569 case TBM_FORMAT_YVYU:
570 case TBM_FORMAT_UYVY:
571 case TBM_FORMAT_VYUY:
572 case TBM_FORMAT_AYUV:
575 case TBM_FORMAT_NV12:
576 case TBM_FORMAT_NV12MT:
577 case TBM_FORMAT_NV21:
580 case TBM_FORMAT_NV16:
581 case TBM_FORMAT_NV61:
584 case TBM_FORMAT_YUV410:
585 case TBM_FORMAT_YVU410:
588 case TBM_FORMAT_YUV411:
589 case TBM_FORMAT_YVU411:
590 case TBM_FORMAT_YUV420:
591 case TBM_FORMAT_YVU420:
594 case TBM_FORMAT_YUV422:
595 case TBM_FORMAT_YVU422:
598 case TBM_FORMAT_YUV444:
599 case TBM_FORMAT_YVU444:
606 TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
612 tbm_surface_internal_create_with_flags(int width, int height,
613 int format, int flags)
615 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
616 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
618 struct _tbm_bufmgr *mgr;
619 struct _tbm_surface *surf = NULL;
623 uint32_t bo_size = 0;
626 bool bufmgr_initialized = false;
628 _tbm_surface_mutex_lock();
630 if (!g_surface_bufmgr) {
631 _init_surface_bufmgr();
632 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
633 bufmgr_initialized = true;
636 mgr = g_surface_bufmgr;
637 if (!TBM_BUFMGR_IS_VALID(mgr)) {
638 TBM_LOG_E("The bufmgr is invalid\n");
639 goto check_valid_fail;
642 surf = calloc(1, sizeof(struct _tbm_surface));
644 TBM_LOG_E("fail to alloc surf\n");
645 goto alloc_surf_fail;
649 surf->info.width = width;
650 surf->info.height = height;
651 surf->info.format = format;
652 surf->info.bpp = tbm_surface_internal_get_bpp(format);
653 surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
656 /* get size, stride and offset bo_idx */
657 for (i = 0; i < surf->info.num_planes; i++) {
658 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
659 &offset, &stride, &bo_idx)) {
660 TBM_LOG_E("fail to query plane data\n");
661 goto query_plane_data_fail;
664 surf->info.planes[i].size = size;
665 surf->info.planes[i].offset = offset;
666 surf->info.planes[i].stride = stride;
667 surf->planes_bo_idx[i] = bo_idx;
672 for (i = 0; i < surf->info.num_planes; i++) {
673 surf->info.size += surf->info.planes[i].size;
675 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
676 surf->num_bos = surf->planes_bo_idx[i] + 1;
681 for (i = 0; i < surf->num_bos; i++) {
683 for (j = 0; j < surf->info.num_planes; j++) {
684 if (surf->planes_bo_idx[j] == i)
685 bo_size += surf->info.planes[j].size;
688 if (mgr->backend->surface_bo_alloc) {
689 /* LCOV_EXCL_START */
691 void *bo_priv = NULL;
693 bo = calloc(1, sizeof(struct _tbm_bo));
695 TBM_LOG_E("fail to alloc bo struct\n");
699 bo->bufmgr = surf->bufmgr;
701 pthread_mutex_lock(&surf->bufmgr->lock);
703 bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
705 TBM_LOG_E("fail to alloc bo priv\n");
707 pthread_mutex_unlock(&surf->bufmgr->lock);
715 LIST_INITHEAD(&bo->user_data_list);
717 LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
719 pthread_mutex_unlock(&surf->bufmgr->lock);
724 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
726 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
731 _tbm_bo_set_surface(surf->bos[i], surf);
734 TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
735 _tbm_surface_internal_format_to_str(format), flags, surf);
737 LIST_INITHEAD(&surf->user_data_list);
738 LIST_INITHEAD(&surf->debug_data_list);
740 LIST_ADD(&surf->item_link, &mgr->surf_list);
742 _tbm_surface_mutex_unlock();
747 for (j = 0; j < i; j++) {
749 tbm_bo_unref(surf->bos[j]);
751 query_plane_data_fail:
755 if (bufmgr_initialized && mgr) {
756 LIST_DELINIT(&mgr->surf_list);
757 _deinit_surface_bufmgr();
759 _tbm_surface_mutex_unlock();
761 TBM_LOG_E("error: width(%d) height(%d) format(%s) flags(%d)\n",
763 _tbm_surface_internal_format_to_str(format), flags);
769 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
770 tbm_bo *bos, int num)
772 TBM_RETURN_VAL_IF_FAIL(bos, NULL);
773 TBM_RETURN_VAL_IF_FAIL(info, NULL);
774 TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
776 struct _tbm_bufmgr *mgr;
777 struct _tbm_surface *surf = NULL;
779 bool bufmgr_initialized = false;
781 _tbm_surface_mutex_lock();
783 if (!g_surface_bufmgr) {
784 _init_surface_bufmgr();
785 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
786 bufmgr_initialized = true;
789 mgr = g_surface_bufmgr;
790 if (!TBM_BUFMGR_IS_VALID(mgr)) {
791 TBM_LOG_E("fail to validate the Bufmgr.\n");
792 goto check_valid_fail;
795 surf = calloc(1, sizeof(struct _tbm_surface));
797 TBM_LOG_E("fail to allocate struct _tbm_surface.\n");
798 goto alloc_surf_fail;
802 surf->info.width = info->width;
803 surf->info.height = info->height;
804 surf->info.format = info->format;
806 surf->info.bpp = info->bpp;
808 surf->info.bpp = tbm_surface_internal_get_bpp(info->format);
809 surf->info.num_planes = info->num_planes;
812 /* get size, stride and offset */
813 for (i = 0; i < info->num_planes; i++) {
814 surf->info.planes[i].offset = info->planes[i].offset;
815 surf->info.planes[i].stride = info->planes[i].stride;
817 if (info->planes[i].size > 0)
818 surf->info.planes[i].size = info->planes[i].size;
820 uint32_t size = 0, offset = 0, stride = 0;
823 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx);
824 surf->info.planes[i].size = size;
828 surf->planes_bo_idx[i] = 0;
830 surf->planes_bo_idx[i] = i;
833 if (info->size > 0) {
834 surf->info.size = info->size;
837 for (i = 0; i < info->num_planes; i++)
838 surf->info.size += surf->info.planes[i].size;
841 surf->flags = TBM_BO_DEFAULT;
843 /* create only one bo */
845 for (i = 0; i < num; i++) {
846 if (bos[i] == NULL) {
847 TBM_LOG_E("bos[%d] is null.\n", i);
851 surf->bos[i] = tbm_bo_ref(bos[i]);
852 _tbm_bo_set_surface(bos[i], surf);
855 TBM_TRACE("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
856 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
858 LIST_INITHEAD(&surf->user_data_list);
859 LIST_INITHEAD(&surf->debug_data_list);
861 LIST_ADD(&surf->item_link, &mgr->surf_list);
863 _tbm_surface_mutex_unlock();
868 for (i = 0; i < num; i++) {
870 tbm_bo_unref(surf->bos[i]);
875 if (bufmgr_initialized && mgr) {
876 LIST_DELINIT(&mgr->surf_list);
877 _deinit_surface_bufmgr();
879 _tbm_surface_mutex_unlock();
881 TBM_LOG_E("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
882 info->width, info->height,
883 _tbm_surface_internal_format_to_str(info->format), num);
889 tbm_surface_internal_destroy(tbm_surface_h surface)
891 _tbm_surface_mutex_lock();
893 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
897 if (surface->refcnt > 0) {
898 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
899 _tbm_surface_mutex_unlock();
903 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
905 if (surface->refcnt == 0)
906 _tbm_surface_internal_destroy(surface);
908 _tbm_surface_mutex_unlock();
912 tbm_surface_internal_ref(tbm_surface_h surface)
914 _tbm_surface_mutex_lock();
916 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
920 TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
922 _tbm_surface_mutex_unlock();
926 tbm_surface_internal_unref(tbm_surface_h surface)
928 _tbm_surface_mutex_lock();
930 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
934 if (surface->refcnt > 0) {
935 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
936 _tbm_surface_mutex_unlock();
940 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
942 if (surface->refcnt == 0)
943 _tbm_surface_internal_destroy(surface);
945 _tbm_surface_mutex_unlock();
949 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
951 struct _tbm_surface *surf;
954 _tbm_surface_mutex_lock();
956 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
958 surf = (struct _tbm_surface *)surface;
961 TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
963 _tbm_surface_mutex_unlock();
969 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
971 struct _tbm_surface *surf;
974 _tbm_surface_mutex_lock();
976 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
977 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
979 surf = (struct _tbm_surface *)surface;
980 bo = surf->bos[bo_idx];
982 TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
984 _tbm_surface_mutex_unlock();
990 tbm_surface_internal_get_size(tbm_surface_h surface)
992 struct _tbm_surface *surf;
995 _tbm_surface_mutex_lock();
997 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
999 surf = (struct _tbm_surface *)surface;
1000 size = surf->info.size;
1002 TBM_TRACE("tbm_surface(%p) size(%u)\n", surface, size);
1004 _tbm_surface_mutex_unlock();
1010 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1011 uint32_t *size, uint32_t *offset, uint32_t *pitch)
1013 struct _tbm_surface *surf;
1015 _tbm_surface_mutex_lock();
1017 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1018 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1020 surf = (struct _tbm_surface *)surface;
1022 if (plane_idx >= surf->info.num_planes) {
1023 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1024 _tbm_surface_mutex_unlock();
1029 *size = surf->info.planes[plane_idx].size;
1032 *offset = surf->info.planes[plane_idx].offset;
1035 *pitch = surf->info.planes[plane_idx].stride;
1037 TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1038 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1039 surf->info.planes[plane_idx].stride);
1041 _tbm_surface_mutex_unlock();
1047 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1048 tbm_surface_info_s *info, int map)
1050 struct _tbm_surface *surf;
1051 tbm_bo_handle bo_handles[4];
1054 _tbm_surface_mutex_lock();
1056 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1058 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1060 surf = (struct _tbm_surface *)surface;
1062 memset(info, 0x00, sizeof(tbm_surface_info_s));
1063 info->width = surf->info.width;
1064 info->height = surf->info.height;
1065 info->format = surf->info.format;
1066 info->bpp = surf->info.bpp;
1067 info->size = surf->info.size;
1068 info->num_planes = surf->info.num_planes;
1071 for (i = 0; i < surf->num_bos; i++) {
1072 _tbm_surface_mutex_unlock();
1073 bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1074 _tbm_surface_mutex_lock();
1075 if (bo_handles[i].ptr == NULL) {
1076 for (j = 0; j < i; j++)
1077 tbm_bo_unmap(surf->bos[j]);
1079 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1080 _tbm_surface_mutex_unlock();
1085 for (i = 0; i < surf->num_bos; i++) {
1086 bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1087 if (bo_handles[i].ptr == NULL) {
1088 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1089 _tbm_surface_mutex_unlock();
1095 for (i = 0; i < surf->info.num_planes; i++) {
1096 info->planes[i].size = surf->info.planes[i].size;
1097 info->planes[i].offset = surf->info.planes[i].offset;
1098 info->planes[i].stride = surf->info.planes[i].stride;
1100 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1101 info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1102 surf->info.planes[i].offset;
1105 TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1107 _tbm_surface_mutex_unlock();
1113 tbm_surface_internal_unmap(tbm_surface_h surface)
1115 struct _tbm_surface *surf;
1118 _tbm_surface_mutex_lock();
1120 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1122 surf = (struct _tbm_surface *)surface;
1124 for (i = 0; i < surf->num_bos; i++)
1125 tbm_bo_unmap(surf->bos[i]);
1127 TBM_TRACE("tbm_surface(%p)\n", surface);
1129 _tbm_surface_mutex_unlock();
1133 tbm_surface_internal_get_width(tbm_surface_h surface)
1135 struct _tbm_surface *surf;
1138 _tbm_surface_mutex_lock();
1140 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1142 surf = (struct _tbm_surface *)surface;
1143 width = surf->info.width;
1145 TBM_TRACE("tbm_surface(%p) width(%u)\n", surface, width);
1147 _tbm_surface_mutex_unlock();
1153 tbm_surface_internal_get_height(tbm_surface_h surface)
1155 struct _tbm_surface *surf;
1156 unsigned int height;
1158 _tbm_surface_mutex_lock();
1160 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1162 surf = (struct _tbm_surface *)surface;
1163 height = surf->info.height;
1165 TBM_TRACE("tbm_surface(%p) height(%u)\n", surface, height);
1167 _tbm_surface_mutex_unlock();
1174 tbm_surface_internal_get_format(tbm_surface_h surface)
1176 struct _tbm_surface *surf;
1179 _tbm_surface_mutex_lock();
1181 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1183 surf = (struct _tbm_surface *)surface;
1184 format = surf->info.format;
1186 TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1188 _tbm_surface_mutex_unlock();
1194 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1196 struct _tbm_surface *surf;
1199 _tbm_surface_mutex_lock();
1201 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1202 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1204 surf = (struct _tbm_surface *)surface;
1205 bo_idx = surf->planes_bo_idx[plane_idx];
1207 TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1209 _tbm_surface_mutex_unlock();
1215 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1216 tbm_data_free data_free_func)
1218 tbm_user_data *data;
1220 _tbm_surface_mutex_lock();
1222 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1224 /* check if the data according to the key exist if so, return false. */
1225 data = user_data_lookup(&surface->user_data_list, key);
1227 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1228 _tbm_surface_mutex_unlock();
1232 data = user_data_create(key, data_free_func);
1234 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1235 _tbm_surface_mutex_unlock();
1239 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1241 LIST_ADD(&data->item_link, &surface->user_data_list);
1243 _tbm_surface_mutex_unlock();
1249 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1252 tbm_user_data *old_data;
1254 _tbm_surface_mutex_lock();
1256 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1258 old_data = user_data_lookup(&surface->user_data_list, key);
1260 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1261 _tbm_surface_mutex_unlock();
1265 if (old_data->data && old_data->free_func)
1266 old_data->free_func(old_data->data);
1268 old_data->data = data;
1270 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1272 _tbm_surface_mutex_unlock();
1278 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1281 tbm_user_data *old_data;
1283 _tbm_surface_mutex_lock();
1285 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1288 TBM_LOG_E("error: tbm_surface(%p) key(%lu)\n", surface, key);
1289 _tbm_surface_mutex_unlock();
1294 old_data = user_data_lookup(&surface->user_data_list, key);
1296 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1297 _tbm_surface_mutex_unlock();
1301 *data = old_data->data;
1303 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1305 _tbm_surface_mutex_unlock();
1311 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1314 tbm_user_data *old_data = (void *)0;
1316 _tbm_surface_mutex_lock();
1318 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1320 old_data = user_data_lookup(&surface->user_data_list, key);
1322 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1323 _tbm_surface_mutex_unlock();
1327 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1329 user_data_delete(old_data);
1331 _tbm_surface_mutex_unlock();
1336 /* LCOV_EXCL_START */
1338 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1340 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1342 return surface->debug_pid;
1346 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1348 _tbm_surface_mutex_lock();
1350 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1352 surface->debug_pid = pid;
1354 _tbm_surface_mutex_unlock();
1357 static tbm_surface_debug_data *
1358 _tbm_surface_internal_debug_data_create(char *key, char *value)
1360 tbm_surface_debug_data *debug_data = NULL;
1362 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1366 if (key) debug_data->key = strdup(key);
1367 if (value) debug_data->value = strdup(value);
1373 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1375 tbm_surface_debug_data *debug_data = NULL;
1376 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1377 tbm_bufmgr bufmgr = NULL;
1379 _tbm_surface_mutex_lock();
1381 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1382 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1384 bufmgr = surface->bufmgr;
1386 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1388 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1389 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1391 if (!strcmp(old_data->key, key)) {
1392 if (old_data->value && value && !strncmp(old_data->value, value, strlen(old_data->value))) {
1393 TBM_TRACE("tbm_surface(%p) Already exist key(%s) and value(%s)!\n", surface, key, value);
1394 goto add_debug_key_list;
1397 if (old_data->value)
1398 free(old_data->value);
1401 old_data->value = strdup(value);
1403 old_data->value = NULL;
1405 goto add_debug_key_list;
1411 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1413 TBM_LOG_E("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1414 _tbm_surface_mutex_unlock();
1418 TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1420 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1423 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1424 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1425 if (!strcmp(old_data->key, key)) {
1426 _tbm_surface_mutex_unlock();
1432 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1433 LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1435 _tbm_surface_mutex_unlock();
1441 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1443 tbm_surface_debug_data *old_data = NULL;
1445 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1447 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1448 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1449 if (!strcmp(old_data->key, key))
1450 return old_data->value;
1457 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1458 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1460 struct _tbm_surface_dump_buf_info {
1470 tbm_surface_info_s info;
1472 struct list_head link;
1475 struct _tbm_surface_dump_info {
1476 char *path; // copy???
1479 struct list_head *link;
1480 struct list_head surface_list; /* link of surface */
1483 static tbm_surface_dump_info *g_dump_info = NULL;
1484 static const char *dump_postfix[2] = {"png", "yuv"};
1487 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1488 void *data2, int size2, void *data3, int size3)
1490 FILE *fp = fopen(file, "w+");
1491 TBM_RETURN_IF_FAIL(fp != NULL);
1492 unsigned int *blocks;
1494 blocks = (unsigned int *)data1;
1495 fwrite(blocks, 1, size1, fp);
1498 blocks = (unsigned int *)data2;
1499 fwrite(blocks, 1, size2, fp);
1503 blocks = (unsigned int *)data3;
1504 fwrite(blocks, 1, size3, fp);
1511 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height)
1513 unsigned int *blocks = (unsigned int *)data;
1514 FILE *fp = fopen(file, "wb");
1515 TBM_RETURN_IF_FAIL(fp != NULL);
1516 const int pixel_size = 4; // RGBA
1517 png_bytep *row_pointers;
1520 png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1523 TBM_LOG_E("fail to create a png write structure.\n");
1528 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1530 TBM_LOG_E("fail to create a png info structure.\n");
1531 png_destroy_write_struct(&pPngStruct, NULL);
1536 png_init_io(pPngStruct, fp);
1537 png_set_IHDR(pPngStruct,
1542 PNG_COLOR_TYPE_RGBA,
1544 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1546 png_set_bgr(pPngStruct);
1547 png_write_info(pPngStruct, pPngInfo);
1549 row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1550 if (!row_pointers) {
1551 TBM_LOG_E("fail to allocate the png row_pointers.\n");
1552 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1557 for (y = 0; y < height; ++y) {
1561 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1563 TBM_LOG_E("fail to allocate the png row.\n");
1564 for (x = 0; x < y; x++)
1565 png_free(pPngStruct, row_pointers[x]);
1566 png_free(pPngStruct, row_pointers);
1567 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1571 row_pointers[y] = (png_bytep)row;
1573 for (x = 0; x < width; ++x) {
1574 unsigned int curBlock = blocks[y * width + x];
1576 row[x * pixel_size] = (curBlock & 0xFF);
1577 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1578 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1579 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1583 png_write_image(pPngStruct, row_pointers);
1584 png_write_end(pPngStruct, pPngInfo);
1586 for (y = 0; y < height; y++)
1587 png_free(pPngStruct, row_pointers[y]);
1588 png_free(pPngStruct, row_pointers);
1590 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1596 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1598 TBM_RETURN_IF_FAIL(path != NULL);
1599 TBM_RETURN_IF_FAIL(w > 0);
1600 TBM_RETURN_IF_FAIL(h > 0);
1601 TBM_RETURN_IF_FAIL(count > 0);
1603 tbm_surface_dump_buf_info *buf_info = NULL;
1604 tbm_surface_h tbm_surface;
1605 tbm_surface_info_s info;
1610 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1614 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1615 TBM_RETURN_IF_FAIL(g_dump_info);
1617 LIST_INITHEAD(&g_dump_info->surface_list);
1618 g_dump_info->count = 0;
1619 g_dump_info->dump_max = count;
1621 /* get buffer size */
1622 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1623 if (tbm_surface == NULL) {
1624 TBM_LOG_E("tbm_surface_create fail\n");
1630 if (TBM_SURFACE_ERROR_NONE != tbm_surface_map(tbm_surface,
1631 TBM_SURF_OPTION_READ, &info)) {
1632 TBM_LOG_E("tbm_surface_map fail\n");
1633 tbm_surface_destroy(tbm_surface);
1638 buffer_size = info.planes[0].stride * h;
1640 tbm_surface_unmap(tbm_surface);
1641 tbm_surface_destroy(tbm_surface);
1643 /* create dump lists */
1644 for (i = 0; i < count; i++) {
1647 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1648 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1650 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1652 TBM_LOG_E("fail to allocate the tbm_bo[%d]\n", i);
1657 buf_info->index = i;
1659 buf_info->size = buffer_size;
1661 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1664 g_dump_info->path = path;
1665 g_dump_info->link = &g_dump_info->surface_list;
1667 TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1672 /* free resources */
1673 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1674 tbm_surface_dump_buf_info *tmp;
1676 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1677 tbm_bo_unref(buf_info->bo);
1678 LIST_DEL(&buf_info->link);
1683 TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1692 tbm_surface_internal_dump_end(void)
1694 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1695 tbm_bo_handle bo_handle;
1700 if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1707 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1710 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1711 if (bo_handle.ptr == NULL) {
1712 tbm_bo_unref(buf_info->bo);
1713 LIST_DEL(&buf_info->link);
1718 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1719 TBM_LOG_I("Dump File.. %s generated.\n", file);
1721 if (buf_info->dirty) {
1722 void *ptr1 = NULL, *ptr2 = NULL;
1724 switch (buf_info->info.format) {
1725 case TBM_FORMAT_ARGB8888:
1726 case TBM_FORMAT_XRGB8888:
1727 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1728 buf_info->info.planes[0].stride >> 2,
1729 buf_info->info.height);
1731 case TBM_FORMAT_YVU420:
1732 case TBM_FORMAT_YUV420:
1733 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1734 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1735 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1736 buf_info->info.planes[0].stride * buf_info->info.height,
1738 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1740 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1742 case TBM_FORMAT_NV12:
1743 case TBM_FORMAT_NV21:
1744 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1745 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1746 buf_info->info.planes[0].stride * buf_info->info.height,
1748 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1751 case TBM_FORMAT_YUYV:
1752 case TBM_FORMAT_UYVY:
1753 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1754 buf_info->info.planes[0].stride * buf_info->info.height,
1758 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1761 } else if (buf_info->dirty_shm)
1762 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1763 buf_info->shm_stride >> 2,
1766 tbm_bo_unmap(buf_info->bo);
1767 tbm_bo_unref(buf_info->bo);
1768 LIST_DEL(&buf_info->link);
1775 TBM_LOG_I("Dump End..\n");
1779 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1781 TBM_RETURN_IF_FAIL(surface != NULL);
1782 TBM_RETURN_IF_FAIL(type != NULL);
1784 tbm_surface_dump_buf_info *buf_info;
1785 struct list_head *next_link;
1786 tbm_surface_info_s info;
1787 tbm_bo_handle bo_handle;
1788 const char *postfix;
1794 next_link = g_dump_info->link->next;
1795 TBM_RETURN_IF_FAIL(next_link != NULL);
1797 if (next_link == &g_dump_info->surface_list) {
1798 next_link = next_link->next;
1799 TBM_RETURN_IF_FAIL(next_link != NULL);
1802 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1803 TBM_RETURN_IF_FAIL(buf_info != NULL);
1805 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1806 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1808 if (info.size > buf_info->size) {
1809 TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1810 info.size, buf_info->size);
1811 tbm_surface_unmap(surface);
1815 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1816 postfix = dump_postfix[0];
1818 postfix = dump_postfix[1];
1820 /* make the file information */
1821 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1824 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1825 if (!bo_handle.ptr) {
1826 TBM_LOG_E("fail to map bo");
1827 tbm_surface_unmap(surface);
1830 memset(bo_handle.ptr, 0x00, buf_info->size);
1832 switch (info.format) {
1833 case TBM_FORMAT_ARGB8888:
1834 case TBM_FORMAT_XRGB8888:
1835 snprintf(buf_info->name, sizeof(buf_info->name),
1836 "%10.3f_%03d_%p-%s.%s",
1837 _tbm_surface_internal_get_time(),
1838 g_dump_info->count++, surface, type, postfix);
1839 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1841 case TBM_FORMAT_YVU420:
1842 case TBM_FORMAT_YUV420:
1843 snprintf(buf_info->name, sizeof(buf_info->name),
1844 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1845 _tbm_surface_internal_get_time(),
1846 g_dump_info->count++, type, info.planes[0].stride,
1847 info.height, FOURCC_STR(info.format), postfix);
1848 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1849 bo_handle.ptr += info.planes[0].stride * info.height;
1850 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1851 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1852 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1854 case TBM_FORMAT_NV12:
1855 case TBM_FORMAT_NV21:
1856 snprintf(buf_info->name, sizeof(buf_info->name),
1857 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1858 _tbm_surface_internal_get_time(),
1859 g_dump_info->count++, type, info.planes[0].stride,
1860 info.height, FOURCC_STR(info.format), postfix);
1861 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1862 bo_handle.ptr += info.planes[0].stride * info.height;
1863 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1865 case TBM_FORMAT_YUYV:
1866 case TBM_FORMAT_UYVY:
1867 snprintf(buf_info->name, sizeof(buf_info->name),
1868 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1869 _tbm_surface_internal_get_time(),
1870 g_dump_info->count++, type, info.planes[0].stride,
1871 info.height, FOURCC_STR(info.format), postfix);
1872 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1875 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1876 tbm_bo_unmap(buf_info->bo);
1877 tbm_surface_unmap(surface);
1881 tbm_bo_unmap(buf_info->bo);
1883 tbm_surface_unmap(surface);
1885 buf_info->dirty = 1;
1886 buf_info->dirty_shm = 0;
1888 if (g_dump_info->count == 1000)
1889 g_dump_info->count = 0;
1891 g_dump_info->link = next_link;
1893 TBM_LOG_I("Dump %s \n", buf_info->name);
1896 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
1899 TBM_RETURN_IF_FAIL(ptr != NULL);
1900 TBM_RETURN_IF_FAIL(w > 0);
1901 TBM_RETURN_IF_FAIL(h > 0);
1902 TBM_RETURN_IF_FAIL(stride > 0);
1903 TBM_RETURN_IF_FAIL(type != NULL);
1905 tbm_surface_dump_buf_info *buf_info;
1906 struct list_head *next_link;
1907 tbm_bo_handle bo_handle;
1913 next_link = g_dump_info->link->next;
1914 TBM_RETURN_IF_FAIL(next_link != NULL);
1916 if (next_link == &g_dump_info->surface_list) {
1917 next_link = next_link->next;
1918 TBM_RETURN_IF_FAIL(next_link != NULL);
1921 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1922 TBM_RETURN_IF_FAIL(buf_info != NULL);
1925 if (size > buf_info->size) {
1926 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
1927 size, buf_info->size);
1932 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1933 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1935 memset(bo_handle.ptr, 0x00, buf_info->size);
1936 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1938 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1939 _tbm_surface_internal_get_time(),
1940 g_dump_info->count++, type, dump_postfix[0]);
1941 memcpy(bo_handle.ptr, ptr, size);
1943 tbm_bo_unmap(buf_info->bo);
1945 buf_info->dirty = 0;
1946 buf_info->dirty_shm = 1;
1947 buf_info->shm_stride = stride;
1948 buf_info->shm_h = h;
1950 if (g_dump_info->count == 1000)
1951 g_dump_info->count = 0;
1953 g_dump_info->link = next_link;
1955 TBM_LOG_I("Dump %s \n", buf_info->name);
1959 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
1961 TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
1962 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1963 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
1965 tbm_surface_info_s info;
1966 const char *postfix;
1970 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1971 TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
1973 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1974 postfix = dump_postfix[0];
1976 postfix = dump_postfix[1];
1978 if (strcmp(postfix, type)) {
1979 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
1980 tbm_surface_unmap(surface);
1984 snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
1986 if (!access(file, 0)) {
1987 TBM_LOG_E("can't capture buffer, exist file %s", file);
1988 tbm_surface_unmap(surface);
1992 switch (info.format) {
1993 case TBM_FORMAT_ARGB8888:
1994 case TBM_FORMAT_XRGB8888:
1995 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
1996 info.planes[0].stride >> 2,
1999 case TBM_FORMAT_YVU420:
2000 case TBM_FORMAT_YUV420:
2001 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2002 info.planes[0].stride * info.height,
2004 info.planes[1].stride * (info.height >> 1),
2006 info.planes[2].stride * (info.height >> 1));
2008 case TBM_FORMAT_NV12:
2009 case TBM_FORMAT_NV21:
2010 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2011 info.planes[0].stride * info.height,
2013 info.planes[1].stride * (info.height >> 1),
2016 case TBM_FORMAT_YUYV:
2017 case TBM_FORMAT_UYVY:
2018 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2019 info.planes[0].stride * info.height,
2023 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2024 tbm_surface_unmap(surface);
2028 tbm_surface_unmap(surface);
2030 TBM_LOG_I("Capture %s \n", file);
2036 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2037 const char *path, const char *name, const char *type)
2039 TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2040 TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2041 TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2042 TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2043 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2044 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2048 if (strcmp(dump_postfix[0], type)) {
2049 TBM_LOG_E("Not supported type:%s'", type);
2053 if (!access(file, 0)) {
2054 TBM_LOG_E("can't capture buffer, exist file %s", file);
2058 snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2060 _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2062 TBM_LOG_I("Capture %s \n", file);