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: tbm_surface mutex init\n");
235 tbm_surface_mutex_init = true;
241 _tbm_surface_mutex_lock(void)
243 if (!_tbm_surface_mutex_init())
246 pthread_mutex_lock(&tbm_surface_lock);
250 _tbm_surface_mutex_unlock(void)
252 pthread_mutex_unlock(&tbm_surface_lock);
256 _init_surface_bufmgr(void)
258 g_surface_bufmgr = tbm_bufmgr_init(-1);
262 _deinit_surface_bufmgr(void)
264 if (!g_surface_bufmgr)
267 tbm_bufmgr_deinit(g_surface_bufmgr);
268 g_surface_bufmgr = NULL;
272 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
273 int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
275 TBM_RETURN_VAL_IF_FAIL(surface, 0);
276 TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
278 struct _tbm_surface *surf = (struct _tbm_surface *)surface;
279 struct _tbm_bufmgr *mgr = surf->bufmgr;
282 TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
283 TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
284 TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
285 TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
287 if (!mgr->backend->surface_get_plane_data)
290 ret = mgr->backend->surface_get_plane_data(surf->info.width,
291 surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
299 _tbm_surface_internal_destroy(tbm_surface_h surface)
302 tbm_bufmgr bufmgr = surface->bufmgr;
303 tbm_user_data *old_data = NULL, *tmp = NULL;
304 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
306 /* destory the user_data_list */
307 if (!LIST_IS_EMPTY(&surface->user_data_list)) {
308 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
309 TBM_DBG("free user_data\n");
310 user_data_delete(old_data);
314 for (i = 0; i < surface->num_bos; i++) {
315 surface->bos[i]->surface = NULL;
317 tbm_bo_unref(surface->bos[i]);
318 surface->bos[i] = NULL;
321 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
322 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
323 _tbm_surface_internal_debug_data_delete(debug_old_data);
326 LIST_DEL(&surface->item_link);
331 if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
332 LIST_DELINIT(&bufmgr->surf_list);
334 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
335 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
336 _tbm_surface_internal_debug_data_delete(debug_old_data);
340 _deinit_surface_bufmgr();
345 tbm_surface_internal_is_valid(tbm_surface_h surface)
347 tbm_surface_h old_data = NULL;
349 if (surface == NULL || g_surface_bufmgr == NULL) {
350 TBM_TRACE("error: tbm_surface(%p)\n", surface);
354 if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
355 LIST_FOR_EACH_ENTRY(old_data, &g_surface_bufmgr->surf_list, item_link) {
356 if (old_data == surface) {
357 TBM_TRACE("tbm_surface(%p)\n", surface);
362 TBM_TRACE("error: tbm_surface(%p)\n", surface);
367 tbm_surface_internal_query_supported_formats(uint32_t **formats,
370 struct _tbm_bufmgr *mgr;
372 bool bufmgr_initialized = false;
374 _tbm_surface_mutex_lock();
376 if (!g_surface_bufmgr) {
377 _init_surface_bufmgr();
378 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
379 bufmgr_initialized = true;
382 mgr = g_surface_bufmgr;
384 if (!mgr->backend->surface_supported_format)
387 ret = mgr->backend->surface_supported_format(formats, num);
391 TBM_TRACE("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
393 _tbm_surface_mutex_unlock();
398 if (bufmgr_initialized) {
399 LIST_DELINIT(&g_surface_bufmgr->surf_list);
400 _deinit_surface_bufmgr();
402 _tbm_surface_mutex_unlock();
403 TBM_TRACE("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
408 tbm_surface_internal_get_num_planes(tbm_format format)
414 case TBM_FORMAT_RGB332:
415 case TBM_FORMAT_BGR233:
416 case TBM_FORMAT_XRGB4444:
417 case TBM_FORMAT_XBGR4444:
418 case TBM_FORMAT_RGBX4444:
419 case TBM_FORMAT_BGRX4444:
420 case TBM_FORMAT_ARGB4444:
421 case TBM_FORMAT_ABGR4444:
422 case TBM_FORMAT_RGBA4444:
423 case TBM_FORMAT_BGRA4444:
424 case TBM_FORMAT_XRGB1555:
425 case TBM_FORMAT_XBGR1555:
426 case TBM_FORMAT_RGBX5551:
427 case TBM_FORMAT_BGRX5551:
428 case TBM_FORMAT_ARGB1555:
429 case TBM_FORMAT_ABGR1555:
430 case TBM_FORMAT_RGBA5551:
431 case TBM_FORMAT_BGRA5551:
432 case TBM_FORMAT_RGB565:
433 case TBM_FORMAT_BGR565:
434 case TBM_FORMAT_RGB888:
435 case TBM_FORMAT_BGR888:
436 case TBM_FORMAT_XRGB8888:
437 case TBM_FORMAT_XBGR8888:
438 case TBM_FORMAT_RGBX8888:
439 case TBM_FORMAT_BGRX8888:
440 case TBM_FORMAT_ARGB8888:
441 case TBM_FORMAT_ABGR8888:
442 case TBM_FORMAT_RGBA8888:
443 case TBM_FORMAT_BGRA8888:
444 case TBM_FORMAT_XRGB2101010:
445 case TBM_FORMAT_XBGR2101010:
446 case TBM_FORMAT_RGBX1010102:
447 case TBM_FORMAT_BGRX1010102:
448 case TBM_FORMAT_ARGB2101010:
449 case TBM_FORMAT_ABGR2101010:
450 case TBM_FORMAT_RGBA1010102:
451 case TBM_FORMAT_BGRA1010102:
452 case TBM_FORMAT_YUYV:
453 case TBM_FORMAT_YVYU:
454 case TBM_FORMAT_UYVY:
455 case TBM_FORMAT_VYUY:
456 case TBM_FORMAT_AYUV:
459 case TBM_FORMAT_NV12:
460 case TBM_FORMAT_NV12MT:
461 case TBM_FORMAT_NV21:
462 case TBM_FORMAT_NV16:
463 case TBM_FORMAT_NV61:
466 case TBM_FORMAT_YUV410:
467 case TBM_FORMAT_YVU410:
468 case TBM_FORMAT_YUV411:
469 case TBM_FORMAT_YVU411:
470 case TBM_FORMAT_YUV420:
471 case TBM_FORMAT_YVU420:
472 case TBM_FORMAT_YUV422:
473 case TBM_FORMAT_YVU422:
474 case TBM_FORMAT_YUV444:
475 case TBM_FORMAT_YVU444:
483 TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
489 tbm_surface_internal_get_bpp(tbm_format format)
496 case TBM_FORMAT_RGB332:
497 case TBM_FORMAT_BGR233:
500 case TBM_FORMAT_XRGB4444:
501 case TBM_FORMAT_XBGR4444:
502 case TBM_FORMAT_RGBX4444:
503 case TBM_FORMAT_BGRX4444:
504 case TBM_FORMAT_ARGB4444:
505 case TBM_FORMAT_ABGR4444:
506 case TBM_FORMAT_RGBA4444:
507 case TBM_FORMAT_BGRA4444:
508 case TBM_FORMAT_XRGB1555:
509 case TBM_FORMAT_XBGR1555:
510 case TBM_FORMAT_RGBX5551:
511 case TBM_FORMAT_BGRX5551:
512 case TBM_FORMAT_ARGB1555:
513 case TBM_FORMAT_ABGR1555:
514 case TBM_FORMAT_RGBA5551:
515 case TBM_FORMAT_BGRA5551:
516 case TBM_FORMAT_RGB565:
517 case TBM_FORMAT_BGR565:
520 case TBM_FORMAT_RGB888:
521 case TBM_FORMAT_BGR888:
524 case TBM_FORMAT_XRGB8888:
525 case TBM_FORMAT_XBGR8888:
526 case TBM_FORMAT_RGBX8888:
527 case TBM_FORMAT_BGRX8888:
528 case TBM_FORMAT_ARGB8888:
529 case TBM_FORMAT_ABGR8888:
530 case TBM_FORMAT_RGBA8888:
531 case TBM_FORMAT_BGRA8888:
532 case TBM_FORMAT_XRGB2101010:
533 case TBM_FORMAT_XBGR2101010:
534 case TBM_FORMAT_RGBX1010102:
535 case TBM_FORMAT_BGRX1010102:
536 case TBM_FORMAT_ARGB2101010:
537 case TBM_FORMAT_ABGR2101010:
538 case TBM_FORMAT_RGBA1010102:
539 case TBM_FORMAT_BGRA1010102:
540 case TBM_FORMAT_YUYV:
541 case TBM_FORMAT_YVYU:
542 case TBM_FORMAT_UYVY:
543 case TBM_FORMAT_VYUY:
544 case TBM_FORMAT_AYUV:
547 case TBM_FORMAT_NV12:
548 case TBM_FORMAT_NV12MT:
549 case TBM_FORMAT_NV21:
552 case TBM_FORMAT_NV16:
553 case TBM_FORMAT_NV61:
556 case TBM_FORMAT_YUV410:
557 case TBM_FORMAT_YVU410:
560 case TBM_FORMAT_YUV411:
561 case TBM_FORMAT_YVU411:
562 case TBM_FORMAT_YUV420:
563 case TBM_FORMAT_YVU420:
566 case TBM_FORMAT_YUV422:
567 case TBM_FORMAT_YVU422:
570 case TBM_FORMAT_YUV444:
571 case TBM_FORMAT_YVU444:
578 TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
584 tbm_surface_internal_create_with_flags(int width, int height,
585 int format, int flags)
587 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
588 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
590 struct _tbm_bufmgr *mgr;
591 struct _tbm_surface *surf = NULL;
595 uint32_t bo_size = 0;
598 bool bufmgr_initialized = false;
600 _tbm_surface_mutex_lock();
602 if (!g_surface_bufmgr) {
603 _init_surface_bufmgr();
604 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
605 bufmgr_initialized = true;
608 mgr = g_surface_bufmgr;
609 if (!TBM_BUFMGR_IS_VALID(mgr)) {
610 TBM_LOG_E("The bufmgr is invalid\n");
611 goto check_valid_fail;
614 surf = calloc(1, sizeof(struct _tbm_surface));
616 TBM_LOG_E("fail to alloc surf\n");
617 goto alloc_surf_fail;
621 surf->info.width = width;
622 surf->info.height = height;
623 surf->info.format = format;
624 surf->info.bpp = tbm_surface_internal_get_bpp(format);
625 surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
628 /* get size, stride and offset bo_idx */
629 for (i = 0; i < surf->info.num_planes; i++) {
630 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
631 &offset, &stride, &bo_idx)) {
632 TBM_LOG_E("fail to query plane data\n");
633 goto query_plane_data_fail;
636 surf->info.planes[i].size = size;
637 surf->info.planes[i].offset = offset;
638 surf->info.planes[i].stride = stride;
639 surf->planes_bo_idx[i] = bo_idx;
644 for (i = 0; i < surf->info.num_planes; i++) {
645 surf->info.size += surf->info.planes[i].size;
647 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
648 surf->num_bos = surf->planes_bo_idx[i] + 1;
653 for (i = 0; i < surf->num_bos; i++) {
655 for (j = 0; j < surf->info.num_planes; j++) {
656 if (surf->planes_bo_idx[j] == i)
657 bo_size += surf->info.planes[j].size;
660 if (mgr->backend->surface_bo_alloc) {
661 /* LCOV_EXCL_START */
663 void *bo_priv = NULL;
665 bo = calloc(1, sizeof(struct _tbm_bo));
667 TBM_LOG_E("fail to alloc bo struct\n");
671 bo->bufmgr = surf->bufmgr;
673 pthread_mutex_lock(&surf->bufmgr->lock);
675 bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
677 TBM_LOG_E("fail to alloc bo priv\n");
679 pthread_mutex_unlock(&surf->bufmgr->lock);
687 LIST_INITHEAD(&bo->user_data_list);
689 LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
691 pthread_mutex_unlock(&surf->bufmgr->lock);
696 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
698 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
703 _tbm_bo_set_surface(surf->bos[i], surf);
706 TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
707 _tbm_surface_internal_format_to_str(format), flags, surf);
709 LIST_INITHEAD(&surf->user_data_list);
710 LIST_INITHEAD(&surf->debug_data_list);
712 LIST_ADD(&surf->item_link, &mgr->surf_list);
714 _tbm_surface_mutex_unlock();
719 for (j = 0; j < i; j++) {
721 tbm_bo_unref(surf->bos[j]);
723 query_plane_data_fail:
727 if (bufmgr_initialized) {
728 LIST_DELINIT(&mgr->surf_list);
729 _deinit_surface_bufmgr();
731 _tbm_surface_mutex_unlock();
732 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
734 _tbm_surface_internal_format_to_str(format), flags);
739 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
740 tbm_bo *bos, int num)
742 TBM_RETURN_VAL_IF_FAIL(bos, NULL);
743 TBM_RETURN_VAL_IF_FAIL(info, NULL);
744 TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
746 struct _tbm_bufmgr *mgr;
747 struct _tbm_surface *surf = NULL;
749 bool bufmgr_initialized = false;
751 _tbm_surface_mutex_lock();
753 if (!g_surface_bufmgr) {
754 _init_surface_bufmgr();
755 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
756 bufmgr_initialized = true;
759 mgr = g_surface_bufmgr;
760 if (!TBM_BUFMGR_IS_VALID(mgr))
761 goto check_valid_fail;
763 surf = calloc(1, sizeof(struct _tbm_surface));
765 goto alloc_surf_fail;
768 surf->info.width = info->width;
769 surf->info.height = info->height;
770 surf->info.format = info->format;
771 surf->info.bpp = info->bpp;
772 surf->info.num_planes = info->num_planes;
775 /* get size, stride and offset */
776 for (i = 0; i < info->num_planes; i++) {
777 surf->info.planes[i].offset = info->planes[i].offset;
778 surf->info.planes[i].stride = info->planes[i].stride;
780 if (info->planes[i].size > 0)
781 surf->info.planes[i].size = info->planes[i].size;
783 surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
786 surf->planes_bo_idx[i] = 0;
788 surf->planes_bo_idx[i] = i;
791 if (info->size > 0) {
792 surf->info.size = info->size;
795 for (i = 0; i < info->num_planes; i++)
796 surf->info.size += surf->info.planes[i].size;
799 surf->flags = TBM_BO_DEFAULT;
801 /* create only one bo */
803 for (i = 0; i < num; i++) {
807 surf->bos[i] = tbm_bo_ref(bos[i]);
808 _tbm_bo_set_surface(bos[i], surf);
811 TBM_TRACE("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
812 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
814 LIST_INITHEAD(&surf->user_data_list);
815 LIST_INITHEAD(&surf->debug_data_list);
817 LIST_ADD(&surf->item_link, &mgr->surf_list);
819 _tbm_surface_mutex_unlock();
824 for (i = 0; i < num; i++) {
826 tbm_bo_unref(surf->bos[i]);
831 if (bufmgr_initialized) {
832 LIST_DELINIT(&g_surface_bufmgr->surf_list);
833 _deinit_surface_bufmgr();
835 _tbm_surface_mutex_unlock();
836 TBM_TRACE("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
837 info->width, info->height,
838 _tbm_surface_internal_format_to_str(info->format), num);
843 tbm_surface_internal_destroy(tbm_surface_h surface)
845 _tbm_surface_mutex_lock();
847 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
851 if (surface->refcnt > 0) {
852 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
853 _tbm_surface_mutex_unlock();
857 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
859 if (surface->refcnt == 0)
860 _tbm_surface_internal_destroy(surface);
862 _tbm_surface_mutex_unlock();
866 tbm_surface_internal_ref(tbm_surface_h surface)
868 _tbm_surface_mutex_lock();
870 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
874 TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
876 _tbm_surface_mutex_unlock();
880 tbm_surface_internal_unref(tbm_surface_h surface)
882 _tbm_surface_mutex_lock();
884 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
888 if (surface->refcnt > 0) {
889 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
890 _tbm_surface_mutex_unlock();
894 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
896 if (surface->refcnt == 0)
897 _tbm_surface_internal_destroy(surface);
899 _tbm_surface_mutex_unlock();
903 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
905 struct _tbm_surface *surf;
908 _tbm_surface_mutex_lock();
910 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
912 surf = (struct _tbm_surface *)surface;
915 TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
917 _tbm_surface_mutex_unlock();
923 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
925 struct _tbm_surface *surf;
928 _tbm_surface_mutex_lock();
930 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), NULL);
931 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
933 surf = (struct _tbm_surface *)surface;
934 bo = surf->bos[bo_idx];
936 TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
938 _tbm_surface_mutex_unlock();
944 tbm_surface_internal_get_size(tbm_surface_h surface)
946 struct _tbm_surface *surf;
949 _tbm_surface_mutex_lock();
951 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
953 surf = (struct _tbm_surface *)surface;
954 size = surf->info.size;
956 TBM_TRACE("tbm_surface(%p) size(%u)\n", surface, size);
958 _tbm_surface_mutex_unlock();
964 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
965 uint32_t *size, uint32_t *offset, uint32_t *pitch)
967 struct _tbm_surface *surf;
969 _tbm_surface_mutex_lock();
971 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
972 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
974 surf = (struct _tbm_surface *)surface;
976 if (plane_idx >= surf->info.num_planes) {
977 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
978 _tbm_surface_mutex_unlock();
983 *size = surf->info.planes[plane_idx].size;
986 *offset = surf->info.planes[plane_idx].offset;
989 *pitch = surf->info.planes[plane_idx].stride;
991 TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
992 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
993 surf->info.planes[plane_idx].stride);
995 _tbm_surface_mutex_unlock();
1001 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1002 tbm_surface_info_s *info, int map)
1004 struct _tbm_surface *surf;
1005 tbm_bo_handle bo_handles[4];
1008 _tbm_surface_mutex_lock();
1010 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1012 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1014 surf = (struct _tbm_surface *)surface;
1016 memset(info, 0x00, sizeof(tbm_surface_info_s));
1017 info->width = surf->info.width;
1018 info->height = surf->info.height;
1019 info->format = surf->info.format;
1020 info->bpp = surf->info.bpp;
1021 info->size = surf->info.size;
1022 info->num_planes = surf->info.num_planes;
1025 for (i = 0; i < surf->num_bos; i++) {
1026 _tbm_surface_mutex_unlock();
1027 bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1028 _tbm_surface_mutex_lock();
1029 if (bo_handles[i].ptr == NULL) {
1030 for (j = 0; j < i; j++)
1031 tbm_bo_unmap(surf->bos[j]);
1033 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1034 _tbm_surface_mutex_unlock();
1039 for (i = 0; i < surf->num_bos; i++) {
1040 bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1041 if (bo_handles[i].ptr == NULL) {
1042 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1043 _tbm_surface_mutex_unlock();
1049 for (i = 0; i < surf->info.num_planes; i++) {
1050 info->planes[i].size = surf->info.planes[i].size;
1051 info->planes[i].offset = surf->info.planes[i].offset;
1052 info->planes[i].stride = surf->info.planes[i].stride;
1054 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1055 info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1056 surf->info.planes[i].offset;
1059 TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1061 _tbm_surface_mutex_unlock();
1067 tbm_surface_internal_unmap(tbm_surface_h surface)
1069 struct _tbm_surface *surf;
1072 _tbm_surface_mutex_lock();
1074 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1076 surf = (struct _tbm_surface *)surface;
1078 for (i = 0; i < surf->num_bos; i++)
1079 tbm_bo_unmap(surf->bos[i]);
1081 TBM_TRACE("tbm_surface(%p)\n", surface);
1083 _tbm_surface_mutex_unlock();
1087 tbm_surface_internal_get_width(tbm_surface_h surface)
1089 struct _tbm_surface *surf;
1092 _tbm_surface_mutex_lock();
1094 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1096 surf = (struct _tbm_surface *)surface;
1097 width = surf->info.width;
1099 TBM_TRACE("tbm_surface(%p) width(%u)\n", surface, width);
1101 _tbm_surface_mutex_unlock();
1107 tbm_surface_internal_get_height(tbm_surface_h surface)
1109 struct _tbm_surface *surf;
1110 unsigned int height;
1112 _tbm_surface_mutex_lock();
1114 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1116 surf = (struct _tbm_surface *)surface;
1117 height = surf->info.height;
1119 TBM_TRACE("tbm_surface(%p) height(%u)\n", surface, height);
1121 _tbm_surface_mutex_unlock();
1128 tbm_surface_internal_get_format(tbm_surface_h surface)
1130 struct _tbm_surface *surf;
1133 _tbm_surface_mutex_lock();
1135 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1137 surf = (struct _tbm_surface *)surface;
1138 format = surf->info.format;
1140 TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1142 _tbm_surface_mutex_unlock();
1148 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1150 struct _tbm_surface *surf;
1153 _tbm_surface_mutex_lock();
1155 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1156 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1158 surf = (struct _tbm_surface *)surface;
1159 bo_idx = surf->planes_bo_idx[plane_idx];
1161 TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1163 _tbm_surface_mutex_unlock();
1169 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1170 tbm_data_free data_free_func)
1172 tbm_user_data *data;
1174 _tbm_surface_mutex_lock();
1176 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1178 /* check if the data according to the key exist if so, return false. */
1179 data = user_data_lookup(&surface->user_data_list, key);
1181 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1182 _tbm_surface_mutex_unlock();
1186 data = user_data_create(key, data_free_func);
1188 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1189 _tbm_surface_mutex_unlock();
1193 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1195 LIST_ADD(&data->item_link, &surface->user_data_list);
1197 _tbm_surface_mutex_unlock();
1203 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1206 tbm_user_data *old_data;
1208 _tbm_surface_mutex_lock();
1210 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1212 if (LIST_IS_EMPTY(&surface->user_data_list)) {
1213 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1214 _tbm_surface_mutex_unlock();
1218 old_data = user_data_lookup(&surface->user_data_list, key);
1220 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1221 _tbm_surface_mutex_unlock();
1225 if (old_data->data && old_data->free_func)
1226 old_data->free_func(old_data->data);
1228 old_data->data = data;
1230 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1232 _tbm_surface_mutex_unlock();
1238 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1241 tbm_user_data *old_data;
1243 _tbm_surface_mutex_lock();
1245 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1247 if (!data || LIST_IS_EMPTY(&surface->user_data_list)) {
1248 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1249 _tbm_surface_mutex_unlock();
1253 old_data = user_data_lookup(&surface->user_data_list, key);
1255 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1257 _tbm_surface_mutex_unlock();
1261 *data = old_data->data;
1263 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1265 _tbm_surface_mutex_unlock();
1271 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1274 tbm_user_data *old_data = (void *)0;
1276 _tbm_surface_mutex_lock();
1278 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1280 if (LIST_IS_EMPTY(&surface->user_data_list)) {
1281 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1282 _tbm_surface_mutex_unlock();
1286 old_data = user_data_lookup(&surface->user_data_list, key);
1288 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1289 _tbm_surface_mutex_unlock();
1293 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1295 user_data_delete(old_data);
1297 _tbm_surface_mutex_unlock();
1302 /* LCOV_EXCL_START */
1304 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1306 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1308 return surface->debug_pid;
1312 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1314 _tbm_surface_mutex_lock();
1316 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1318 surface->debug_pid = pid;
1320 _tbm_surface_mutex_unlock();
1323 static tbm_surface_debug_data *
1324 _tbm_surface_internal_debug_data_create(char *key, char *value)
1326 tbm_surface_debug_data *debug_data = NULL;
1328 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1332 if (key) debug_data->key = strdup(key);
1333 if (value) debug_data->value = strdup(value);
1339 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1341 tbm_surface_debug_data *debug_data = NULL;
1342 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1343 tbm_bufmgr bufmgr = NULL;
1345 _tbm_surface_mutex_lock();
1347 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1348 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1350 bufmgr = surface->bufmgr;
1352 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1354 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1355 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1356 if (!strcmp(old_data->key, key)) {
1358 old_data->value = strdup(value);
1360 old_data->value = NULL;
1365 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1367 TBM_TRACE("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1368 _tbm_surface_mutex_unlock();
1372 TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1374 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1376 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1377 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1378 if (!strcmp(old_data->key, key)) {
1379 _tbm_surface_mutex_unlock();
1385 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1386 LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1388 _tbm_surface_mutex_unlock();
1394 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1396 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1398 _tbm_surface_mutex_lock();
1400 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1402 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1403 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1404 if (!strcmp(old_data->key, key)) {
1405 _tbm_surface_mutex_unlock();
1406 return old_data->value;
1411 _tbm_surface_mutex_unlock();
1416 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1417 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1419 struct _tbm_surface_dump_buf_info {
1429 tbm_surface_info_s info;
1431 struct list_head link;
1434 struct _tbm_surface_dump_info {
1435 char *path; // copy???
1438 struct list_head *link;
1439 struct list_head surface_list; /* link of surface */
1442 static tbm_surface_dump_info *g_dump_info = NULL;
1443 static const char *dump_postfix[2] = {"png", "yuv"};
1446 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1, void *data2,
1447 int size2, void *data3, int size3)
1449 unsigned int *blocks;
1450 FILE *fp = fopen(file, "w+");
1451 TBM_RETURN_IF_FAIL(fp != NULL);
1453 blocks = (unsigned int *)data1;
1454 fwrite(blocks, 1, size1, fp);
1457 blocks = (unsigned int *)data2;
1458 fwrite(blocks, 1, size2, fp);
1462 blocks = (unsigned int *)data3;
1463 fwrite(blocks, 1, size3, fp);
1470 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width,
1473 FILE *fp = fopen(file, "wb");
1474 TBM_RETURN_IF_FAIL(fp != NULL);
1477 png_structp pPngStruct =
1478 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1484 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1486 png_destroy_write_struct(&pPngStruct, NULL);
1491 png_init_io(pPngStruct, fp);
1492 png_set_IHDR(pPngStruct,
1497 PNG_COLOR_TYPE_RGBA,
1499 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1501 png_set_bgr(pPngStruct);
1502 png_write_info(pPngStruct, pPngInfo);
1504 const int pixel_size = 4; // RGBA
1505 png_bytep *row_pointers =
1506 png_malloc(pPngStruct, height * sizeof(png_byte *));
1508 unsigned int *blocks = (unsigned int *)data;
1512 for (; y < height; ++y) {
1514 png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1515 row_pointers[y] = (png_bytep)row;
1516 for (x = 0; x < width; ++x) {
1517 unsigned int curBlock = blocks[y * width + x];
1518 row[x * pixel_size] = (curBlock & 0xFF);
1519 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1520 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1521 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1525 png_write_image(pPngStruct, row_pointers);
1526 png_write_end(pPngStruct, pPngInfo);
1528 for (y = 0; y < height; y++)
1529 png_free(pPngStruct, row_pointers[y]);
1530 png_free(pPngStruct, row_pointers);
1532 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1538 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1540 TBM_RETURN_IF_FAIL(path != NULL);
1541 TBM_RETURN_IF_FAIL(w > 0);
1542 TBM_RETURN_IF_FAIL(h > 0);
1543 TBM_RETURN_IF_FAIL(count > 0);
1545 tbm_surface_dump_buf_info *buf_info = NULL;
1546 tbm_surface_dump_buf_info *tmp;
1550 tbm_surface_h tbm_surface;
1551 tbm_surface_info_s info;
1552 tbm_surface_error_e err;
1556 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1560 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1561 TBM_RETURN_IF_FAIL(g_dump_info);
1563 LIST_INITHEAD(&g_dump_info->surface_list);
1564 g_dump_info->count = 0;
1565 g_dump_info->dump_max = count;
1567 /* get buffer size */
1568 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1569 if (tbm_surface == NULL) {
1570 TBM_LOG_E("tbm_surface_create fail\n");
1575 err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
1576 if (err != TBM_SURFACE_ERROR_NONE) {
1577 TBM_LOG_E("tbm_surface_map fail\n");
1578 tbm_surface_destroy(tbm_surface);
1583 buffer_size = info.planes[0].stride * h;
1584 tbm_surface_unmap(tbm_surface);
1585 tbm_surface_destroy(tbm_surface);
1587 /* create dump lists */
1588 for (i = 0; i < count; i++) {
1589 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1590 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1591 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1597 buf_info->index = i;
1599 buf_info->size = buffer_size;
1601 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1604 g_dump_info->path = path;
1605 g_dump_info->link = &g_dump_info->surface_list;
1607 TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1611 /* free resources */
1612 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1613 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1614 tbm_bo_unref(buf_info->bo);
1619 TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1628 tbm_surface_internal_dump_end(void)
1630 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1631 tbm_bo_handle bo_handle;
1637 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1638 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1641 if (buf_info->dirty) {
1645 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1646 if (bo_handle.ptr == NULL)
1649 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1650 TBM_LOG_I("Dump File.. %s generated.\n", file);
1652 switch (buf_info->info.format) {
1653 case TBM_FORMAT_ARGB8888:
1654 case TBM_FORMAT_XRGB8888:
1655 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1656 buf_info->info.planes[0].stride >> 2, buf_info->info.height);
1658 case TBM_FORMAT_YVU420:
1659 case TBM_FORMAT_YUV420:
1660 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1661 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1662 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1663 buf_info->info.planes[0].stride * buf_info->info.height,
1665 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1667 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1669 case TBM_FORMAT_NV12:
1670 case TBM_FORMAT_NV21:
1671 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1672 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1673 buf_info->info.planes[0].stride * buf_info->info.height,
1675 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1678 case TBM_FORMAT_YUYV:
1679 case TBM_FORMAT_UYVY:
1680 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1681 buf_info->info.planes[0].stride * buf_info->info.height,
1685 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1686 tbm_bo_unmap(buf_info->bo);
1690 tbm_bo_unmap(buf_info->bo);
1691 } else if (buf_info->dirty_shm) {
1692 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1693 if (bo_handle.ptr == NULL)
1696 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1697 TBM_LOG_I("Dump File.. %s generated.\n", file);
1699 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1700 buf_info->shm_stride >> 2, buf_info->shm_h);
1702 tbm_bo_unmap(buf_info->bo);
1707 /* free resources */
1708 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1709 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1710 tbm_bo_unref(buf_info->bo);
1718 TBM_LOG_I("Dump End..\n");
1722 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1724 TBM_RETURN_IF_FAIL(surface != NULL);
1725 TBM_RETURN_IF_FAIL(type != NULL);
1727 tbm_surface_dump_buf_info *buf_info;
1728 tbm_surface_info_s info;
1729 struct list_head *next_link;
1730 tbm_bo_handle bo_handle;
1732 const char *postfix;
1737 next_link = g_dump_info->link->next;
1738 TBM_RETURN_IF_FAIL(next_link != NULL);
1740 if (next_link == &g_dump_info->surface_list) {
1741 next_link = next_link->next;
1742 TBM_RETURN_IF_FAIL(next_link != NULL);
1745 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1746 TBM_RETURN_IF_FAIL(buf_info != NULL);
1748 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1749 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1751 if (info.size > buf_info->size) {
1752 TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n", info.size, buf_info->size);
1753 tbm_surface_unmap(surface);
1757 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1758 postfix = dump_postfix[0];
1760 postfix = dump_postfix[1];
1762 /* make the file information */
1763 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1766 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1767 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1768 memset(bo_handle.ptr, 0x00, buf_info->size);
1770 switch (info.format) {
1771 case TBM_FORMAT_ARGB8888:
1772 case TBM_FORMAT_XRGB8888:
1773 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d_%p-%s.%s",
1774 _tbm_surface_internal_get_time(),
1775 g_dump_info->count++, surface, type, postfix);
1776 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1778 case TBM_FORMAT_YVU420:
1779 case TBM_FORMAT_YUV420:
1780 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1781 _tbm_surface_internal_get_time(),
1782 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1783 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1784 bo_handle.ptr += info.planes[0].stride * info.height;
1785 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1786 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1787 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1789 case TBM_FORMAT_NV12:
1790 case TBM_FORMAT_NV21:
1791 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1792 _tbm_surface_internal_get_time(),
1793 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1794 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1795 bo_handle.ptr += info.planes[0].stride * info.height;
1796 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1798 case TBM_FORMAT_YUYV:
1799 case TBM_FORMAT_UYVY:
1800 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1801 _tbm_surface_internal_get_time(),
1802 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1803 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1806 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1807 tbm_bo_unmap(buf_info->bo);
1811 tbm_bo_unmap(buf_info->bo);
1813 tbm_surface_unmap(surface);
1815 buf_info->dirty = 1;
1816 buf_info->dirty_shm = 0;
1818 if (g_dump_info->count == 1000)
1819 g_dump_info->count = 0;
1821 g_dump_info->link = next_link;
1823 TBM_LOG_I("Dump %s \n", buf_info->name);
1826 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride, const char *type)
1828 TBM_RETURN_IF_FAIL(ptr != NULL);
1829 TBM_RETURN_IF_FAIL(w > 0);
1830 TBM_RETURN_IF_FAIL(h > 0);
1831 TBM_RETURN_IF_FAIL(stride > 0);
1832 TBM_RETURN_IF_FAIL(type != NULL);
1834 tbm_surface_dump_buf_info *buf_info;
1835 struct list_head *next_link;
1836 tbm_bo_handle bo_handle;
1841 next_link = g_dump_info->link->next;
1842 TBM_RETURN_IF_FAIL(next_link != NULL);
1844 if (next_link == &g_dump_info->surface_list) {
1845 next_link = next_link->next;
1846 TBM_RETURN_IF_FAIL(next_link != NULL);
1849 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1850 TBM_RETURN_IF_FAIL(buf_info != NULL);
1852 if (stride * h > buf_info->size) {
1853 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n", stride * h, buf_info->size);
1858 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1859 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1860 memset(bo_handle.ptr, 0x00, buf_info->size);
1861 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1863 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1864 _tbm_surface_internal_get_time(),
1865 g_dump_info->count++, type, dump_postfix[0]);
1866 memcpy(bo_handle.ptr, ptr, stride * h);
1868 tbm_bo_unmap(buf_info->bo);
1870 buf_info->dirty = 0;
1871 buf_info->dirty_shm = 1;
1872 buf_info->shm_stride = stride;
1873 buf_info->shm_h = h;
1875 if (g_dump_info->count == 1000)
1876 g_dump_info->count = 0;
1878 g_dump_info->link = next_link;
1880 TBM_LOG_I("Dump %s \n", buf_info->name);