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();\
72 _tbm_surface_internal_get_time(void)
77 clock_gettime(CLOCK_MONOTONIC, &tp);
78 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
84 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
86 LIST_DEL(&debug_data->item_link);
88 if (debug_data->key) free(debug_data->key);
89 if (debug_data->value) free(debug_data->value);
94 _tbm_surface_internal_format_to_str(tbm_format format)
98 return "TBM_FORMAT_C8";
99 case TBM_FORMAT_RGB332:
100 return "TBM_FORMAT_RGB332";
101 case TBM_FORMAT_BGR233:
102 return "TBM_FORMAT_BGR233";
103 case TBM_FORMAT_XRGB4444:
104 return "TBM_FORMAT_XRGB4444";
105 case TBM_FORMAT_XBGR4444:
106 return "TBM_FORMAT_XBGR4444";
107 case TBM_FORMAT_RGBX4444:
108 return "TBM_FORMAT_RGBX4444";
109 case TBM_FORMAT_BGRX4444:
110 return "TBM_FORMAT_BGRX4444";
111 case TBM_FORMAT_ARGB4444:
112 return "TBM_FORMAT_ARGB4444";
113 case TBM_FORMAT_ABGR4444:
114 return "TBM_FORMAT_ABGR4444";
115 case TBM_FORMAT_RGBA4444:
116 return "TBM_FORMAT_RGBA4444";
117 case TBM_FORMAT_BGRA4444:
118 return "TBM_FORMAT_BGRA4444";
119 case TBM_FORMAT_XRGB1555:
120 return "TBM_FORMAT_XRGB1555";
121 case TBM_FORMAT_XBGR1555:
122 return "TBM_FORMAT_XBGR1555";
123 case TBM_FORMAT_RGBX5551:
124 return "TBM_FORMAT_RGBX5551";
125 case TBM_FORMAT_BGRX5551:
126 return "TBM_FORMAT_BGRX5551";
127 case TBM_FORMAT_ARGB1555:
128 return "TBM_FORMAT_ARGB1555";
129 case TBM_FORMAT_ABGR1555:
130 return "TBM_FORMAT_ABGR1555";
131 case TBM_FORMAT_RGBA5551:
132 return "TBM_FORMAT_RGBA5551";
133 case TBM_FORMAT_BGRA5551:
134 return "TBM_FORMAT_BGRA5551";
135 case TBM_FORMAT_RGB565:
136 return "TBM_FORMAT_RGB565";
137 case TBM_FORMAT_BGR565:
138 return "TBM_FORMAT_BGR565";
139 case TBM_FORMAT_RGB888:
140 return "TBM_FORMAT_RGB888";
141 case TBM_FORMAT_BGR888:
142 return "TBM_FORMAT_BGR888";
143 case TBM_FORMAT_XRGB8888:
144 return "TBM_FORMAT_XRGB8888";
145 case TBM_FORMAT_XBGR8888:
146 return "TBM_FORMAT_XBGR8888";
147 case TBM_FORMAT_RGBX8888:
148 return "TBM_FORMAT_RGBX8888";
149 case TBM_FORMAT_BGRX8888:
150 return "TBM_FORMAT_BGRX8888";
151 case TBM_FORMAT_ARGB8888:
152 return "TBM_FORMAT_ARGB8888";
153 case TBM_FORMAT_ABGR8888:
154 return "TBM_FORMAT_ABGR8888";
155 case TBM_FORMAT_RGBA8888:
156 return "TBM_FORMAT_RGBA8888";
157 case TBM_FORMAT_BGRA8888:
158 return "TBM_FORMAT_BGRA8888";
159 case TBM_FORMAT_XRGB2101010:
160 return "TBM_FORMAT_XRGB2101010";
161 case TBM_FORMAT_XBGR2101010:
162 return "TBM_FORMAT_XBGR2101010";
163 case TBM_FORMAT_RGBX1010102:
164 return "TBM_FORMAT_RGBX1010102";
165 case TBM_FORMAT_BGRX1010102:
166 return "TBM_FORMAT_BGRX1010102";
167 case TBM_FORMAT_ARGB2101010:
168 return "TBM_FORMAT_ARGB2101010";
169 case TBM_FORMAT_ABGR2101010:
170 return "TBM_FORMAT_ABGR2101010";
171 case TBM_FORMAT_RGBA1010102:
172 return "TBM_FORMAT_RGBA1010102";
173 case TBM_FORMAT_BGRA1010102:
174 return "TBM_FORMAT_BGRA1010102";
175 case TBM_FORMAT_YUYV:
176 return "TBM_FORMAT_YUYV";
177 case TBM_FORMAT_YVYU:
178 return "TBM_FORMAT_YVYU";
179 case TBM_FORMAT_UYVY:
180 return "TBM_FORMAT_UYVY";
181 case TBM_FORMAT_VYUY:
182 return "TBM_FORMAT_VYUY";
183 case TBM_FORMAT_AYUV:
184 return "TBM_FORMAT_AYUV";
185 case TBM_FORMAT_NV12:
186 return "TBM_FORMAT_NV12";
187 case TBM_FORMAT_NV21:
188 return "TBM_FORMAT_NV21";
189 case TBM_FORMAT_NV16:
190 return "TBM_FORMAT_NV16";
191 case TBM_FORMAT_NV61:
192 return "TBM_FORMAT_NV61";
193 case TBM_FORMAT_YUV410:
194 return "TBM_FORMAT_YUV410";
195 case TBM_FORMAT_YVU410:
196 return "TBM_FORMAT_YVU410";
197 case TBM_FORMAT_YUV411:
198 return "TBM_FORMAT_YUV411";
199 case TBM_FORMAT_YVU411:
200 return "TBM_FORMAT_YVU411";
201 case TBM_FORMAT_YUV420:
202 return "TBM_FORMAT_YUV420";
203 case TBM_FORMAT_YVU420:
204 return "TBM_FORMAT_YVU420";
205 case TBM_FORMAT_YUV422:
206 return "TBM_FORMAT_YUV422";
207 case TBM_FORMAT_YVU422:
208 return "TBM_FORMAT_YVU422";
209 case TBM_FORMAT_YUV444:
210 return "TBM_FORMAT_YUV444";
211 case TBM_FORMAT_YVU444:
212 return "TBM_FORMAT_YVU444";
213 case TBM_FORMAT_NV12MT:
214 return "TBM_FORMAT_NV12MT";
222 _tbm_surface_mutex_init(void)
224 static bool tbm_surface_mutex_init = false;
226 if (tbm_surface_mutex_init)
229 if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
230 TBM_LOG_E("fail: tbm_surface mutex init\n");
234 tbm_surface_mutex_init = true;
240 _tbm_surface_mutex_lock(void)
242 if (!_tbm_surface_mutex_init())
245 pthread_mutex_lock(&tbm_surface_lock);
249 _tbm_surface_mutex_unlock(void)
251 pthread_mutex_unlock(&tbm_surface_lock);
255 _init_surface_bufmgr(void)
257 g_surface_bufmgr = tbm_bufmgr_init(-1);
261 _deinit_surface_bufmgr(void)
263 if (!g_surface_bufmgr)
266 tbm_bufmgr_deinit(g_surface_bufmgr);
267 g_surface_bufmgr = NULL;
271 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
272 int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
274 TBM_RETURN_VAL_IF_FAIL(surface, 0);
275 TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
277 struct _tbm_surface *surf = (struct _tbm_surface *)surface;
278 struct _tbm_bufmgr *mgr = surf->bufmgr;
281 TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
282 TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
283 TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
284 TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
286 if (!mgr->backend->surface_get_plane_data)
289 ret = mgr->backend->surface_get_plane_data(surf->info.width,
290 surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
298 _tbm_surface_internal_destroy(tbm_surface_h surface)
301 tbm_bufmgr bufmgr = surface->bufmgr;
302 tbm_user_data *old_data = NULL, *tmp = NULL;
303 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
305 /* destory the user_data_list */
306 if (!LIST_IS_EMPTY(&surface->user_data_list)) {
307 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
308 TBM_DBG("free user_data\n");
309 user_data_delete(old_data);
313 for (i = 0; i < surface->num_bos; i++) {
314 surface->bos[i]->surface = NULL;
316 tbm_bo_unref(surface->bos[i]);
317 surface->bos[i] = NULL;
320 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
321 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
322 _tbm_surface_internal_debug_data_delete(debug_old_data);
325 LIST_DEL(&surface->item_link);
330 if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
331 LIST_DELINIT(&bufmgr->surf_list);
333 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
334 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
335 _tbm_surface_internal_debug_data_delete(debug_old_data);
339 _deinit_surface_bufmgr();
344 tbm_surface_internal_is_valid(tbm_surface_h surface)
346 tbm_surface_h old_data = NULL, tmp = NULL;
348 if (surface == NULL || g_surface_bufmgr == NULL) {
349 TBM_TRACE("error: tbm_surface(%p)\n", surface);
353 if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
354 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &g_surface_bufmgr->surf_list, item_link) {
355 if (old_data == surface) {
356 TBM_TRACE("tbm_surface(%p)\n", surface);
361 TBM_TRACE("error: tbm_surface(%p)\n", surface);
366 tbm_surface_internal_query_supported_formats(uint32_t **formats,
369 struct _tbm_bufmgr *mgr;
372 _tbm_surface_mutex_lock();
374 if (!g_surface_bufmgr) {
375 _init_surface_bufmgr();
376 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
379 mgr = g_surface_bufmgr;
381 if (!mgr->backend->surface_supported_format) {
382 TBM_TRACE("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
383 _tbm_surface_mutex_unlock();
387 ret = mgr->backend->surface_supported_format(formats, num);
389 TBM_TRACE("tbm_bufmgr(%p) format num(%d)\n", g_surface_bufmgr, *num);
391 _tbm_surface_mutex_unlock();
397 tbm_surface_internal_get_num_planes(tbm_format format)
403 case TBM_FORMAT_RGB332:
404 case TBM_FORMAT_BGR233:
405 case TBM_FORMAT_XRGB4444:
406 case TBM_FORMAT_XBGR4444:
407 case TBM_FORMAT_RGBX4444:
408 case TBM_FORMAT_BGRX4444:
409 case TBM_FORMAT_ARGB4444:
410 case TBM_FORMAT_ABGR4444:
411 case TBM_FORMAT_RGBA4444:
412 case TBM_FORMAT_BGRA4444:
413 case TBM_FORMAT_XRGB1555:
414 case TBM_FORMAT_XBGR1555:
415 case TBM_FORMAT_RGBX5551:
416 case TBM_FORMAT_BGRX5551:
417 case TBM_FORMAT_ARGB1555:
418 case TBM_FORMAT_ABGR1555:
419 case TBM_FORMAT_RGBA5551:
420 case TBM_FORMAT_BGRA5551:
421 case TBM_FORMAT_RGB565:
422 case TBM_FORMAT_BGR565:
423 case TBM_FORMAT_RGB888:
424 case TBM_FORMAT_BGR888:
425 case TBM_FORMAT_XRGB8888:
426 case TBM_FORMAT_XBGR8888:
427 case TBM_FORMAT_RGBX8888:
428 case TBM_FORMAT_BGRX8888:
429 case TBM_FORMAT_ARGB8888:
430 case TBM_FORMAT_ABGR8888:
431 case TBM_FORMAT_RGBA8888:
432 case TBM_FORMAT_BGRA8888:
433 case TBM_FORMAT_XRGB2101010:
434 case TBM_FORMAT_XBGR2101010:
435 case TBM_FORMAT_RGBX1010102:
436 case TBM_FORMAT_BGRX1010102:
437 case TBM_FORMAT_ARGB2101010:
438 case TBM_FORMAT_ABGR2101010:
439 case TBM_FORMAT_RGBA1010102:
440 case TBM_FORMAT_BGRA1010102:
441 case TBM_FORMAT_YUYV:
442 case TBM_FORMAT_YVYU:
443 case TBM_FORMAT_UYVY:
444 case TBM_FORMAT_VYUY:
445 case TBM_FORMAT_AYUV:
448 case TBM_FORMAT_NV12:
449 case TBM_FORMAT_NV12MT:
450 case TBM_FORMAT_NV21:
451 case TBM_FORMAT_NV16:
452 case TBM_FORMAT_NV61:
455 case TBM_FORMAT_YUV410:
456 case TBM_FORMAT_YVU410:
457 case TBM_FORMAT_YUV411:
458 case TBM_FORMAT_YVU411:
459 case TBM_FORMAT_YUV420:
460 case TBM_FORMAT_YVU420:
461 case TBM_FORMAT_YUV422:
462 case TBM_FORMAT_YVU422:
463 case TBM_FORMAT_YUV444:
464 case TBM_FORMAT_YVU444:
472 TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
478 tbm_surface_internal_get_bpp(tbm_format format)
485 case TBM_FORMAT_RGB332:
486 case TBM_FORMAT_BGR233:
489 case TBM_FORMAT_XRGB4444:
490 case TBM_FORMAT_XBGR4444:
491 case TBM_FORMAT_RGBX4444:
492 case TBM_FORMAT_BGRX4444:
493 case TBM_FORMAT_ARGB4444:
494 case TBM_FORMAT_ABGR4444:
495 case TBM_FORMAT_RGBA4444:
496 case TBM_FORMAT_BGRA4444:
497 case TBM_FORMAT_XRGB1555:
498 case TBM_FORMAT_XBGR1555:
499 case TBM_FORMAT_RGBX5551:
500 case TBM_FORMAT_BGRX5551:
501 case TBM_FORMAT_ARGB1555:
502 case TBM_FORMAT_ABGR1555:
503 case TBM_FORMAT_RGBA5551:
504 case TBM_FORMAT_BGRA5551:
505 case TBM_FORMAT_RGB565:
506 case TBM_FORMAT_BGR565:
509 case TBM_FORMAT_RGB888:
510 case TBM_FORMAT_BGR888:
513 case TBM_FORMAT_XRGB8888:
514 case TBM_FORMAT_XBGR8888:
515 case TBM_FORMAT_RGBX8888:
516 case TBM_FORMAT_BGRX8888:
517 case TBM_FORMAT_ARGB8888:
518 case TBM_FORMAT_ABGR8888:
519 case TBM_FORMAT_RGBA8888:
520 case TBM_FORMAT_BGRA8888:
521 case TBM_FORMAT_XRGB2101010:
522 case TBM_FORMAT_XBGR2101010:
523 case TBM_FORMAT_RGBX1010102:
524 case TBM_FORMAT_BGRX1010102:
525 case TBM_FORMAT_ARGB2101010:
526 case TBM_FORMAT_ABGR2101010:
527 case TBM_FORMAT_RGBA1010102:
528 case TBM_FORMAT_BGRA1010102:
529 case TBM_FORMAT_YUYV:
530 case TBM_FORMAT_YVYU:
531 case TBM_FORMAT_UYVY:
532 case TBM_FORMAT_VYUY:
533 case TBM_FORMAT_AYUV:
536 case TBM_FORMAT_NV12:
537 case TBM_FORMAT_NV12MT:
538 case TBM_FORMAT_NV21:
541 case TBM_FORMAT_NV16:
542 case TBM_FORMAT_NV61:
545 case TBM_FORMAT_YUV410:
546 case TBM_FORMAT_YVU410:
549 case TBM_FORMAT_YUV411:
550 case TBM_FORMAT_YVU411:
551 case TBM_FORMAT_YUV420:
552 case TBM_FORMAT_YVU420:
555 case TBM_FORMAT_YUV422:
556 case TBM_FORMAT_YVU422:
559 case TBM_FORMAT_YUV444:
560 case TBM_FORMAT_YVU444:
567 TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
573 tbm_surface_internal_create_with_flags(int width, int height,
574 int format, int flags)
576 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
577 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
579 struct _tbm_bufmgr *mgr;
580 struct _tbm_surface *surf = NULL;
584 uint32_t bo_size = 0;
588 _tbm_surface_mutex_lock();
590 if (!g_surface_bufmgr) {
591 _init_surface_bufmgr();
592 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
595 mgr = g_surface_bufmgr;
596 if (!TBM_BUFMGR_IS_VALID(mgr)) {
597 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
598 width, height, _tbm_surface_internal_format_to_str(format), flags);
599 _tbm_surface_mutex_unlock();
602 surf = calloc(1, sizeof(struct _tbm_surface));
604 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
605 width, height, _tbm_surface_internal_format_to_str(format), flags);
606 _tbm_surface_mutex_unlock();
611 surf->info.width = width;
612 surf->info.height = height;
613 surf->info.format = format;
614 surf->info.bpp = tbm_surface_internal_get_bpp(format);
615 surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
618 /* get size, stride and offset bo_idx */
619 for (i = 0; i < surf->info.num_planes; i++) {
620 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride,
622 surf->info.planes[i].size = size;
623 surf->info.planes[i].offset = offset;
624 surf->info.planes[i].stride = stride;
625 surf->planes_bo_idx[i] = bo_idx;
630 for (i = 0; i < surf->info.num_planes; i++) {
631 surf->info.size += surf->info.planes[i].size;
633 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
634 surf->num_bos = surf->planes_bo_idx[i] + 1;
639 for (i = 0; i < surf->num_bos; i++) {
641 for (j = 0; j < surf->info.num_planes; j++) {
642 if (surf->planes_bo_idx[j] == i)
643 bo_size += surf->info.planes[j].size;
646 if (mgr->backend->surface_bo_alloc) {
647 /* LCOV_EXCL_START */
649 void *bo_priv = NULL;
651 bo = calloc(1, sizeof(struct _tbm_bo));
653 TBM_LOG_E("fail to alloc bo struct\n");
657 bo->bufmgr = surf->bufmgr;
659 pthread_mutex_lock(&surf->bufmgr->lock);
661 bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
663 TBM_LOG_E("fail to alloc bo priv\n");
665 pthread_mutex_unlock(&surf->bufmgr->lock);
673 LIST_INITHEAD(&bo->user_data_list);
675 LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
677 pthread_mutex_unlock(&surf->bufmgr->lock);
682 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
686 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
690 _tbm_bo_set_surface(surf->bos[i], surf);
694 TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
695 _tbm_surface_internal_format_to_str(format), flags, surf);
697 LIST_INITHEAD(&surf->user_data_list);
698 LIST_INITHEAD(&surf->debug_data_list);
700 LIST_ADD(&surf->item_link, &mgr->surf_list);
702 _tbm_surface_mutex_unlock();
708 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
709 width, height, _tbm_surface_internal_format_to_str(format), flags);
711 for (j = 0; j < i; j++) {
713 tbm_bo_unref(surf->bos[j]);
719 if (LIST_IS_EMPTY(&mgr->surf_list)) {
720 LIST_DELINIT(&mgr->surf_list);
721 _deinit_surface_bufmgr();
724 _tbm_surface_mutex_unlock();
729 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
730 tbm_bo *bos, int num)
732 TBM_RETURN_VAL_IF_FAIL(bos, NULL);
733 TBM_RETURN_VAL_IF_FAIL(info, NULL);
734 TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
736 struct _tbm_bufmgr *mgr;
737 struct _tbm_surface *surf = NULL;
740 _tbm_surface_mutex_lock();
742 if (!g_surface_bufmgr) {
743 _init_surface_bufmgr();
744 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
747 mgr = g_surface_bufmgr;
748 if (!TBM_BUFMGR_IS_VALID(mgr)) {
749 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
750 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
751 _tbm_surface_mutex_unlock();
755 surf = calloc(1, sizeof(struct _tbm_surface));
757 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
758 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
759 _tbm_surface_mutex_unlock();
764 surf->info.width = info->width;
765 surf->info.height = info->height;
766 surf->info.format = info->format;
767 surf->info.bpp = info->bpp;
768 surf->info.num_planes = info->num_planes;
771 /* get size, stride and offset */
772 for (i = 0; i < info->num_planes; i++) {
773 surf->info.planes[i].offset = info->planes[i].offset;
774 surf->info.planes[i].stride = info->planes[i].stride;
776 if (info->planes[i].size > 0)
777 surf->info.planes[i].size = info->planes[i].size;
779 surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
782 surf->planes_bo_idx[i] = 0;
784 surf->planes_bo_idx[i] = i;
787 if (info->size > 0) {
788 surf->info.size = info->size;
791 for (i = 0; i < info->num_planes; i++)
792 surf->info.size += surf->info.planes[i].size;
795 surf->flags = TBM_BO_DEFAULT;
797 /* create only one bo */
799 for (i = 0; i < num; i++) {
803 surf->bos[i] = tbm_bo_ref(bos[i]);
804 _tbm_bo_set_surface(bos[i], surf);
807 TBM_TRACE("tbm_surface(%p) width(%d) height(%d) format(%s) bo_num(%d)\n", surf,
808 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
810 LIST_INITHEAD(&surf->user_data_list);
811 LIST_INITHEAD(&surf->debug_data_list);
813 LIST_ADD(&surf->item_link, &mgr->surf_list);
815 _tbm_surface_mutex_unlock();
819 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
820 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
821 for (i = 0; i < num; i++) {
823 tbm_bo_unref(surf->bos[i]);
831 if (LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
832 LIST_DELINIT(&g_surface_bufmgr->surf_list);
833 _deinit_surface_bufmgr();
836 _tbm_surface_mutex_unlock();
842 tbm_surface_internal_destroy(tbm_surface_h surface)
844 _tbm_surface_mutex_lock();
846 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
850 if (surface->refcnt > 0) {
851 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
852 _tbm_surface_mutex_unlock();
856 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
858 if (surface->refcnt == 0)
859 _tbm_surface_internal_destroy(surface);
861 _tbm_surface_mutex_unlock();
865 tbm_surface_internal_ref(tbm_surface_h surface)
867 _tbm_surface_mutex_lock();
869 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
873 TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
875 _tbm_surface_mutex_unlock();
879 tbm_surface_internal_unref(tbm_surface_h surface)
881 _tbm_surface_mutex_lock();
883 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
887 if (surface->refcnt > 0) {
888 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
889 _tbm_surface_mutex_unlock();
893 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
895 if (surface->refcnt == 0)
896 _tbm_surface_internal_destroy(surface);
898 _tbm_surface_mutex_unlock();
902 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
904 struct _tbm_surface *surf;
907 _tbm_surface_mutex_lock();
909 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
911 surf = (struct _tbm_surface *)surface;
914 TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
916 _tbm_surface_mutex_unlock();
922 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
924 struct _tbm_surface *surf;
927 _tbm_surface_mutex_lock();
929 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), NULL);
930 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
932 surf = (struct _tbm_surface *)surface;
933 bo = surf->bos[bo_idx];
935 TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
937 _tbm_surface_mutex_unlock();
943 tbm_surface_internal_get_size(tbm_surface_h surface)
945 struct _tbm_surface *surf;
948 _tbm_surface_mutex_lock();
950 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
952 surf = (struct _tbm_surface *)surface;
953 size = surf->info.size;
955 TBM_TRACE("tbm_surface(%p) size(%d)\n", surface, size);
957 _tbm_surface_mutex_unlock();
963 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
964 uint32_t *size, uint32_t *offset, uint32_t *pitch)
966 struct _tbm_surface *surf;
968 _tbm_surface_mutex_lock();
970 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
971 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
973 surf = (struct _tbm_surface *)surface;
975 if (plane_idx >= surf->info.num_planes) {
976 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
977 _tbm_surface_mutex_unlock();
982 *size = surf->info.planes[plane_idx].size;
985 *offset = surf->info.planes[plane_idx].offset;
988 *pitch = surf->info.planes[plane_idx].stride;
990 TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%d) offset(%d) pitch(%d)\n", surface, plane_idx,
991 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
992 surf->info.planes[plane_idx].stride);
994 _tbm_surface_mutex_unlock();
1000 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1001 tbm_surface_info_s *info, int map)
1003 struct _tbm_surface *surf;
1004 tbm_bo_handle bo_handles[4];
1007 _tbm_surface_mutex_lock();
1009 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1011 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1013 surf = (struct _tbm_surface *)surface;
1015 memset(info, 0x00, sizeof(tbm_surface_info_s));
1016 info->width = surf->info.width;
1017 info->height = surf->info.height;
1018 info->format = surf->info.format;
1019 info->bpp = surf->info.bpp;
1020 info->size = surf->info.size;
1021 info->num_planes = surf->info.num_planes;
1024 for (i = 0; i < surf->num_bos; i++) {
1025 bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1026 if (bo_handles[i].ptr == NULL) {
1027 for (j = 0; j < i; j++)
1028 tbm_bo_unmap(surf->bos[j]);
1030 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1031 _tbm_surface_mutex_unlock();
1036 for (i = 0; i < surf->num_bos; i++)
1037 bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1040 for (i = 0; i < surf->info.num_planes; i++) {
1041 info->planes[i].size = surf->info.planes[i].size;
1042 info->planes[i].offset = surf->info.planes[i].offset;
1043 info->planes[i].stride = surf->info.planes[i].stride;
1045 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1046 info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1047 surf->info.planes[i].offset;
1050 TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1052 _tbm_surface_mutex_unlock();
1058 tbm_surface_internal_unmap(tbm_surface_h surface)
1060 struct _tbm_surface *surf;
1063 _tbm_surface_mutex_lock();
1065 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1067 surf = (struct _tbm_surface *)surface;
1069 for (i = 0; i < surf->num_bos; i++)
1070 tbm_bo_unmap(surf->bos[i]);
1072 TBM_TRACE("tbm_surface(%p)\n", surface);
1074 _tbm_surface_mutex_unlock();
1078 tbm_surface_internal_get_width(tbm_surface_h surface)
1080 struct _tbm_surface *surf;
1083 _tbm_surface_mutex_lock();
1085 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1087 surf = (struct _tbm_surface *)surface;
1088 width = surf->info.width;
1090 TBM_TRACE("tbm_surface(%p) width(%d)\n", surface, width);
1092 _tbm_surface_mutex_unlock();
1098 tbm_surface_internal_get_height(tbm_surface_h surface)
1100 struct _tbm_surface *surf;
1101 unsigned int height;
1103 _tbm_surface_mutex_lock();
1105 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1107 surf = (struct _tbm_surface *)surface;
1108 height = surf->info.height;
1110 TBM_TRACE("tbm_surface(%p) height(%d)\n", surface, height);
1112 _tbm_surface_mutex_unlock();
1119 tbm_surface_internal_get_format(tbm_surface_h surface)
1121 struct _tbm_surface *surf;
1124 _tbm_surface_mutex_lock();
1126 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1128 surf = (struct _tbm_surface *)surface;
1129 format = surf->info.format;
1131 TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1133 _tbm_surface_mutex_unlock();
1139 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1141 struct _tbm_surface *surf;
1144 _tbm_surface_mutex_lock();
1146 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1147 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1149 surf = (struct _tbm_surface *)surface;
1150 bo_idx = surf->planes_bo_idx[plane_idx];
1152 TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1154 _tbm_surface_mutex_unlock();
1160 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1161 tbm_data_free data_free_func)
1163 tbm_user_data *data;
1165 _tbm_surface_mutex_lock();
1167 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1169 /* check if the data according to the key exist if so, return false. */
1170 data = user_data_lookup(&surface->user_data_list, key);
1172 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1173 _tbm_surface_mutex_unlock();
1177 data = user_data_create(key, data_free_func);
1179 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1180 _tbm_surface_mutex_unlock();
1184 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1186 LIST_ADD(&data->item_link, &surface->user_data_list);
1188 _tbm_surface_mutex_unlock();
1194 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1197 tbm_user_data *old_data;
1199 _tbm_surface_mutex_lock();
1201 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1203 if (LIST_IS_EMPTY(&surface->user_data_list)) {
1204 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1205 _tbm_surface_mutex_unlock();
1209 old_data = user_data_lookup(&surface->user_data_list, key);
1211 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1212 _tbm_surface_mutex_unlock();
1216 if (old_data->data && old_data->free_func)
1217 old_data->free_func(old_data->data);
1219 old_data->data = data;
1221 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1223 _tbm_surface_mutex_unlock();
1229 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1232 tbm_user_data *old_data;
1234 _tbm_surface_mutex_lock();
1236 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1238 if (!data || LIST_IS_EMPTY(&surface->user_data_list)) {
1239 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1240 _tbm_surface_mutex_unlock();
1244 old_data = user_data_lookup(&surface->user_data_list, key);
1246 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1248 _tbm_surface_mutex_unlock();
1252 *data = old_data->data;
1254 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1256 _tbm_surface_mutex_unlock();
1262 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1265 tbm_user_data *old_data = (void *)0;
1267 _tbm_surface_mutex_lock();
1269 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1271 if (LIST_IS_EMPTY(&surface->user_data_list)) {
1272 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1273 _tbm_surface_mutex_unlock();
1277 old_data = user_data_lookup(&surface->user_data_list, key);
1279 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1280 _tbm_surface_mutex_unlock();
1284 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1286 user_data_delete(old_data);
1288 _tbm_surface_mutex_unlock();
1293 /* LCOV_EXCL_START */
1295 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1297 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1299 return surface->debug_pid;
1303 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1305 _tbm_surface_mutex_lock();
1307 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1309 surface->debug_pid = pid;
1311 _tbm_surface_mutex_unlock();
1314 static tbm_surface_debug_data *
1315 _tbm_surface_internal_debug_data_create(char *key, char *value)
1317 tbm_surface_debug_data *debug_data = NULL;
1319 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1323 if (key) debug_data->key = strdup(key);
1324 if (value) debug_data->value = strdup(value);
1330 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1332 tbm_surface_debug_data *debug_data = NULL;
1333 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1334 tbm_bufmgr bufmgr = NULL;
1336 _tbm_surface_mutex_lock();
1338 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1339 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1341 bufmgr = surface->bufmgr;
1343 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1345 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1346 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1347 if (!strcmp(old_data->key, key)) {
1349 old_data->value = strdup(value);
1351 old_data->value = NULL;
1356 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1358 TBM_TRACE("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1359 _tbm_surface_mutex_unlock();
1363 TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1365 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1367 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1368 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1369 if (!strcmp(old_data->key, key)) {
1370 _tbm_surface_mutex_unlock();
1376 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1377 LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1379 _tbm_surface_mutex_unlock();
1385 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1387 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1389 _tbm_surface_mutex_lock();
1391 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1393 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1394 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1395 if (!strcmp(old_data->key, key)) {
1396 _tbm_surface_mutex_unlock();
1397 return old_data->value;
1402 _tbm_surface_mutex_unlock();
1407 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1408 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1410 struct _tbm_surface_dump_buf_info {
1420 tbm_surface_info_s info;
1422 struct list_head link;
1425 struct _tbm_surface_dump_info {
1426 char *path; // copy???
1429 struct list_head *link;
1430 struct list_head surface_list; /* link of surface */
1433 static tbm_surface_dump_info *g_dump_info = NULL;
1434 static const char *dump_postfix[2] = {"png", "yuv"};
1437 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1, void *data2,
1438 int size2, void *data3, int size3)
1440 unsigned int *blocks;
1441 FILE *fp = fopen(file, "w+");
1442 TBM_RETURN_IF_FAIL(fp != NULL);
1444 blocks = (unsigned int *)data1;
1445 fwrite(blocks, 1, size1, fp);
1448 blocks = (unsigned int *)data2;
1449 fwrite(blocks, 1, size2, fp);
1453 blocks = (unsigned int *)data3;
1454 fwrite(blocks, 1, size3, fp);
1461 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width,
1464 FILE *fp = fopen(file, "wb");
1465 TBM_RETURN_IF_FAIL(fp != NULL);
1468 png_structp pPngStruct =
1469 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1475 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1477 png_destroy_write_struct(&pPngStruct, NULL);
1482 png_init_io(pPngStruct, fp);
1483 png_set_IHDR(pPngStruct,
1488 PNG_COLOR_TYPE_RGBA,
1490 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1492 png_set_bgr(pPngStruct);
1493 png_write_info(pPngStruct, pPngInfo);
1495 const int pixel_size = 4; // RGBA
1496 png_bytep *row_pointers =
1497 png_malloc(pPngStruct, height * sizeof(png_byte *));
1499 unsigned int *blocks = (unsigned int *)data;
1503 for (; y < height; ++y) {
1505 png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1506 row_pointers[y] = (png_bytep)row;
1507 for (x = 0; x < width; ++x) {
1508 unsigned int curBlock = blocks[y * width + x];
1509 row[x * pixel_size] = (curBlock & 0xFF);
1510 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1511 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1512 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1516 png_write_image(pPngStruct, row_pointers);
1517 png_write_end(pPngStruct, pPngInfo);
1519 for (y = 0; y < height; y++)
1520 png_free(pPngStruct, row_pointers[y]);
1521 png_free(pPngStruct, row_pointers);
1523 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1529 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1531 TBM_RETURN_IF_FAIL(path != NULL);
1532 TBM_RETURN_IF_FAIL(w > 0);
1533 TBM_RETURN_IF_FAIL(h > 0);
1534 TBM_RETURN_IF_FAIL(count > 0);
1536 tbm_surface_dump_buf_info *buf_info = NULL;
1537 tbm_surface_dump_buf_info *tmp;
1541 tbm_surface_h tbm_surface;
1542 tbm_surface_info_s info;
1543 tbm_surface_error_e err;
1547 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1551 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1552 TBM_RETURN_IF_FAIL(g_dump_info);
1554 LIST_INITHEAD(&g_dump_info->surface_list);
1555 g_dump_info->count = 0;
1556 g_dump_info->dump_max = count;
1558 /* get buffer size */
1559 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1560 if (tbm_surface == NULL) {
1561 TBM_LOG_E("tbm_surface_create fail\n");
1566 err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
1567 if (err != TBM_SURFACE_ERROR_NONE) {
1568 TBM_LOG_E("tbm_surface_map fail\n");
1569 tbm_surface_destroy(tbm_surface);
1574 buffer_size = info.planes[0].stride * h;
1575 tbm_surface_unmap(tbm_surface);
1576 tbm_surface_destroy(tbm_surface);
1578 /* create dump lists */
1579 for (i = 0; i < count; i++) {
1580 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1581 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1582 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1588 buf_info->index = i;
1590 buf_info->size = buffer_size;
1592 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1595 g_dump_info->path = path;
1596 g_dump_info->link = &g_dump_info->surface_list;
1598 TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1602 /* free resources */
1603 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1604 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1605 tbm_bo_unref(buf_info->bo);
1610 TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1619 tbm_surface_internal_dump_end(void)
1621 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1622 tbm_bo_handle bo_handle;
1628 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1629 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1632 if (buf_info->dirty) {
1636 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1637 if (bo_handle.ptr == NULL)
1640 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1641 TBM_LOG_I("Dump File.. %s generated.\n", file);
1643 switch (buf_info->info.format) {
1644 case TBM_FORMAT_ARGB8888:
1645 case TBM_FORMAT_XRGB8888:
1646 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1647 buf_info->info.planes[0].stride >> 2, buf_info->info.height);
1649 case TBM_FORMAT_YVU420:
1650 case TBM_FORMAT_YUV420:
1651 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1652 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1653 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1654 buf_info->info.planes[0].stride * buf_info->info.height,
1656 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1658 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1660 case TBM_FORMAT_NV12:
1661 case TBM_FORMAT_NV21:
1662 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1663 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1664 buf_info->info.planes[0].stride * buf_info->info.height,
1666 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1669 case TBM_FORMAT_YUYV:
1670 case TBM_FORMAT_UYVY:
1671 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1672 buf_info->info.planes[0].stride * buf_info->info.height,
1676 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1677 tbm_bo_unmap(buf_info->bo);
1681 tbm_bo_unmap(buf_info->bo);
1682 } else if (buf_info->dirty_shm) {
1683 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1684 if (bo_handle.ptr == NULL)
1687 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1688 TBM_LOG_I("Dump File.. %s generated.\n", file);
1690 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1691 buf_info->shm_stride >> 2, buf_info->shm_h);
1693 tbm_bo_unmap(buf_info->bo);
1698 /* free resources */
1699 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1700 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1701 tbm_bo_unref(buf_info->bo);
1709 TBM_LOG_I("Dump End..\n");
1713 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1715 TBM_RETURN_IF_FAIL(surface != NULL);
1716 TBM_RETURN_IF_FAIL(type != NULL);
1718 tbm_surface_dump_buf_info *buf_info;
1719 tbm_surface_info_s info;
1720 struct list_head *next_link;
1721 tbm_bo_handle bo_handle;
1723 const char *postfix;
1728 next_link = g_dump_info->link->next;
1729 TBM_RETURN_IF_FAIL(next_link != NULL);
1731 if (next_link == &g_dump_info->surface_list) {
1732 next_link = next_link->next;
1733 TBM_RETURN_IF_FAIL(next_link != NULL);
1736 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1737 TBM_RETURN_IF_FAIL(buf_info != NULL);
1739 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1740 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1742 if (info.size > buf_info->size) {
1743 TBM_LOG_W("Dump skip. surface over created buffer size(%d, %d)\n", info.size, buf_info->size);
1744 tbm_surface_unmap(surface);
1748 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1749 postfix = dump_postfix[0];
1751 postfix = dump_postfix[1];
1753 /* make the file information */
1754 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1757 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1758 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1759 memset(bo_handle.ptr, 0x00, buf_info->size);
1761 switch (info.format) {
1762 case TBM_FORMAT_ARGB8888:
1763 case TBM_FORMAT_XRGB8888:
1764 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d_%p-%s.%s",
1765 _tbm_surface_internal_get_time(),
1766 g_dump_info->count++, surface, type, postfix);
1767 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1769 case TBM_FORMAT_YVU420:
1770 case TBM_FORMAT_YUV420:
1771 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1772 _tbm_surface_internal_get_time(),
1773 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1774 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1775 bo_handle.ptr += info.planes[0].stride * info.height;
1776 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1777 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1778 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1780 case TBM_FORMAT_NV12:
1781 case TBM_FORMAT_NV21:
1782 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1783 _tbm_surface_internal_get_time(),
1784 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1785 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1786 bo_handle.ptr += info.planes[0].stride * info.height;
1787 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1789 case TBM_FORMAT_YUYV:
1790 case TBM_FORMAT_UYVY:
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);
1797 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1798 tbm_bo_unmap(buf_info->bo);
1802 tbm_bo_unmap(buf_info->bo);
1804 tbm_surface_unmap(surface);
1806 buf_info->dirty = 1;
1807 buf_info->dirty_shm = 0;
1809 if (g_dump_info->count == 1000)
1810 g_dump_info->count = 0;
1812 g_dump_info->link = next_link;
1814 TBM_LOG_I("Dump %s \n", buf_info->name);
1817 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride, const char *type)
1819 TBM_RETURN_IF_FAIL(ptr != NULL);
1820 TBM_RETURN_IF_FAIL(w > 0);
1821 TBM_RETURN_IF_FAIL(h > 0);
1822 TBM_RETURN_IF_FAIL(stride > 0);
1823 TBM_RETURN_IF_FAIL(type != NULL);
1825 tbm_surface_dump_buf_info *buf_info;
1826 struct list_head *next_link;
1827 tbm_bo_handle bo_handle;
1832 next_link = g_dump_info->link->next;
1833 TBM_RETURN_IF_FAIL(next_link != NULL);
1835 if (next_link == &g_dump_info->surface_list) {
1836 next_link = next_link->next;
1837 TBM_RETURN_IF_FAIL(next_link != NULL);
1840 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1841 TBM_RETURN_IF_FAIL(buf_info != NULL);
1843 if (stride * h > buf_info->size) {
1844 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n", stride * h, buf_info->size);
1849 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1850 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1851 memset(bo_handle.ptr, 0x00, buf_info->size);
1852 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1854 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1855 _tbm_surface_internal_get_time(),
1856 g_dump_info->count++, type, dump_postfix[0]);
1857 memcpy(bo_handle.ptr, ptr, stride * h);
1859 tbm_bo_unmap(buf_info->bo);
1861 buf_info->dirty = 0;
1862 buf_info->dirty_shm = 1;
1863 buf_info->shm_stride = stride;
1864 buf_info->shm_h = h;
1866 if (g_dump_info->count == 1000)
1867 g_dump_info->count = 0;
1869 g_dump_info->link = next_link;
1871 TBM_LOG_I("Dump %s \n", buf_info->name);