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 **************************************************************************/
36 #include "tbm_bufmgr.h"
37 #include "tbm_bufmgr_int.h"
38 #include "tbm_surface_internal.h"
42 static tbm_bufmgr g_surface_bufmgr;
43 static pthread_mutex_t tbm_surface_lock;
44 void _tbm_surface_mutex_unlock(void);
46 #define C(b, m) (((b) >> (m)) & 0xFF)
47 #define B(c, s) ((((unsigned int)(c)) & 0xff) << (s))
48 #define FOURCC(a, b, c, d) (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
49 #define FOURCC_STR(id) C(id, 0), C(id, 8), C(id, 16), C(id, 24)
50 #define FOURCC_ID(str) FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3])
53 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
55 TBM_LOG_E("'%s' failed.\n", #cond);\
56 _tbm_surface_mutex_unlock();\
61 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
63 TBM_LOG_E("'%s' failed.\n", #cond);\
64 _tbm_surface_mutex_unlock();\
70 #define USE_REALTIME 1
73 _tbm_surface_internal_get_time(void)
79 clock_gettime(CLOCK_REALTIME, &tp);
80 #else /* USE_MONOTONIC */
81 clock_gettime(CLOCK_MONOTONIC, &tp);
83 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
89 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
91 LIST_DEL(&debug_data->item_link);
93 if (debug_data->key) free(debug_data->key);
94 if (debug_data->value) free(debug_data->value);
99 _tbm_surface_internal_format_to_str(tbm_format format)
103 return "TBM_FORMAT_C8";
104 case TBM_FORMAT_RGB332:
105 return "TBM_FORMAT_RGB332";
106 case TBM_FORMAT_BGR233:
107 return "TBM_FORMAT_BGR233";
108 case TBM_FORMAT_XRGB4444:
109 return "TBM_FORMAT_XRGB4444";
110 case TBM_FORMAT_XBGR4444:
111 return "TBM_FORMAT_XBGR4444";
112 case TBM_FORMAT_RGBX4444:
113 return "TBM_FORMAT_RGBX4444";
114 case TBM_FORMAT_BGRX4444:
115 return "TBM_FORMAT_BGRX4444";
116 case TBM_FORMAT_ARGB4444:
117 return "TBM_FORMAT_ARGB4444";
118 case TBM_FORMAT_ABGR4444:
119 return "TBM_FORMAT_ABGR4444";
120 case TBM_FORMAT_RGBA4444:
121 return "TBM_FORMAT_RGBA4444";
122 case TBM_FORMAT_BGRA4444:
123 return "TBM_FORMAT_BGRA4444";
124 case TBM_FORMAT_XRGB1555:
125 return "TBM_FORMAT_XRGB1555";
126 case TBM_FORMAT_XBGR1555:
127 return "TBM_FORMAT_XBGR1555";
128 case TBM_FORMAT_RGBX5551:
129 return "TBM_FORMAT_RGBX5551";
130 case TBM_FORMAT_BGRX5551:
131 return "TBM_FORMAT_BGRX5551";
132 case TBM_FORMAT_ARGB1555:
133 return "TBM_FORMAT_ARGB1555";
134 case TBM_FORMAT_ABGR1555:
135 return "TBM_FORMAT_ABGR1555";
136 case TBM_FORMAT_RGBA5551:
137 return "TBM_FORMAT_RGBA5551";
138 case TBM_FORMAT_BGRA5551:
139 return "TBM_FORMAT_BGRA5551";
140 case TBM_FORMAT_RGB565:
141 return "TBM_FORMAT_RGB565";
142 case TBM_FORMAT_BGR565:
143 return "TBM_FORMAT_BGR565";
144 case TBM_FORMAT_RGB888:
145 return "TBM_FORMAT_RGB888";
146 case TBM_FORMAT_BGR888:
147 return "TBM_FORMAT_BGR888";
148 case TBM_FORMAT_XRGB8888:
149 return "TBM_FORMAT_XRGB8888";
150 case TBM_FORMAT_XBGR8888:
151 return "TBM_FORMAT_XBGR8888";
152 case TBM_FORMAT_RGBX8888:
153 return "TBM_FORMAT_RGBX8888";
154 case TBM_FORMAT_BGRX8888:
155 return "TBM_FORMAT_BGRX8888";
156 case TBM_FORMAT_ARGB8888:
157 return "TBM_FORMAT_ARGB8888";
158 case TBM_FORMAT_ABGR8888:
159 return "TBM_FORMAT_ABGR8888";
160 case TBM_FORMAT_RGBA8888:
161 return "TBM_FORMAT_RGBA8888";
162 case TBM_FORMAT_BGRA8888:
163 return "TBM_FORMAT_BGRA8888";
164 case TBM_FORMAT_XRGB2101010:
165 return "TBM_FORMAT_XRGB2101010";
166 case TBM_FORMAT_XBGR2101010:
167 return "TBM_FORMAT_XBGR2101010";
168 case TBM_FORMAT_RGBX1010102:
169 return "TBM_FORMAT_RGBX1010102";
170 case TBM_FORMAT_BGRX1010102:
171 return "TBM_FORMAT_BGRX1010102";
172 case TBM_FORMAT_ARGB2101010:
173 return "TBM_FORMAT_ARGB2101010";
174 case TBM_FORMAT_ABGR2101010:
175 return "TBM_FORMAT_ABGR2101010";
176 case TBM_FORMAT_RGBA1010102:
177 return "TBM_FORMAT_RGBA1010102";
178 case TBM_FORMAT_BGRA1010102:
179 return "TBM_FORMAT_BGRA1010102";
180 case TBM_FORMAT_YUYV:
181 return "TBM_FORMAT_YUYV";
182 case TBM_FORMAT_YVYU:
183 return "TBM_FORMAT_YVYU";
184 case TBM_FORMAT_UYVY:
185 return "TBM_FORMAT_UYVY";
186 case TBM_FORMAT_VYUY:
187 return "TBM_FORMAT_VYUY";
188 case TBM_FORMAT_AYUV:
189 return "TBM_FORMAT_AYUV";
190 case TBM_FORMAT_NV12:
191 return "TBM_FORMAT_NV12";
192 case TBM_FORMAT_NV21:
193 return "TBM_FORMAT_NV21";
194 case TBM_FORMAT_NV16:
195 return "TBM_FORMAT_NV16";
196 case TBM_FORMAT_NV61:
197 return "TBM_FORMAT_NV61";
198 case TBM_FORMAT_YUV410:
199 return "TBM_FORMAT_YUV410";
200 case TBM_FORMAT_YVU410:
201 return "TBM_FORMAT_YVU410";
202 case TBM_FORMAT_YUV411:
203 return "TBM_FORMAT_YUV411";
204 case TBM_FORMAT_YVU411:
205 return "TBM_FORMAT_YVU411";
206 case TBM_FORMAT_YUV420:
207 return "TBM_FORMAT_YUV420";
208 case TBM_FORMAT_YVU420:
209 return "TBM_FORMAT_YVU420";
210 case TBM_FORMAT_YUV422:
211 return "TBM_FORMAT_YUV422";
212 case TBM_FORMAT_YVU422:
213 return "TBM_FORMAT_YVU422";
214 case TBM_FORMAT_YUV444:
215 return "TBM_FORMAT_YUV444";
216 case TBM_FORMAT_YVU444:
217 return "TBM_FORMAT_YVU444";
218 case TBM_FORMAT_NV12MT:
219 return "TBM_FORMAT_NV12MT";
227 _tbm_surface_mutex_init(void)
229 static bool tbm_surface_mutex_init = false;
231 if (tbm_surface_mutex_init)
234 if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
235 TBM_LOG_E("fail: tbm_surface mutex init\n");
239 tbm_surface_mutex_init = true;
245 _tbm_surface_mutex_lock(void)
247 if (!_tbm_surface_mutex_init())
250 pthread_mutex_lock(&tbm_surface_lock);
254 _tbm_surface_mutex_unlock(void)
256 pthread_mutex_unlock(&tbm_surface_lock);
260 _init_surface_bufmgr(void)
262 g_surface_bufmgr = tbm_bufmgr_init(-1);
266 _deinit_surface_bufmgr(void)
268 if (!g_surface_bufmgr)
271 tbm_bufmgr_deinit(g_surface_bufmgr);
272 g_surface_bufmgr = NULL;
276 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
277 int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
279 TBM_RETURN_VAL_IF_FAIL(surface, 0);
280 TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
282 struct _tbm_surface *surf = (struct _tbm_surface *)surface;
283 struct _tbm_bufmgr *mgr = surf->bufmgr;
286 TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
287 TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
288 TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
289 TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
291 if (!mgr->backend->surface_get_plane_data)
294 ret = mgr->backend->surface_get_plane_data(surf->info.width,
295 surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
303 _tbm_surface_internal_destroy(tbm_surface_h surface)
306 tbm_bufmgr bufmgr = surface->bufmgr;
307 tbm_user_data *old_data = NULL, *tmp = NULL;
308 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
310 /* destory the user_data_list */
311 if (!LIST_IS_EMPTY(&surface->user_data_list)) {
312 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
313 DBG("free user_data\n");
314 user_data_delete(old_data);
318 for (i = 0; i < surface->num_bos; i++) {
319 surface->bos[i]->surface = NULL;
321 tbm_bo_unref(surface->bos[i]);
322 surface->bos[i] = NULL;
325 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
326 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
327 _tbm_surface_internal_debug_data_delete(debug_old_data);
330 LIST_DEL(&surface->item_link);
335 if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
336 LIST_DELINIT(&bufmgr->surf_list);
338 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
339 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
340 _tbm_surface_internal_debug_data_delete(debug_old_data);
344 _deinit_surface_bufmgr();
349 tbm_surface_internal_is_valid(tbm_surface_h surface)
351 tbm_surface_h old_data = NULL, tmp = NULL;
353 if (surface == NULL || g_surface_bufmgr == NULL) {
354 TBM_TRACE("error: tbm_surface(%p)\n", surface);
358 if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
359 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &g_surface_bufmgr->surf_list, item_link) {
360 if (old_data == surface) {
361 TBM_TRACE("tbm_surface(%p)\n", surface);
366 TBM_TRACE("error: tbm_surface(%p)\n", surface);
371 tbm_surface_internal_query_supported_formats(uint32_t **formats,
374 struct _tbm_bufmgr *mgr;
377 _tbm_surface_mutex_lock();
379 if (!g_surface_bufmgr) {
380 _init_surface_bufmgr();
381 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
384 mgr = g_surface_bufmgr;
386 if (!mgr->backend->surface_supported_format) {
387 TBM_TRACE("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
388 _tbm_surface_mutex_unlock();
392 ret = mgr->backend->surface_supported_format(formats, num);
394 TBM_TRACE("tbm_bufmgr(%p) format num(%d)\n", g_surface_bufmgr, *num);
396 _tbm_surface_mutex_unlock();
402 tbm_surface_internal_get_num_planes(tbm_format format)
408 case TBM_FORMAT_RGB332:
409 case TBM_FORMAT_BGR233:
410 case TBM_FORMAT_XRGB4444:
411 case TBM_FORMAT_XBGR4444:
412 case TBM_FORMAT_RGBX4444:
413 case TBM_FORMAT_BGRX4444:
414 case TBM_FORMAT_ARGB4444:
415 case TBM_FORMAT_ABGR4444:
416 case TBM_FORMAT_RGBA4444:
417 case TBM_FORMAT_BGRA4444:
418 case TBM_FORMAT_XRGB1555:
419 case TBM_FORMAT_XBGR1555:
420 case TBM_FORMAT_RGBX5551:
421 case TBM_FORMAT_BGRX5551:
422 case TBM_FORMAT_ARGB1555:
423 case TBM_FORMAT_ABGR1555:
424 case TBM_FORMAT_RGBA5551:
425 case TBM_FORMAT_BGRA5551:
426 case TBM_FORMAT_RGB565:
427 case TBM_FORMAT_BGR565:
428 case TBM_FORMAT_RGB888:
429 case TBM_FORMAT_BGR888:
430 case TBM_FORMAT_XRGB8888:
431 case TBM_FORMAT_XBGR8888:
432 case TBM_FORMAT_RGBX8888:
433 case TBM_FORMAT_BGRX8888:
434 case TBM_FORMAT_ARGB8888:
435 case TBM_FORMAT_ABGR8888:
436 case TBM_FORMAT_RGBA8888:
437 case TBM_FORMAT_BGRA8888:
438 case TBM_FORMAT_XRGB2101010:
439 case TBM_FORMAT_XBGR2101010:
440 case TBM_FORMAT_RGBX1010102:
441 case TBM_FORMAT_BGRX1010102:
442 case TBM_FORMAT_ARGB2101010:
443 case TBM_FORMAT_ABGR2101010:
444 case TBM_FORMAT_RGBA1010102:
445 case TBM_FORMAT_BGRA1010102:
446 case TBM_FORMAT_YUYV:
447 case TBM_FORMAT_YVYU:
448 case TBM_FORMAT_UYVY:
449 case TBM_FORMAT_VYUY:
450 case TBM_FORMAT_AYUV:
453 case TBM_FORMAT_NV12:
454 case TBM_FORMAT_NV12MT:
455 case TBM_FORMAT_NV21:
456 case TBM_FORMAT_NV16:
457 case TBM_FORMAT_NV61:
460 case TBM_FORMAT_YUV410:
461 case TBM_FORMAT_YVU410:
462 case TBM_FORMAT_YUV411:
463 case TBM_FORMAT_YVU411:
464 case TBM_FORMAT_YUV420:
465 case TBM_FORMAT_YVU420:
466 case TBM_FORMAT_YUV422:
467 case TBM_FORMAT_YVU422:
468 case TBM_FORMAT_YUV444:
469 case TBM_FORMAT_YVU444:
477 TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
483 tbm_surface_internal_get_bpp(tbm_format format)
490 case TBM_FORMAT_RGB332:
491 case TBM_FORMAT_BGR233:
494 case TBM_FORMAT_XRGB4444:
495 case TBM_FORMAT_XBGR4444:
496 case TBM_FORMAT_RGBX4444:
497 case TBM_FORMAT_BGRX4444:
498 case TBM_FORMAT_ARGB4444:
499 case TBM_FORMAT_ABGR4444:
500 case TBM_FORMAT_RGBA4444:
501 case TBM_FORMAT_BGRA4444:
502 case TBM_FORMAT_XRGB1555:
503 case TBM_FORMAT_XBGR1555:
504 case TBM_FORMAT_RGBX5551:
505 case TBM_FORMAT_BGRX5551:
506 case TBM_FORMAT_ARGB1555:
507 case TBM_FORMAT_ABGR1555:
508 case TBM_FORMAT_RGBA5551:
509 case TBM_FORMAT_BGRA5551:
510 case TBM_FORMAT_RGB565:
511 case TBM_FORMAT_BGR565:
514 case TBM_FORMAT_RGB888:
515 case TBM_FORMAT_BGR888:
518 case TBM_FORMAT_XRGB8888:
519 case TBM_FORMAT_XBGR8888:
520 case TBM_FORMAT_RGBX8888:
521 case TBM_FORMAT_BGRX8888:
522 case TBM_FORMAT_ARGB8888:
523 case TBM_FORMAT_ABGR8888:
524 case TBM_FORMAT_RGBA8888:
525 case TBM_FORMAT_BGRA8888:
526 case TBM_FORMAT_XRGB2101010:
527 case TBM_FORMAT_XBGR2101010:
528 case TBM_FORMAT_RGBX1010102:
529 case TBM_FORMAT_BGRX1010102:
530 case TBM_FORMAT_ARGB2101010:
531 case TBM_FORMAT_ABGR2101010:
532 case TBM_FORMAT_RGBA1010102:
533 case TBM_FORMAT_BGRA1010102:
534 case TBM_FORMAT_YUYV:
535 case TBM_FORMAT_YVYU:
536 case TBM_FORMAT_UYVY:
537 case TBM_FORMAT_VYUY:
538 case TBM_FORMAT_AYUV:
541 case TBM_FORMAT_NV12:
542 case TBM_FORMAT_NV12MT:
543 case TBM_FORMAT_NV21:
546 case TBM_FORMAT_NV16:
547 case TBM_FORMAT_NV61:
550 case TBM_FORMAT_YUV410:
551 case TBM_FORMAT_YVU410:
554 case TBM_FORMAT_YUV411:
555 case TBM_FORMAT_YVU411:
556 case TBM_FORMAT_YUV420:
557 case TBM_FORMAT_YVU420:
560 case TBM_FORMAT_YUV422:
561 case TBM_FORMAT_YVU422:
564 case TBM_FORMAT_YUV444:
565 case TBM_FORMAT_YVU444:
572 TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
578 tbm_surface_internal_create_with_flags(int width, int height,
579 int format, int flags)
581 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
582 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
584 struct _tbm_bufmgr *mgr;
585 struct _tbm_surface *surf = NULL;
589 uint32_t bo_size = 0;
593 _tbm_surface_mutex_lock();
595 if (!g_surface_bufmgr) {
596 _init_surface_bufmgr();
597 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
600 mgr = g_surface_bufmgr;
601 if (!TBM_BUFMGR_IS_VALID(mgr)) {
602 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
603 width, height, _tbm_surface_internal_format_to_str(format), flags);
604 _tbm_surface_mutex_unlock();
607 surf = calloc(1, sizeof(struct _tbm_surface));
609 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
610 width, height, _tbm_surface_internal_format_to_str(format), flags);
611 _tbm_surface_mutex_unlock();
616 surf->info.width = width;
617 surf->info.height = height;
618 surf->info.format = format;
619 surf->info.bpp = tbm_surface_internal_get_bpp(format);
620 surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
623 /* get size, stride and offset bo_idx */
624 for (i = 0; i < surf->info.num_planes; i++) {
625 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride,
627 surf->info.planes[i].size = size;
628 surf->info.planes[i].offset = offset;
629 surf->info.planes[i].stride = stride;
630 surf->planes_bo_idx[i] = bo_idx;
635 for (i = 0; i < surf->info.num_planes; i++) {
636 surf->info.size += surf->info.planes[i].size;
638 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
639 surf->num_bos = surf->planes_bo_idx[i] + 1;
644 for (i = 0; i < surf->num_bos; i++) {
646 for (j = 0; j < surf->info.num_planes; j++) {
647 if (surf->planes_bo_idx[j] == i)
648 bo_size += surf->info.planes[j].size;
651 if (mgr->backend->surface_bo_alloc) {
652 /* LCOV_EXCL_START */
654 void *bo_priv = NULL;
656 bo = calloc(1, sizeof(struct _tbm_bo));
658 TBM_LOG_E("fail to alloc bo struct\n");
662 bo->bufmgr = surf->bufmgr;
664 pthread_mutex_lock(&surf->bufmgr->lock);
666 bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
668 TBM_LOG_E("fail to alloc bo priv\n");
670 pthread_mutex_unlock(&surf->bufmgr->lock);
678 LIST_INITHEAD(&bo->user_data_list);
680 LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
682 pthread_mutex_unlock(&surf->bufmgr->lock);
687 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
691 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
695 _tbm_bo_set_surface(surf->bos[i], surf);
699 TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
700 _tbm_surface_internal_format_to_str(format), flags, surf);
702 LIST_INITHEAD(&surf->user_data_list);
703 LIST_INITHEAD(&surf->debug_data_list);
705 LIST_ADD(&surf->item_link, &mgr->surf_list);
707 _tbm_surface_mutex_unlock();
713 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
714 width, height, _tbm_surface_internal_format_to_str(format), flags);
716 for (j = 0; j < i; j++) {
718 tbm_bo_unref(surf->bos[j]);
724 if (LIST_IS_EMPTY(&mgr->surf_list)) {
725 LIST_DELINIT(&mgr->surf_list);
726 _deinit_surface_bufmgr();
729 _tbm_surface_mutex_unlock();
734 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
735 tbm_bo *bos, int num)
737 TBM_RETURN_VAL_IF_FAIL(bos, NULL);
738 TBM_RETURN_VAL_IF_FAIL(info, NULL);
739 TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
741 struct _tbm_bufmgr *mgr;
742 struct _tbm_surface *surf = NULL;
745 _tbm_surface_mutex_lock();
747 if (!g_surface_bufmgr) {
748 _init_surface_bufmgr();
749 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
752 mgr = g_surface_bufmgr;
753 if (!TBM_BUFMGR_IS_VALID(mgr)) {
754 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
755 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
756 _tbm_surface_mutex_unlock();
760 surf = calloc(1, sizeof(struct _tbm_surface));
762 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
763 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
764 _tbm_surface_mutex_unlock();
769 surf->info.width = info->width;
770 surf->info.height = info->height;
771 surf->info.format = info->format;
772 surf->info.bpp = info->bpp;
773 surf->info.num_planes = info->num_planes;
776 /* get size, stride and offset */
777 for (i = 0; i < info->num_planes; i++) {
778 surf->info.planes[i].offset = info->planes[i].offset;
779 surf->info.planes[i].stride = info->planes[i].stride;
781 if (info->planes[i].size > 0)
782 surf->info.planes[i].size = info->planes[i].size;
784 surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
787 surf->planes_bo_idx[i] = 0;
789 surf->planes_bo_idx[i] = i;
792 if (info->size > 0) {
793 surf->info.size = info->size;
796 for (i = 0; i < info->num_planes; i++)
797 surf->info.size += surf->info.planes[i].size;
800 surf->flags = TBM_BO_DEFAULT;
802 /* create only one bo */
804 for (i = 0; i < num; i++) {
808 surf->bos[i] = tbm_bo_ref(bos[i]);
809 _tbm_bo_set_surface(bos[i], surf);
812 TBM_TRACE("tbm_surface(%p) width(%d) height(%d) format(%s) bo_num(%d)\n", surf,
813 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
815 LIST_INITHEAD(&surf->user_data_list);
816 LIST_INITHEAD(&surf->debug_data_list);
818 LIST_ADD(&surf->item_link, &mgr->surf_list);
820 _tbm_surface_mutex_unlock();
824 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
825 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
826 for (i = 0; i < num; i++) {
828 tbm_bo_unref(surf->bos[i]);
836 if (LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
837 LIST_DELINIT(&g_surface_bufmgr->surf_list);
838 _deinit_surface_bufmgr();
841 _tbm_surface_mutex_unlock();
847 tbm_surface_internal_destroy(tbm_surface_h surface)
849 _tbm_surface_mutex_lock();
851 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
855 if (surface->refcnt > 0) {
856 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
857 _tbm_surface_mutex_unlock();
861 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
863 if (surface->refcnt == 0)
864 _tbm_surface_internal_destroy(surface);
866 _tbm_surface_mutex_unlock();
870 tbm_surface_internal_ref(tbm_surface_h surface)
872 _tbm_surface_mutex_lock();
874 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
878 TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
880 _tbm_surface_mutex_unlock();
884 tbm_surface_internal_unref(tbm_surface_h surface)
886 _tbm_surface_mutex_lock();
888 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
892 if (surface->refcnt > 0) {
893 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
894 _tbm_surface_mutex_unlock();
898 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
900 if (surface->refcnt == 0)
901 _tbm_surface_internal_destroy(surface);
903 _tbm_surface_mutex_unlock();
907 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
909 struct _tbm_surface *surf;
912 _tbm_surface_mutex_lock();
914 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
916 surf = (struct _tbm_surface *)surface;
919 TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
921 _tbm_surface_mutex_unlock();
927 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
929 struct _tbm_surface *surf;
932 _tbm_surface_mutex_lock();
934 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), NULL);
935 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
937 surf = (struct _tbm_surface *)surface;
938 bo = surf->bos[bo_idx];
940 TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
942 _tbm_surface_mutex_unlock();
948 tbm_surface_internal_get_size(tbm_surface_h surface)
950 struct _tbm_surface *surf;
953 _tbm_surface_mutex_lock();
955 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
957 surf = (struct _tbm_surface *)surface;
958 size = surf->info.size;
960 TBM_TRACE("tbm_surface(%p) size(%d)\n", surface, size);
962 _tbm_surface_mutex_unlock();
968 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
969 uint32_t *size, uint32_t *offset, uint32_t *pitch)
971 struct _tbm_surface *surf;
973 _tbm_surface_mutex_lock();
975 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
976 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
978 surf = (struct _tbm_surface *)surface;
980 if (plane_idx >= surf->info.num_planes) {
981 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
982 _tbm_surface_mutex_unlock();
987 *size = surf->info.planes[plane_idx].size;
990 *offset = surf->info.planes[plane_idx].offset;
993 *pitch = surf->info.planes[plane_idx].stride;
995 TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%d) offset(%d) pitch(%d)\n", surface, plane_idx,
996 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
997 surf->info.planes[plane_idx].stride);
999 _tbm_surface_mutex_unlock();
1005 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1006 tbm_surface_info_s *info, int map)
1008 struct _tbm_surface *surf;
1009 tbm_bo_handle bo_handles[4];
1012 _tbm_surface_mutex_lock();
1014 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1016 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1018 surf = (struct _tbm_surface *)surface;
1020 memset(info, 0x00, sizeof(tbm_surface_info_s));
1021 info->width = surf->info.width;
1022 info->height = surf->info.height;
1023 info->format = surf->info.format;
1024 info->bpp = surf->info.bpp;
1025 info->size = surf->info.size;
1026 info->num_planes = surf->info.num_planes;
1029 for (i = 0; i < surf->num_bos; i++) {
1030 bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1031 if (bo_handles[i].ptr == NULL) {
1032 for (j = 0; j < i; j++)
1033 tbm_bo_unmap(surf->bos[j]);
1035 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1036 _tbm_surface_mutex_unlock();
1041 for (i = 0; i < surf->num_bos; i++)
1042 bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1045 for (i = 0; i < surf->info.num_planes; i++) {
1046 info->planes[i].size = surf->info.planes[i].size;
1047 info->planes[i].offset = surf->info.planes[i].offset;
1048 info->planes[i].stride = surf->info.planes[i].stride;
1050 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1051 info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1052 surf->info.planes[i].offset;
1055 TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1057 _tbm_surface_mutex_unlock();
1063 tbm_surface_internal_unmap(tbm_surface_h surface)
1065 struct _tbm_surface *surf;
1068 _tbm_surface_mutex_lock();
1070 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1072 surf = (struct _tbm_surface *)surface;
1074 for (i = 0; i < surf->num_bos; i++)
1075 tbm_bo_unmap(surf->bos[i]);
1077 TBM_TRACE("tbm_surface(%p)\n", surface);
1079 _tbm_surface_mutex_unlock();
1083 tbm_surface_internal_get_width(tbm_surface_h surface)
1085 struct _tbm_surface *surf;
1088 _tbm_surface_mutex_lock();
1090 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1092 surf = (struct _tbm_surface *)surface;
1093 width = surf->info.width;
1095 TBM_TRACE("tbm_surface(%p) width(%d)\n", surface, width);
1097 _tbm_surface_mutex_unlock();
1103 tbm_surface_internal_get_height(tbm_surface_h surface)
1105 struct _tbm_surface *surf;
1106 unsigned int height;
1108 _tbm_surface_mutex_lock();
1110 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1112 surf = (struct _tbm_surface *)surface;
1113 height = surf->info.height;
1115 TBM_TRACE("tbm_surface(%p) height(%d)\n", surface, height);
1117 _tbm_surface_mutex_unlock();
1124 tbm_surface_internal_get_format(tbm_surface_h surface)
1126 struct _tbm_surface *surf;
1129 _tbm_surface_mutex_lock();
1131 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1133 surf = (struct _tbm_surface *)surface;
1134 format = surf->info.format;
1136 TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1138 _tbm_surface_mutex_unlock();
1144 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1146 struct _tbm_surface *surf;
1149 _tbm_surface_mutex_lock();
1151 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1152 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1154 surf = (struct _tbm_surface *)surface;
1155 bo_idx = surf->planes_bo_idx[plane_idx];
1157 TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1159 _tbm_surface_mutex_unlock();
1165 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1166 tbm_data_free data_free_func)
1168 tbm_user_data *data;
1170 _tbm_surface_mutex_lock();
1172 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1174 /* check if the data according to the key exist if so, return false. */
1175 data = user_data_lookup(&surface->user_data_list, key);
1177 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1178 _tbm_surface_mutex_unlock();
1182 data = user_data_create(key, data_free_func);
1184 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1185 _tbm_surface_mutex_unlock();
1189 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1191 LIST_ADD(&data->item_link, &surface->user_data_list);
1193 _tbm_surface_mutex_unlock();
1199 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1202 tbm_user_data *old_data;
1204 _tbm_surface_mutex_lock();
1206 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1208 if (LIST_IS_EMPTY(&surface->user_data_list)) {
1209 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1210 _tbm_surface_mutex_unlock();
1214 old_data = user_data_lookup(&surface->user_data_list, key);
1216 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1217 _tbm_surface_mutex_unlock();
1221 if (old_data->data && old_data->free_func)
1222 old_data->free_func(old_data->data);
1224 old_data->data = data;
1226 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1228 _tbm_surface_mutex_unlock();
1234 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1237 tbm_user_data *old_data;
1239 _tbm_surface_mutex_lock();
1241 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1243 if (!data || LIST_IS_EMPTY(&surface->user_data_list)) {
1244 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1245 _tbm_surface_mutex_unlock();
1249 old_data = user_data_lookup(&surface->user_data_list, key);
1251 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1253 _tbm_surface_mutex_unlock();
1257 *data = old_data->data;
1259 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1261 _tbm_surface_mutex_unlock();
1267 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1270 tbm_user_data *old_data = (void *)0;
1272 _tbm_surface_mutex_lock();
1274 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1276 if (LIST_IS_EMPTY(&surface->user_data_list)) {
1277 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1278 _tbm_surface_mutex_unlock();
1282 old_data = user_data_lookup(&surface->user_data_list, key);
1284 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1285 _tbm_surface_mutex_unlock();
1289 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1291 user_data_delete(old_data);
1293 _tbm_surface_mutex_unlock();
1298 /* LCOV_EXCL_START */
1300 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1302 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1304 return surface->debug_pid;
1308 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1310 _tbm_surface_mutex_lock();
1312 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1314 surface->debug_pid = pid;
1316 _tbm_surface_mutex_unlock();
1319 static tbm_surface_debug_data *
1320 _tbm_surface_internal_debug_data_create(char *key, char *value)
1322 tbm_surface_debug_data *debug_data = NULL;
1324 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1328 if (key) debug_data->key = strdup(key);
1329 if (value) debug_data->value = strdup(value);
1335 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1337 tbm_surface_debug_data *debug_data = NULL;
1338 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1339 tbm_bufmgr bufmgr = NULL;
1341 _tbm_surface_mutex_lock();
1343 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1344 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1346 bufmgr = surface->bufmgr;
1348 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1350 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1351 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1352 if (!strcmp(old_data->key, key)) {
1354 old_data->value = strdup(value);
1356 old_data->value = NULL;
1361 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1363 TBM_TRACE("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1364 _tbm_surface_mutex_unlock();
1368 TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1370 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1372 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1373 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1374 if (!strcmp(old_data->key, key)) {
1375 _tbm_surface_mutex_unlock();
1381 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1382 LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1384 _tbm_surface_mutex_unlock();
1390 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1392 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1394 _tbm_surface_mutex_lock();
1396 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1398 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1399 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1400 if (!strcmp(old_data->key, key)) {
1401 _tbm_surface_mutex_unlock();
1402 return old_data->value;
1407 _tbm_surface_mutex_unlock();
1412 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1413 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1415 struct _tbm_surface_dump_buf_info {
1425 tbm_surface_info_s info;
1427 struct list_head link;
1430 struct _tbm_surface_dump_info {
1431 char *path; // copy???
1434 struct list_head *link;
1435 struct list_head surface_list; /* link of surface */
1438 static tbm_surface_dump_info *g_dump_info = NULL;
1439 static const char *dump_postfix[2] = {"png", "yuv"};
1442 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1, void *data2,
1443 int size2, void *data3, int size3)
1445 unsigned int *blocks;
1446 FILE *fp = fopen(file, "w+");
1447 TBM_RETURN_IF_FAIL(fp != NULL);
1449 blocks = (unsigned int *)data1;
1450 fwrite(blocks, 1, size1, fp);
1453 blocks = (unsigned int *)data2;
1454 fwrite(blocks, 1, size2, fp);
1458 blocks = (unsigned int *)data3;
1459 fwrite(blocks, 1, size3, fp);
1466 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width,
1469 FILE *fp = fopen(file, "wb");
1470 TBM_RETURN_IF_FAIL(fp != NULL);
1473 png_structp pPngStruct =
1474 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1480 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1482 png_destroy_write_struct(&pPngStruct, NULL);
1487 png_init_io(pPngStruct, fp);
1488 png_set_IHDR(pPngStruct,
1493 PNG_COLOR_TYPE_RGBA,
1495 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1497 png_set_bgr(pPngStruct);
1498 png_write_info(pPngStruct, pPngInfo);
1500 const int pixel_size = 4; // RGBA
1501 png_bytep *row_pointers =
1502 png_malloc(pPngStruct, height * sizeof(png_byte *));
1504 unsigned int *blocks = (unsigned int *)data;
1508 for (; y < height; ++y) {
1510 png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1511 row_pointers[y] = (png_bytep)row;
1512 for (x = 0; x < width; ++x) {
1513 unsigned int curBlock = blocks[y * width + x];
1514 row[x * pixel_size] = (curBlock & 0xFF);
1515 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1516 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1517 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1521 png_write_image(pPngStruct, row_pointers);
1522 png_write_end(pPngStruct, pPngInfo);
1524 for (y = 0; y < height; y++)
1525 png_free(pPngStruct, row_pointers[y]);
1526 png_free(pPngStruct, row_pointers);
1528 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1534 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1536 TBM_RETURN_IF_FAIL(path != NULL);
1537 TBM_RETURN_IF_FAIL(w > 0);
1538 TBM_RETURN_IF_FAIL(h > 0);
1539 TBM_RETURN_IF_FAIL(count > 0);
1541 tbm_surface_dump_buf_info *buf_info = NULL;
1542 tbm_surface_dump_buf_info *tmp;
1546 tbm_surface_h tbm_surface;
1547 tbm_surface_info_s info;
1548 tbm_surface_error_e err;
1552 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1556 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1557 TBM_RETURN_IF_FAIL(g_dump_info);
1559 LIST_INITHEAD(&g_dump_info->surface_list);
1560 g_dump_info->count = 0;
1561 g_dump_info->dump_max = count;
1563 /* get buffer size */
1564 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1565 if (tbm_surface == NULL) {
1566 TBM_LOG_E("tbm_surface_create fail\n");
1571 err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
1572 if (err != TBM_SURFACE_ERROR_NONE) {
1573 TBM_LOG_E("tbm_surface_map fail\n");
1574 tbm_surface_destroy(tbm_surface);
1579 buffer_size = info.planes[0].stride * h;
1580 tbm_surface_unmap(tbm_surface);
1581 tbm_surface_destroy(tbm_surface);
1583 /* create dump lists */
1584 for (i = 0; i < count; i++) {
1585 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1586 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1587 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1593 buf_info->index = i;
1595 buf_info->size = buffer_size;
1597 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1600 g_dump_info->path = path;
1601 g_dump_info->link = &g_dump_info->surface_list;
1603 TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1607 /* free resources */
1608 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1609 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1610 tbm_bo_unref(buf_info->bo);
1615 TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1624 tbm_surface_internal_dump_end(void)
1626 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1627 tbm_bo_handle bo_handle;
1633 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1634 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1637 if (buf_info->dirty) {
1641 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1642 if (bo_handle.ptr == NULL)
1645 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1646 TBM_LOG_I("Dump File.. %s generated.\n", file);
1648 switch (buf_info->info.format) {
1649 case TBM_FORMAT_ARGB8888:
1650 case TBM_FORMAT_XRGB8888:
1651 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1652 buf_info->info.planes[0].stride >> 2, buf_info->info.height);
1654 case TBM_FORMAT_YVU420:
1655 case TBM_FORMAT_YUV420:
1656 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1657 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1658 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1659 buf_info->info.planes[0].stride * buf_info->info.height,
1661 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1663 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1665 case TBM_FORMAT_NV12:
1666 case TBM_FORMAT_NV21:
1667 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1668 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1669 buf_info->info.planes[0].stride * buf_info->info.height,
1671 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1674 case TBM_FORMAT_YUYV:
1675 case TBM_FORMAT_UYVY:
1676 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1677 buf_info->info.planes[0].stride * buf_info->info.height,
1681 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1682 tbm_bo_unmap(buf_info->bo);
1686 tbm_bo_unmap(buf_info->bo);
1687 } else if (buf_info->dirty_shm) {
1688 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1689 if (bo_handle.ptr == NULL)
1692 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1693 TBM_LOG_I("Dump File.. %s generated.\n", file);
1695 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1696 buf_info->shm_stride >> 2, buf_info->shm_h);
1698 tbm_bo_unmap(buf_info->bo);
1703 /* free resources */
1704 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1705 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1706 tbm_bo_unref(buf_info->bo);
1714 TBM_LOG_I("Dump End..\n");
1718 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1720 TBM_RETURN_IF_FAIL(surface != NULL);
1721 TBM_RETURN_IF_FAIL(type != NULL);
1723 tbm_surface_dump_buf_info *buf_info;
1724 tbm_surface_info_s info;
1725 struct list_head *next_link;
1726 tbm_bo_handle bo_handle;
1728 const char *postfix;
1733 next_link = g_dump_info->link->next;
1734 TBM_RETURN_IF_FAIL(next_link != NULL);
1736 if (next_link == &g_dump_info->surface_list) {
1737 next_link = next_link->next;
1738 TBM_RETURN_IF_FAIL(next_link != NULL);
1741 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1742 TBM_RETURN_IF_FAIL(buf_info != NULL);
1744 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1745 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1747 if (info.size > buf_info->size) {
1748 TBM_LOG_W("Dump skip. surface over created buffer size(%d, %d)\n", info.size, buf_info->size);
1749 tbm_surface_unmap(surface);
1753 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1754 postfix = dump_postfix[0];
1756 postfix = dump_postfix[1];
1758 /* make the file information */
1759 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1762 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1763 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1764 memset(bo_handle.ptr, 0x00, buf_info->size);
1766 switch (info.format) {
1767 case TBM_FORMAT_ARGB8888:
1768 case TBM_FORMAT_XRGB8888:
1769 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d_%p-%s.%s",
1770 _tbm_surface_internal_get_time(),
1771 g_dump_info->count++, surface, type, postfix);
1772 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1774 case TBM_FORMAT_YVU420:
1775 case TBM_FORMAT_YUV420:
1776 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1777 _tbm_surface_internal_get_time(),
1778 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1779 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1780 bo_handle.ptr += info.planes[0].stride * info.height;
1781 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1782 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1783 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1785 case TBM_FORMAT_NV12:
1786 case TBM_FORMAT_NV21:
1787 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1788 _tbm_surface_internal_get_time(),
1789 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1790 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1791 bo_handle.ptr += info.planes[0].stride * info.height;
1792 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1794 case TBM_FORMAT_YUYV:
1795 case TBM_FORMAT_UYVY:
1796 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1797 _tbm_surface_internal_get_time(),
1798 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1799 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1802 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1803 tbm_bo_unmap(buf_info->bo);
1807 tbm_bo_unmap(buf_info->bo);
1809 tbm_surface_unmap(surface);
1811 buf_info->dirty = 1;
1812 buf_info->dirty_shm = 0;
1814 if (g_dump_info->count == 1000)
1815 g_dump_info->count = 0;
1817 g_dump_info->link = next_link;
1819 TBM_LOG_I("Dump %s \n", buf_info->name);
1822 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride, const char *type)
1824 TBM_RETURN_IF_FAIL(ptr != NULL);
1825 TBM_RETURN_IF_FAIL(w > 0);
1826 TBM_RETURN_IF_FAIL(h > 0);
1827 TBM_RETURN_IF_FAIL(stride > 0);
1828 TBM_RETURN_IF_FAIL(type != NULL);
1830 tbm_surface_dump_buf_info *buf_info;
1831 struct list_head *next_link;
1832 tbm_bo_handle bo_handle;
1837 next_link = g_dump_info->link->next;
1838 TBM_RETURN_IF_FAIL(next_link != NULL);
1840 if (next_link == &g_dump_info->surface_list) {
1841 next_link = next_link->next;
1842 TBM_RETURN_IF_FAIL(next_link != NULL);
1845 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1846 TBM_RETURN_IF_FAIL(buf_info != NULL);
1848 if (stride * h > buf_info->size) {
1849 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n", stride * h, buf_info->size);
1854 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1855 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1856 memset(bo_handle.ptr, 0x00, buf_info->size);
1857 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1859 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1860 _tbm_surface_internal_get_time(),
1861 g_dump_info->count++, type, dump_postfix[0]);
1862 memcpy(bo_handle.ptr, ptr, stride * h);
1864 tbm_bo_unmap(buf_info->bo);
1866 buf_info->dirty = 0;
1867 buf_info->dirty_shm = 1;
1868 buf_info->shm_stride = stride;
1869 buf_info->shm_h = h;
1871 if (g_dump_info->count == 1000)
1872 g_dump_info->count = 0;
1874 g_dump_info->link = next_link;
1876 TBM_LOG_I("Dump %s \n", buf_info->name);