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;
373 _tbm_surface_mutex_lock();
375 if (!g_surface_bufmgr) {
376 _init_surface_bufmgr();
377 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
380 mgr = g_surface_bufmgr;
382 if (!mgr->backend->surface_supported_format) {
383 TBM_TRACE("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
384 _tbm_surface_mutex_unlock();
388 ret = mgr->backend->surface_supported_format(formats, num);
390 TBM_TRACE("tbm_bufmgr(%p) format num(%d)\n", g_surface_bufmgr, *num);
392 _tbm_surface_mutex_unlock();
398 tbm_surface_internal_get_num_planes(tbm_format format)
404 case TBM_FORMAT_RGB332:
405 case TBM_FORMAT_BGR233:
406 case TBM_FORMAT_XRGB4444:
407 case TBM_FORMAT_XBGR4444:
408 case TBM_FORMAT_RGBX4444:
409 case TBM_FORMAT_BGRX4444:
410 case TBM_FORMAT_ARGB4444:
411 case TBM_FORMAT_ABGR4444:
412 case TBM_FORMAT_RGBA4444:
413 case TBM_FORMAT_BGRA4444:
414 case TBM_FORMAT_XRGB1555:
415 case TBM_FORMAT_XBGR1555:
416 case TBM_FORMAT_RGBX5551:
417 case TBM_FORMAT_BGRX5551:
418 case TBM_FORMAT_ARGB1555:
419 case TBM_FORMAT_ABGR1555:
420 case TBM_FORMAT_RGBA5551:
421 case TBM_FORMAT_BGRA5551:
422 case TBM_FORMAT_RGB565:
423 case TBM_FORMAT_BGR565:
424 case TBM_FORMAT_RGB888:
425 case TBM_FORMAT_BGR888:
426 case TBM_FORMAT_XRGB8888:
427 case TBM_FORMAT_XBGR8888:
428 case TBM_FORMAT_RGBX8888:
429 case TBM_FORMAT_BGRX8888:
430 case TBM_FORMAT_ARGB8888:
431 case TBM_FORMAT_ABGR8888:
432 case TBM_FORMAT_RGBA8888:
433 case TBM_FORMAT_BGRA8888:
434 case TBM_FORMAT_XRGB2101010:
435 case TBM_FORMAT_XBGR2101010:
436 case TBM_FORMAT_RGBX1010102:
437 case TBM_FORMAT_BGRX1010102:
438 case TBM_FORMAT_ARGB2101010:
439 case TBM_FORMAT_ABGR2101010:
440 case TBM_FORMAT_RGBA1010102:
441 case TBM_FORMAT_BGRA1010102:
442 case TBM_FORMAT_YUYV:
443 case TBM_FORMAT_YVYU:
444 case TBM_FORMAT_UYVY:
445 case TBM_FORMAT_VYUY:
446 case TBM_FORMAT_AYUV:
449 case TBM_FORMAT_NV12:
450 case TBM_FORMAT_NV12MT:
451 case TBM_FORMAT_NV21:
452 case TBM_FORMAT_NV16:
453 case TBM_FORMAT_NV61:
456 case TBM_FORMAT_YUV410:
457 case TBM_FORMAT_YVU410:
458 case TBM_FORMAT_YUV411:
459 case TBM_FORMAT_YVU411:
460 case TBM_FORMAT_YUV420:
461 case TBM_FORMAT_YVU420:
462 case TBM_FORMAT_YUV422:
463 case TBM_FORMAT_YVU422:
464 case TBM_FORMAT_YUV444:
465 case TBM_FORMAT_YVU444:
473 TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
479 tbm_surface_internal_get_bpp(tbm_format format)
486 case TBM_FORMAT_RGB332:
487 case TBM_FORMAT_BGR233:
490 case TBM_FORMAT_XRGB4444:
491 case TBM_FORMAT_XBGR4444:
492 case TBM_FORMAT_RGBX4444:
493 case TBM_FORMAT_BGRX4444:
494 case TBM_FORMAT_ARGB4444:
495 case TBM_FORMAT_ABGR4444:
496 case TBM_FORMAT_RGBA4444:
497 case TBM_FORMAT_BGRA4444:
498 case TBM_FORMAT_XRGB1555:
499 case TBM_FORMAT_XBGR1555:
500 case TBM_FORMAT_RGBX5551:
501 case TBM_FORMAT_BGRX5551:
502 case TBM_FORMAT_ARGB1555:
503 case TBM_FORMAT_ABGR1555:
504 case TBM_FORMAT_RGBA5551:
505 case TBM_FORMAT_BGRA5551:
506 case TBM_FORMAT_RGB565:
507 case TBM_FORMAT_BGR565:
510 case TBM_FORMAT_RGB888:
511 case TBM_FORMAT_BGR888:
514 case TBM_FORMAT_XRGB8888:
515 case TBM_FORMAT_XBGR8888:
516 case TBM_FORMAT_RGBX8888:
517 case TBM_FORMAT_BGRX8888:
518 case TBM_FORMAT_ARGB8888:
519 case TBM_FORMAT_ABGR8888:
520 case TBM_FORMAT_RGBA8888:
521 case TBM_FORMAT_BGRA8888:
522 case TBM_FORMAT_XRGB2101010:
523 case TBM_FORMAT_XBGR2101010:
524 case TBM_FORMAT_RGBX1010102:
525 case TBM_FORMAT_BGRX1010102:
526 case TBM_FORMAT_ARGB2101010:
527 case TBM_FORMAT_ABGR2101010:
528 case TBM_FORMAT_RGBA1010102:
529 case TBM_FORMAT_BGRA1010102:
530 case TBM_FORMAT_YUYV:
531 case TBM_FORMAT_YVYU:
532 case TBM_FORMAT_UYVY:
533 case TBM_FORMAT_VYUY:
534 case TBM_FORMAT_AYUV:
537 case TBM_FORMAT_NV12:
538 case TBM_FORMAT_NV12MT:
539 case TBM_FORMAT_NV21:
542 case TBM_FORMAT_NV16:
543 case TBM_FORMAT_NV61:
546 case TBM_FORMAT_YUV410:
547 case TBM_FORMAT_YVU410:
550 case TBM_FORMAT_YUV411:
551 case TBM_FORMAT_YVU411:
552 case TBM_FORMAT_YUV420:
553 case TBM_FORMAT_YVU420:
556 case TBM_FORMAT_YUV422:
557 case TBM_FORMAT_YVU422:
560 case TBM_FORMAT_YUV444:
561 case TBM_FORMAT_YVU444:
568 TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
574 tbm_surface_internal_create_with_flags(int width, int height,
575 int format, int flags)
577 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
578 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
580 struct _tbm_bufmgr *mgr;
581 struct _tbm_surface *surf = NULL;
585 uint32_t bo_size = 0;
588 bool bufmgr_initialized = false;
590 _tbm_surface_mutex_lock();
592 if (!g_surface_bufmgr) {
593 _init_surface_bufmgr();
594 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
595 bufmgr_initialized = true;
598 mgr = g_surface_bufmgr;
599 if (!TBM_BUFMGR_IS_VALID(mgr)) {
600 TBM_LOG_E("The bufmgr is invalid\n");
601 goto check_valid_fail;
604 surf = calloc(1, sizeof(struct _tbm_surface));
606 TBM_LOG_E("fail to alloc surf\n");
607 goto alloc_surf_fail;
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 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
621 &offset, &stride, &bo_idx)) {
622 TBM_LOG_E("fail to query plane data\n");
623 goto query_plane_data_fail;
626 surf->info.planes[i].size = size;
627 surf->info.planes[i].offset = offset;
628 surf->info.planes[i].stride = stride;
629 surf->planes_bo_idx[i] = bo_idx;
634 for (i = 0; i < surf->info.num_planes; i++) {
635 surf->info.size += surf->info.planes[i].size;
637 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
638 surf->num_bos = surf->planes_bo_idx[i] + 1;
643 for (i = 0; i < surf->num_bos; i++) {
645 for (j = 0; j < surf->info.num_planes; j++) {
646 if (surf->planes_bo_idx[j] == i)
647 bo_size += surf->info.planes[j].size;
650 if (mgr->backend->surface_bo_alloc) {
651 /* LCOV_EXCL_START */
653 void *bo_priv = NULL;
655 bo = calloc(1, sizeof(struct _tbm_bo));
657 TBM_LOG_E("fail to alloc bo struct\n");
661 bo->bufmgr = surf->bufmgr;
663 pthread_mutex_lock(&surf->bufmgr->lock);
665 bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
667 TBM_LOG_E("fail to alloc bo priv\n");
669 pthread_mutex_unlock(&surf->bufmgr->lock);
677 LIST_INITHEAD(&bo->user_data_list);
679 LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
681 pthread_mutex_unlock(&surf->bufmgr->lock);
686 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
688 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
693 _tbm_bo_set_surface(surf->bos[i], surf);
696 TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
697 _tbm_surface_internal_format_to_str(format), flags, surf);
699 LIST_INITHEAD(&surf->user_data_list);
700 LIST_INITHEAD(&surf->debug_data_list);
702 LIST_ADD(&surf->item_link, &mgr->surf_list);
704 _tbm_surface_mutex_unlock();
709 for (j = 0; j < i; j++) {
711 tbm_bo_unref(surf->bos[j]);
713 query_plane_data_fail:
717 if (bufmgr_initialized) {
718 LIST_DELINIT(&mgr->surf_list);
719 _deinit_surface_bufmgr();
721 _tbm_surface_mutex_unlock();
722 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
724 _tbm_surface_internal_format_to_str(format), flags);
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;
739 bool bufmgr_initialized = false;
741 _tbm_surface_mutex_lock();
743 if (!g_surface_bufmgr) {
744 _init_surface_bufmgr();
745 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
746 bufmgr_initialized = true;
749 mgr = g_surface_bufmgr;
750 if (!TBM_BUFMGR_IS_VALID(mgr))
751 goto check_valid_fail;
753 surf = calloc(1, sizeof(struct _tbm_surface));
755 goto alloc_surf_fail;
758 surf->info.width = info->width;
759 surf->info.height = info->height;
760 surf->info.format = info->format;
761 surf->info.bpp = info->bpp;
762 surf->info.num_planes = info->num_planes;
765 /* get size, stride and offset */
766 for (i = 0; i < info->num_planes; i++) {
767 surf->info.planes[i].offset = info->planes[i].offset;
768 surf->info.planes[i].stride = info->planes[i].stride;
770 if (info->planes[i].size > 0)
771 surf->info.planes[i].size = info->planes[i].size;
773 surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
776 surf->planes_bo_idx[i] = 0;
778 surf->planes_bo_idx[i] = i;
781 if (info->size > 0) {
782 surf->info.size = info->size;
785 for (i = 0; i < info->num_planes; i++)
786 surf->info.size += surf->info.planes[i].size;
789 surf->flags = TBM_BO_DEFAULT;
791 /* create only one bo */
793 for (i = 0; i < num; i++) {
797 surf->bos[i] = tbm_bo_ref(bos[i]);
798 _tbm_bo_set_surface(bos[i], surf);
801 TBM_TRACE("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
802 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
804 LIST_INITHEAD(&surf->user_data_list);
805 LIST_INITHEAD(&surf->debug_data_list);
807 LIST_ADD(&surf->item_link, &mgr->surf_list);
809 _tbm_surface_mutex_unlock();
814 for (i = 0; i < num; i++) {
816 tbm_bo_unref(surf->bos[i]);
821 if (bufmgr_initialized) {
822 LIST_DELINIT(&g_surface_bufmgr->surf_list);
823 _deinit_surface_bufmgr();
825 _tbm_surface_mutex_unlock();
826 TBM_TRACE("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
827 info->width, info->height,
828 _tbm_surface_internal_format_to_str(info->format), num);
833 tbm_surface_internal_destroy(tbm_surface_h surface)
835 _tbm_surface_mutex_lock();
837 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
841 if (surface->refcnt > 0) {
842 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
843 _tbm_surface_mutex_unlock();
847 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
849 if (surface->refcnt == 0)
850 _tbm_surface_internal_destroy(surface);
852 _tbm_surface_mutex_unlock();
856 tbm_surface_internal_ref(tbm_surface_h surface)
858 _tbm_surface_mutex_lock();
860 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
864 TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
866 _tbm_surface_mutex_unlock();
870 tbm_surface_internal_unref(tbm_surface_h surface)
872 _tbm_surface_mutex_lock();
874 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
878 if (surface->refcnt > 0) {
879 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
880 _tbm_surface_mutex_unlock();
884 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
886 if (surface->refcnt == 0)
887 _tbm_surface_internal_destroy(surface);
889 _tbm_surface_mutex_unlock();
893 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
895 struct _tbm_surface *surf;
898 _tbm_surface_mutex_lock();
900 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
902 surf = (struct _tbm_surface *)surface;
905 TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
907 _tbm_surface_mutex_unlock();
913 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
915 struct _tbm_surface *surf;
918 _tbm_surface_mutex_lock();
920 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), NULL);
921 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
923 surf = (struct _tbm_surface *)surface;
924 bo = surf->bos[bo_idx];
926 TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
928 _tbm_surface_mutex_unlock();
934 tbm_surface_internal_get_size(tbm_surface_h surface)
936 struct _tbm_surface *surf;
939 _tbm_surface_mutex_lock();
941 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
943 surf = (struct _tbm_surface *)surface;
944 size = surf->info.size;
946 TBM_TRACE("tbm_surface(%p) size(%d)\n", surface, size);
948 _tbm_surface_mutex_unlock();
954 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
955 uint32_t *size, uint32_t *offset, uint32_t *pitch)
957 struct _tbm_surface *surf;
959 _tbm_surface_mutex_lock();
961 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
962 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
964 surf = (struct _tbm_surface *)surface;
966 if (plane_idx >= surf->info.num_planes) {
967 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
968 _tbm_surface_mutex_unlock();
973 *size = surf->info.planes[plane_idx].size;
976 *offset = surf->info.planes[plane_idx].offset;
979 *pitch = surf->info.planes[plane_idx].stride;
981 TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%d) offset(%d) pitch(%d)\n", surface, plane_idx,
982 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
983 surf->info.planes[plane_idx].stride);
985 _tbm_surface_mutex_unlock();
991 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
992 tbm_surface_info_s *info, int map)
994 struct _tbm_surface *surf;
995 tbm_bo_handle bo_handles[4];
998 _tbm_surface_mutex_lock();
1000 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1002 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1004 surf = (struct _tbm_surface *)surface;
1006 memset(info, 0x00, sizeof(tbm_surface_info_s));
1007 info->width = surf->info.width;
1008 info->height = surf->info.height;
1009 info->format = surf->info.format;
1010 info->bpp = surf->info.bpp;
1011 info->size = surf->info.size;
1012 info->num_planes = surf->info.num_planes;
1015 for (i = 0; i < surf->num_bos; i++) {
1016 _tbm_surface_mutex_unlock();
1017 bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1018 _tbm_surface_mutex_lock();
1019 if (bo_handles[i].ptr == NULL) {
1020 for (j = 0; j < i; j++)
1021 tbm_bo_unmap(surf->bos[j]);
1023 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1024 _tbm_surface_mutex_unlock();
1029 for (i = 0; i < surf->num_bos; i++)
1030 bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1033 for (i = 0; i < surf->info.num_planes; i++) {
1034 info->planes[i].size = surf->info.planes[i].size;
1035 info->planes[i].offset = surf->info.planes[i].offset;
1036 info->planes[i].stride = surf->info.planes[i].stride;
1038 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1039 info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1040 surf->info.planes[i].offset;
1043 TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1045 _tbm_surface_mutex_unlock();
1051 tbm_surface_internal_unmap(tbm_surface_h surface)
1053 struct _tbm_surface *surf;
1056 _tbm_surface_mutex_lock();
1058 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1060 surf = (struct _tbm_surface *)surface;
1062 for (i = 0; i < surf->num_bos; i++)
1063 tbm_bo_unmap(surf->bos[i]);
1065 TBM_TRACE("tbm_surface(%p)\n", surface);
1067 _tbm_surface_mutex_unlock();
1071 tbm_surface_internal_get_width(tbm_surface_h surface)
1073 struct _tbm_surface *surf;
1076 _tbm_surface_mutex_lock();
1078 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1080 surf = (struct _tbm_surface *)surface;
1081 width = surf->info.width;
1083 TBM_TRACE("tbm_surface(%p) width(%d)\n", surface, width);
1085 _tbm_surface_mutex_unlock();
1091 tbm_surface_internal_get_height(tbm_surface_h surface)
1093 struct _tbm_surface *surf;
1094 unsigned int height;
1096 _tbm_surface_mutex_lock();
1098 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1100 surf = (struct _tbm_surface *)surface;
1101 height = surf->info.height;
1103 TBM_TRACE("tbm_surface(%p) height(%d)\n", surface, height);
1105 _tbm_surface_mutex_unlock();
1112 tbm_surface_internal_get_format(tbm_surface_h surface)
1114 struct _tbm_surface *surf;
1117 _tbm_surface_mutex_lock();
1119 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1121 surf = (struct _tbm_surface *)surface;
1122 format = surf->info.format;
1124 TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1126 _tbm_surface_mutex_unlock();
1132 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1134 struct _tbm_surface *surf;
1137 _tbm_surface_mutex_lock();
1139 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1140 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1142 surf = (struct _tbm_surface *)surface;
1143 bo_idx = surf->planes_bo_idx[plane_idx];
1145 TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1147 _tbm_surface_mutex_unlock();
1153 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1154 tbm_data_free data_free_func)
1156 tbm_user_data *data;
1158 _tbm_surface_mutex_lock();
1160 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1162 /* check if the data according to the key exist if so, return false. */
1163 data = user_data_lookup(&surface->user_data_list, key);
1165 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1166 _tbm_surface_mutex_unlock();
1170 data = user_data_create(key, data_free_func);
1172 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1173 _tbm_surface_mutex_unlock();
1177 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1179 LIST_ADD(&data->item_link, &surface->user_data_list);
1181 _tbm_surface_mutex_unlock();
1187 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1190 tbm_user_data *old_data;
1192 _tbm_surface_mutex_lock();
1194 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1196 if (LIST_IS_EMPTY(&surface->user_data_list)) {
1197 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1198 _tbm_surface_mutex_unlock();
1202 old_data = user_data_lookup(&surface->user_data_list, key);
1204 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1205 _tbm_surface_mutex_unlock();
1209 if (old_data->data && old_data->free_func)
1210 old_data->free_func(old_data->data);
1212 old_data->data = data;
1214 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1216 _tbm_surface_mutex_unlock();
1222 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1225 tbm_user_data *old_data;
1227 _tbm_surface_mutex_lock();
1229 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1231 if (!data || LIST_IS_EMPTY(&surface->user_data_list)) {
1232 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1233 _tbm_surface_mutex_unlock();
1237 old_data = user_data_lookup(&surface->user_data_list, key);
1239 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1241 _tbm_surface_mutex_unlock();
1245 *data = old_data->data;
1247 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1249 _tbm_surface_mutex_unlock();
1255 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1258 tbm_user_data *old_data = (void *)0;
1260 _tbm_surface_mutex_lock();
1262 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1264 if (LIST_IS_EMPTY(&surface->user_data_list)) {
1265 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1266 _tbm_surface_mutex_unlock();
1270 old_data = user_data_lookup(&surface->user_data_list, key);
1272 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1273 _tbm_surface_mutex_unlock();
1277 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1279 user_data_delete(old_data);
1281 _tbm_surface_mutex_unlock();
1286 /* LCOV_EXCL_START */
1288 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1290 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1292 return surface->debug_pid;
1296 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1298 _tbm_surface_mutex_lock();
1300 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1302 surface->debug_pid = pid;
1304 _tbm_surface_mutex_unlock();
1307 static tbm_surface_debug_data *
1308 _tbm_surface_internal_debug_data_create(char *key, char *value)
1310 tbm_surface_debug_data *debug_data = NULL;
1312 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1316 if (key) debug_data->key = strdup(key);
1317 if (value) debug_data->value = strdup(value);
1323 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1325 tbm_surface_debug_data *debug_data = NULL;
1326 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1327 tbm_bufmgr bufmgr = NULL;
1329 _tbm_surface_mutex_lock();
1331 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1332 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1334 bufmgr = surface->bufmgr;
1336 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1338 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1339 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1340 if (!strcmp(old_data->key, key)) {
1342 old_data->value = strdup(value);
1344 old_data->value = NULL;
1349 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1351 TBM_TRACE("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1352 _tbm_surface_mutex_unlock();
1356 TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1358 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1360 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1361 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1362 if (!strcmp(old_data->key, key)) {
1363 _tbm_surface_mutex_unlock();
1369 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1370 LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1372 _tbm_surface_mutex_unlock();
1378 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1380 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1382 _tbm_surface_mutex_lock();
1384 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1386 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1387 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1388 if (!strcmp(old_data->key, key)) {
1389 _tbm_surface_mutex_unlock();
1390 return old_data->value;
1395 _tbm_surface_mutex_unlock();
1400 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1401 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1403 struct _tbm_surface_dump_buf_info {
1413 tbm_surface_info_s info;
1415 struct list_head link;
1418 struct _tbm_surface_dump_info {
1419 char *path; // copy???
1422 struct list_head *link;
1423 struct list_head surface_list; /* link of surface */
1426 static tbm_surface_dump_info *g_dump_info = NULL;
1427 static const char *dump_postfix[2] = {"png", "yuv"};
1430 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1, void *data2,
1431 int size2, void *data3, int size3)
1433 unsigned int *blocks;
1434 FILE *fp = fopen(file, "w+");
1435 TBM_RETURN_IF_FAIL(fp != NULL);
1437 blocks = (unsigned int *)data1;
1438 fwrite(blocks, 1, size1, fp);
1441 blocks = (unsigned int *)data2;
1442 fwrite(blocks, 1, size2, fp);
1446 blocks = (unsigned int *)data3;
1447 fwrite(blocks, 1, size3, fp);
1454 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width,
1457 FILE *fp = fopen(file, "wb");
1458 TBM_RETURN_IF_FAIL(fp != NULL);
1461 png_structp pPngStruct =
1462 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1468 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1470 png_destroy_write_struct(&pPngStruct, NULL);
1475 png_init_io(pPngStruct, fp);
1476 png_set_IHDR(pPngStruct,
1481 PNG_COLOR_TYPE_RGBA,
1483 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1485 png_set_bgr(pPngStruct);
1486 png_write_info(pPngStruct, pPngInfo);
1488 const int pixel_size = 4; // RGBA
1489 png_bytep *row_pointers =
1490 png_malloc(pPngStruct, height * sizeof(png_byte *));
1492 unsigned int *blocks = (unsigned int *)data;
1496 for (; y < height; ++y) {
1498 png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1499 row_pointers[y] = (png_bytep)row;
1500 for (x = 0; x < width; ++x) {
1501 unsigned int curBlock = blocks[y * width + x];
1502 row[x * pixel_size] = (curBlock & 0xFF);
1503 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1504 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1505 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1509 png_write_image(pPngStruct, row_pointers);
1510 png_write_end(pPngStruct, pPngInfo);
1512 for (y = 0; y < height; y++)
1513 png_free(pPngStruct, row_pointers[y]);
1514 png_free(pPngStruct, row_pointers);
1516 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1522 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1524 TBM_RETURN_IF_FAIL(path != NULL);
1525 TBM_RETURN_IF_FAIL(w > 0);
1526 TBM_RETURN_IF_FAIL(h > 0);
1527 TBM_RETURN_IF_FAIL(count > 0);
1529 tbm_surface_dump_buf_info *buf_info = NULL;
1530 tbm_surface_dump_buf_info *tmp;
1534 tbm_surface_h tbm_surface;
1535 tbm_surface_info_s info;
1536 tbm_surface_error_e err;
1540 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1544 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1545 TBM_RETURN_IF_FAIL(g_dump_info);
1547 LIST_INITHEAD(&g_dump_info->surface_list);
1548 g_dump_info->count = 0;
1549 g_dump_info->dump_max = count;
1551 /* get buffer size */
1552 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1553 if (tbm_surface == NULL) {
1554 TBM_LOG_E("tbm_surface_create fail\n");
1559 err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
1560 if (err != TBM_SURFACE_ERROR_NONE) {
1561 TBM_LOG_E("tbm_surface_map fail\n");
1562 tbm_surface_destroy(tbm_surface);
1567 buffer_size = info.planes[0].stride * h;
1568 tbm_surface_unmap(tbm_surface);
1569 tbm_surface_destroy(tbm_surface);
1571 /* create dump lists */
1572 for (i = 0; i < count; i++) {
1573 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1574 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1575 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1581 buf_info->index = i;
1583 buf_info->size = buffer_size;
1585 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1588 g_dump_info->path = path;
1589 g_dump_info->link = &g_dump_info->surface_list;
1591 TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1595 /* free resources */
1596 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1597 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1598 tbm_bo_unref(buf_info->bo);
1603 TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1612 tbm_surface_internal_dump_end(void)
1614 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1615 tbm_bo_handle bo_handle;
1621 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1622 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1625 if (buf_info->dirty) {
1629 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1630 if (bo_handle.ptr == NULL)
1633 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1634 TBM_LOG_I("Dump File.. %s generated.\n", file);
1636 switch (buf_info->info.format) {
1637 case TBM_FORMAT_ARGB8888:
1638 case TBM_FORMAT_XRGB8888:
1639 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1640 buf_info->info.planes[0].stride >> 2, buf_info->info.height);
1642 case TBM_FORMAT_YVU420:
1643 case TBM_FORMAT_YUV420:
1644 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1645 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1646 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1647 buf_info->info.planes[0].stride * buf_info->info.height,
1649 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1651 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1653 case TBM_FORMAT_NV12:
1654 case TBM_FORMAT_NV21:
1655 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1656 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1657 buf_info->info.planes[0].stride * buf_info->info.height,
1659 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1662 case TBM_FORMAT_YUYV:
1663 case TBM_FORMAT_UYVY:
1664 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1665 buf_info->info.planes[0].stride * buf_info->info.height,
1669 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1670 tbm_bo_unmap(buf_info->bo);
1674 tbm_bo_unmap(buf_info->bo);
1675 } else if (buf_info->dirty_shm) {
1676 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1677 if (bo_handle.ptr == NULL)
1680 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1681 TBM_LOG_I("Dump File.. %s generated.\n", file);
1683 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1684 buf_info->shm_stride >> 2, buf_info->shm_h);
1686 tbm_bo_unmap(buf_info->bo);
1691 /* free resources */
1692 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1693 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1694 tbm_bo_unref(buf_info->bo);
1702 TBM_LOG_I("Dump End..\n");
1706 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1708 TBM_RETURN_IF_FAIL(surface != NULL);
1709 TBM_RETURN_IF_FAIL(type != NULL);
1711 tbm_surface_dump_buf_info *buf_info;
1712 tbm_surface_info_s info;
1713 struct list_head *next_link;
1714 tbm_bo_handle bo_handle;
1716 const char *postfix;
1721 next_link = g_dump_info->link->next;
1722 TBM_RETURN_IF_FAIL(next_link != NULL);
1724 if (next_link == &g_dump_info->surface_list) {
1725 next_link = next_link->next;
1726 TBM_RETURN_IF_FAIL(next_link != NULL);
1729 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1730 TBM_RETURN_IF_FAIL(buf_info != NULL);
1732 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1733 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1735 if (info.size > buf_info->size) {
1736 TBM_LOG_W("Dump skip. surface over created buffer size(%d, %d)\n", info.size, buf_info->size);
1737 tbm_surface_unmap(surface);
1741 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1742 postfix = dump_postfix[0];
1744 postfix = dump_postfix[1];
1746 /* make the file information */
1747 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1750 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1751 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1752 memset(bo_handle.ptr, 0x00, buf_info->size);
1754 switch (info.format) {
1755 case TBM_FORMAT_ARGB8888:
1756 case TBM_FORMAT_XRGB8888:
1757 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d_%p-%s.%s",
1758 _tbm_surface_internal_get_time(),
1759 g_dump_info->count++, surface, type, postfix);
1760 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1762 case TBM_FORMAT_YVU420:
1763 case TBM_FORMAT_YUV420:
1764 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1765 _tbm_surface_internal_get_time(),
1766 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1767 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1768 bo_handle.ptr += info.planes[0].stride * info.height;
1769 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1770 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1771 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1773 case TBM_FORMAT_NV12:
1774 case TBM_FORMAT_NV21:
1775 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1776 _tbm_surface_internal_get_time(),
1777 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1778 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1779 bo_handle.ptr += info.planes[0].stride * info.height;
1780 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1782 case TBM_FORMAT_YUYV:
1783 case TBM_FORMAT_UYVY:
1784 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1785 _tbm_surface_internal_get_time(),
1786 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1787 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1790 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1791 tbm_bo_unmap(buf_info->bo);
1795 tbm_bo_unmap(buf_info->bo);
1797 tbm_surface_unmap(surface);
1799 buf_info->dirty = 1;
1800 buf_info->dirty_shm = 0;
1802 if (g_dump_info->count == 1000)
1803 g_dump_info->count = 0;
1805 g_dump_info->link = next_link;
1807 TBM_LOG_I("Dump %s \n", buf_info->name);
1810 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride, const char *type)
1812 TBM_RETURN_IF_FAIL(ptr != NULL);
1813 TBM_RETURN_IF_FAIL(w > 0);
1814 TBM_RETURN_IF_FAIL(h > 0);
1815 TBM_RETURN_IF_FAIL(stride > 0);
1816 TBM_RETURN_IF_FAIL(type != NULL);
1818 tbm_surface_dump_buf_info *buf_info;
1819 struct list_head *next_link;
1820 tbm_bo_handle bo_handle;
1825 next_link = g_dump_info->link->next;
1826 TBM_RETURN_IF_FAIL(next_link != NULL);
1828 if (next_link == &g_dump_info->surface_list) {
1829 next_link = next_link->next;
1830 TBM_RETURN_IF_FAIL(next_link != NULL);
1833 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1834 TBM_RETURN_IF_FAIL(buf_info != NULL);
1836 if (stride * h > buf_info->size) {
1837 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n", stride * h, buf_info->size);
1842 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1843 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1844 memset(bo_handle.ptr, 0x00, buf_info->size);
1845 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1847 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1848 _tbm_surface_internal_get_time(),
1849 g_dump_info->count++, type, dump_postfix[0]);
1850 memcpy(bo_handle.ptr, ptr, stride * h);
1852 tbm_bo_unmap(buf_info->bo);
1854 buf_info->dirty = 0;
1855 buf_info->dirty_shm = 1;
1856 buf_info->shm_stride = stride;
1857 buf_info->shm_h = h;
1859 if (g_dump_info->count == 1000)
1860 g_dump_info->count = 0;
1862 g_dump_info->link = next_link;
1864 TBM_LOG_I("Dump %s \n", buf_info->name);