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, tmp = 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_SAFE(old_data, tmp, &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;
589 _tbm_surface_mutex_lock();
591 if (!g_surface_bufmgr) {
592 _init_surface_bufmgr();
593 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
596 mgr = g_surface_bufmgr;
597 if (!TBM_BUFMGR_IS_VALID(mgr)) {
598 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
599 width, height, _tbm_surface_internal_format_to_str(format), flags);
600 _tbm_surface_mutex_unlock();
603 surf = calloc(1, sizeof(struct _tbm_surface));
605 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
606 width, height, _tbm_surface_internal_format_to_str(format), flags);
607 _tbm_surface_mutex_unlock();
612 surf->info.width = width;
613 surf->info.height = height;
614 surf->info.format = format;
615 surf->info.bpp = tbm_surface_internal_get_bpp(format);
616 surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
619 /* get size, stride and offset bo_idx */
620 for (i = 0; i < surf->info.num_planes; i++) {
621 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride,
623 surf->info.planes[i].size = size;
624 surf->info.planes[i].offset = offset;
625 surf->info.planes[i].stride = stride;
626 surf->planes_bo_idx[i] = bo_idx;
631 for (i = 0; i < surf->info.num_planes; i++) {
632 surf->info.size += surf->info.planes[i].size;
634 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
635 surf->num_bos = surf->planes_bo_idx[i] + 1;
640 for (i = 0; i < surf->num_bos; i++) {
642 for (j = 0; j < surf->info.num_planes; j++) {
643 if (surf->planes_bo_idx[j] == i)
644 bo_size += surf->info.planes[j].size;
647 if (mgr->backend->surface_bo_alloc) {
648 /* LCOV_EXCL_START */
650 void *bo_priv = NULL;
652 bo = calloc(1, sizeof(struct _tbm_bo));
654 TBM_LOG_E("fail to alloc bo struct\n");
658 bo->bufmgr = surf->bufmgr;
660 pthread_mutex_lock(&surf->bufmgr->lock);
662 bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
664 TBM_LOG_E("fail to alloc bo priv\n");
666 pthread_mutex_unlock(&surf->bufmgr->lock);
674 LIST_INITHEAD(&bo->user_data_list);
676 LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
678 pthread_mutex_unlock(&surf->bufmgr->lock);
683 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
687 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
691 _tbm_bo_set_surface(surf->bos[i], surf);
695 TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
696 _tbm_surface_internal_format_to_str(format), flags, surf);
698 LIST_INITHEAD(&surf->user_data_list);
699 LIST_INITHEAD(&surf->debug_data_list);
701 LIST_ADD(&surf->item_link, &mgr->surf_list);
703 _tbm_surface_mutex_unlock();
709 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
710 width, height, _tbm_surface_internal_format_to_str(format), flags);
712 for (j = 0; j < i; j++) {
714 tbm_bo_unref(surf->bos[j]);
720 if (LIST_IS_EMPTY(&mgr->surf_list)) {
721 LIST_DELINIT(&mgr->surf_list);
722 _deinit_surface_bufmgr();
725 _tbm_surface_mutex_unlock();
730 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
731 tbm_bo *bos, int num)
733 TBM_RETURN_VAL_IF_FAIL(bos, NULL);
734 TBM_RETURN_VAL_IF_FAIL(info, NULL);
735 TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
737 struct _tbm_bufmgr *mgr;
738 struct _tbm_surface *surf = NULL;
741 _tbm_surface_mutex_lock();
743 if (!g_surface_bufmgr) {
744 _init_surface_bufmgr();
745 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
748 mgr = g_surface_bufmgr;
749 if (!TBM_BUFMGR_IS_VALID(mgr)) {
750 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
751 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
752 _tbm_surface_mutex_unlock();
756 surf = calloc(1, sizeof(struct _tbm_surface));
758 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
759 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
760 _tbm_surface_mutex_unlock();
765 surf->info.width = info->width;
766 surf->info.height = info->height;
767 surf->info.format = info->format;
768 surf->info.bpp = info->bpp;
769 surf->info.num_planes = info->num_planes;
772 /* get size, stride and offset */
773 for (i = 0; i < info->num_planes; i++) {
774 surf->info.planes[i].offset = info->planes[i].offset;
775 surf->info.planes[i].stride = info->planes[i].stride;
777 if (info->planes[i].size > 0)
778 surf->info.planes[i].size = info->planes[i].size;
780 surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
783 surf->planes_bo_idx[i] = 0;
785 surf->planes_bo_idx[i] = i;
788 if (info->size > 0) {
789 surf->info.size = info->size;
792 for (i = 0; i < info->num_planes; i++)
793 surf->info.size += surf->info.planes[i].size;
796 surf->flags = TBM_BO_DEFAULT;
798 /* create only one bo */
800 for (i = 0; i < num; i++) {
804 surf->bos[i] = tbm_bo_ref(bos[i]);
805 _tbm_bo_set_surface(bos[i], surf);
808 TBM_TRACE("tbm_surface(%p) width(%d) height(%d) format(%s) bo_num(%d)\n", surf,
809 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
811 LIST_INITHEAD(&surf->user_data_list);
812 LIST_INITHEAD(&surf->debug_data_list);
814 LIST_ADD(&surf->item_link, &mgr->surf_list);
816 _tbm_surface_mutex_unlock();
820 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
821 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
822 for (i = 0; i < num; i++) {
824 tbm_bo_unref(surf->bos[i]);
832 if (LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
833 LIST_DELINIT(&g_surface_bufmgr->surf_list);
834 _deinit_surface_bufmgr();
837 _tbm_surface_mutex_unlock();
843 tbm_surface_internal_destroy(tbm_surface_h surface)
845 _tbm_surface_mutex_lock();
847 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
851 if (surface->refcnt > 0) {
852 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
853 _tbm_surface_mutex_unlock();
857 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
859 if (surface->refcnt == 0)
860 _tbm_surface_internal_destroy(surface);
862 _tbm_surface_mutex_unlock();
866 tbm_surface_internal_ref(tbm_surface_h surface)
868 _tbm_surface_mutex_lock();
870 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
874 TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
876 _tbm_surface_mutex_unlock();
880 tbm_surface_internal_unref(tbm_surface_h surface)
882 _tbm_surface_mutex_lock();
884 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
888 if (surface->refcnt > 0) {
889 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
890 _tbm_surface_mutex_unlock();
894 TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
896 if (surface->refcnt == 0)
897 _tbm_surface_internal_destroy(surface);
899 _tbm_surface_mutex_unlock();
903 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
905 struct _tbm_surface *surf;
908 _tbm_surface_mutex_lock();
910 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
912 surf = (struct _tbm_surface *)surface;
915 TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
917 _tbm_surface_mutex_unlock();
923 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
925 struct _tbm_surface *surf;
928 _tbm_surface_mutex_lock();
930 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), NULL);
931 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
933 surf = (struct _tbm_surface *)surface;
934 bo = surf->bos[bo_idx];
936 TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
938 _tbm_surface_mutex_unlock();
944 tbm_surface_internal_get_size(tbm_surface_h surface)
946 struct _tbm_surface *surf;
949 _tbm_surface_mutex_lock();
951 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
953 surf = (struct _tbm_surface *)surface;
954 size = surf->info.size;
956 TBM_TRACE("tbm_surface(%p) size(%d)\n", surface, size);
958 _tbm_surface_mutex_unlock();
964 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
965 uint32_t *size, uint32_t *offset, uint32_t *pitch)
967 struct _tbm_surface *surf;
969 _tbm_surface_mutex_lock();
971 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
972 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
974 surf = (struct _tbm_surface *)surface;
976 if (plane_idx >= surf->info.num_planes) {
977 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
978 _tbm_surface_mutex_unlock();
983 *size = surf->info.planes[plane_idx].size;
986 *offset = surf->info.planes[plane_idx].offset;
989 *pitch = surf->info.planes[plane_idx].stride;
991 TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%d) offset(%d) pitch(%d)\n", surface, plane_idx,
992 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
993 surf->info.planes[plane_idx].stride);
995 _tbm_surface_mutex_unlock();
1001 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1002 tbm_surface_info_s *info, int map)
1004 struct _tbm_surface *surf;
1005 tbm_bo_handle bo_handles[4];
1008 _tbm_surface_mutex_lock();
1010 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1012 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1014 surf = (struct _tbm_surface *)surface;
1016 memset(info, 0x00, sizeof(tbm_surface_info_s));
1017 info->width = surf->info.width;
1018 info->height = surf->info.height;
1019 info->format = surf->info.format;
1020 info->bpp = surf->info.bpp;
1021 info->size = surf->info.size;
1022 info->num_planes = surf->info.num_planes;
1025 for (i = 0; i < surf->num_bos; i++) {
1026 bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1027 if (bo_handles[i].ptr == NULL) {
1028 for (j = 0; j < i; j++)
1029 tbm_bo_unmap(surf->bos[j]);
1031 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1032 _tbm_surface_mutex_unlock();
1037 for (i = 0; i < surf->num_bos; i++)
1038 bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1041 for (i = 0; i < surf->info.num_planes; i++) {
1042 info->planes[i].size = surf->info.planes[i].size;
1043 info->planes[i].offset = surf->info.planes[i].offset;
1044 info->planes[i].stride = surf->info.planes[i].stride;
1046 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1047 info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1048 surf->info.planes[i].offset;
1051 TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1053 _tbm_surface_mutex_unlock();
1059 tbm_surface_internal_unmap(tbm_surface_h surface)
1061 struct _tbm_surface *surf;
1064 _tbm_surface_mutex_lock();
1066 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1068 surf = (struct _tbm_surface *)surface;
1070 for (i = 0; i < surf->num_bos; i++)
1071 tbm_bo_unmap(surf->bos[i]);
1073 TBM_TRACE("tbm_surface(%p)\n", surface);
1075 _tbm_surface_mutex_unlock();
1079 tbm_surface_internal_get_width(tbm_surface_h surface)
1081 struct _tbm_surface *surf;
1084 _tbm_surface_mutex_lock();
1086 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1088 surf = (struct _tbm_surface *)surface;
1089 width = surf->info.width;
1091 TBM_TRACE("tbm_surface(%p) width(%d)\n", surface, width);
1093 _tbm_surface_mutex_unlock();
1099 tbm_surface_internal_get_height(tbm_surface_h surface)
1101 struct _tbm_surface *surf;
1102 unsigned int height;
1104 _tbm_surface_mutex_lock();
1106 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1108 surf = (struct _tbm_surface *)surface;
1109 height = surf->info.height;
1111 TBM_TRACE("tbm_surface(%p) height(%d)\n", surface, height);
1113 _tbm_surface_mutex_unlock();
1120 tbm_surface_internal_get_format(tbm_surface_h surface)
1122 struct _tbm_surface *surf;
1125 _tbm_surface_mutex_lock();
1127 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1129 surf = (struct _tbm_surface *)surface;
1130 format = surf->info.format;
1132 TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1134 _tbm_surface_mutex_unlock();
1140 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1142 struct _tbm_surface *surf;
1145 _tbm_surface_mutex_lock();
1147 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1148 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1150 surf = (struct _tbm_surface *)surface;
1151 bo_idx = surf->planes_bo_idx[plane_idx];
1153 TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1155 _tbm_surface_mutex_unlock();
1161 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1162 tbm_data_free data_free_func)
1164 tbm_user_data *data;
1166 _tbm_surface_mutex_lock();
1168 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1170 /* check if the data according to the key exist if so, return false. */
1171 data = user_data_lookup(&surface->user_data_list, key);
1173 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1174 _tbm_surface_mutex_unlock();
1178 data = user_data_create(key, data_free_func);
1180 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1181 _tbm_surface_mutex_unlock();
1185 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1187 LIST_ADD(&data->item_link, &surface->user_data_list);
1189 _tbm_surface_mutex_unlock();
1195 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1198 tbm_user_data *old_data;
1200 _tbm_surface_mutex_lock();
1202 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1204 if (LIST_IS_EMPTY(&surface->user_data_list)) {
1205 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1206 _tbm_surface_mutex_unlock();
1210 old_data = user_data_lookup(&surface->user_data_list, key);
1212 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1213 _tbm_surface_mutex_unlock();
1217 if (old_data->data && old_data->free_func)
1218 old_data->free_func(old_data->data);
1220 old_data->data = data;
1222 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1224 _tbm_surface_mutex_unlock();
1230 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1233 tbm_user_data *old_data;
1235 _tbm_surface_mutex_lock();
1237 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1239 if (!data || LIST_IS_EMPTY(&surface->user_data_list)) {
1240 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1241 _tbm_surface_mutex_unlock();
1245 old_data = user_data_lookup(&surface->user_data_list, key);
1247 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1249 _tbm_surface_mutex_unlock();
1253 *data = old_data->data;
1255 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1257 _tbm_surface_mutex_unlock();
1263 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1266 tbm_user_data *old_data = (void *)0;
1268 _tbm_surface_mutex_lock();
1270 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1272 if (LIST_IS_EMPTY(&surface->user_data_list)) {
1273 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1274 _tbm_surface_mutex_unlock();
1278 old_data = user_data_lookup(&surface->user_data_list, key);
1280 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1281 _tbm_surface_mutex_unlock();
1285 TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1287 user_data_delete(old_data);
1289 _tbm_surface_mutex_unlock();
1294 /* LCOV_EXCL_START */
1296 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1298 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1300 return surface->debug_pid;
1304 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1306 _tbm_surface_mutex_lock();
1308 TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1310 surface->debug_pid = pid;
1312 _tbm_surface_mutex_unlock();
1315 static tbm_surface_debug_data *
1316 _tbm_surface_internal_debug_data_create(char *key, char *value)
1318 tbm_surface_debug_data *debug_data = NULL;
1320 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1324 if (key) debug_data->key = strdup(key);
1325 if (value) debug_data->value = strdup(value);
1331 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1333 tbm_surface_debug_data *debug_data = NULL;
1334 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1335 tbm_bufmgr bufmgr = NULL;
1337 _tbm_surface_mutex_lock();
1339 TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1340 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1342 bufmgr = surface->bufmgr;
1344 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1346 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1347 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1348 if (!strcmp(old_data->key, key)) {
1350 old_data->value = strdup(value);
1352 old_data->value = NULL;
1357 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1359 TBM_TRACE("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1360 _tbm_surface_mutex_unlock();
1364 TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1366 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1368 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1369 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1370 if (!strcmp(old_data->key, key)) {
1371 _tbm_surface_mutex_unlock();
1377 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1378 LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1380 _tbm_surface_mutex_unlock();
1386 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1388 tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1390 _tbm_surface_mutex_lock();
1392 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1394 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1395 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1396 if (!strcmp(old_data->key, key)) {
1397 _tbm_surface_mutex_unlock();
1398 return old_data->value;
1403 _tbm_surface_mutex_unlock();
1408 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1409 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1411 struct _tbm_surface_dump_buf_info {
1421 tbm_surface_info_s info;
1423 struct list_head link;
1426 struct _tbm_surface_dump_info {
1427 char *path; // copy???
1430 struct list_head *link;
1431 struct list_head surface_list; /* link of surface */
1434 static tbm_surface_dump_info *g_dump_info = NULL;
1435 static const char *dump_postfix[2] = {"png", "yuv"};
1438 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1, void *data2,
1439 int size2, void *data3, int size3)
1441 unsigned int *blocks;
1442 FILE *fp = fopen(file, "w+");
1443 TBM_RETURN_IF_FAIL(fp != NULL);
1445 blocks = (unsigned int *)data1;
1446 fwrite(blocks, 1, size1, fp);
1449 blocks = (unsigned int *)data2;
1450 fwrite(blocks, 1, size2, fp);
1454 blocks = (unsigned int *)data3;
1455 fwrite(blocks, 1, size3, fp);
1462 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width,
1465 FILE *fp = fopen(file, "wb");
1466 TBM_RETURN_IF_FAIL(fp != NULL);
1469 png_structp pPngStruct =
1470 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1476 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1478 png_destroy_write_struct(&pPngStruct, NULL);
1483 png_init_io(pPngStruct, fp);
1484 png_set_IHDR(pPngStruct,
1489 PNG_COLOR_TYPE_RGBA,
1491 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1493 png_set_bgr(pPngStruct);
1494 png_write_info(pPngStruct, pPngInfo);
1496 const int pixel_size = 4; // RGBA
1497 png_bytep *row_pointers =
1498 png_malloc(pPngStruct, height * sizeof(png_byte *));
1500 unsigned int *blocks = (unsigned int *)data;
1504 for (; y < height; ++y) {
1506 png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1507 row_pointers[y] = (png_bytep)row;
1508 for (x = 0; x < width; ++x) {
1509 unsigned int curBlock = blocks[y * width + x];
1510 row[x * pixel_size] = (curBlock & 0xFF);
1511 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1512 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1513 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1517 png_write_image(pPngStruct, row_pointers);
1518 png_write_end(pPngStruct, pPngInfo);
1520 for (y = 0; y < height; y++)
1521 png_free(pPngStruct, row_pointers[y]);
1522 png_free(pPngStruct, row_pointers);
1524 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1530 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1532 TBM_RETURN_IF_FAIL(path != NULL);
1533 TBM_RETURN_IF_FAIL(w > 0);
1534 TBM_RETURN_IF_FAIL(h > 0);
1535 TBM_RETURN_IF_FAIL(count > 0);
1537 tbm_surface_dump_buf_info *buf_info = NULL;
1538 tbm_surface_dump_buf_info *tmp;
1542 tbm_surface_h tbm_surface;
1543 tbm_surface_info_s info;
1544 tbm_surface_error_e err;
1548 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1552 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1553 TBM_RETURN_IF_FAIL(g_dump_info);
1555 LIST_INITHEAD(&g_dump_info->surface_list);
1556 g_dump_info->count = 0;
1557 g_dump_info->dump_max = count;
1559 /* get buffer size */
1560 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1561 if (tbm_surface == NULL) {
1562 TBM_LOG_E("tbm_surface_create fail\n");
1567 err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
1568 if (err != TBM_SURFACE_ERROR_NONE) {
1569 TBM_LOG_E("tbm_surface_map fail\n");
1570 tbm_surface_destroy(tbm_surface);
1575 buffer_size = info.planes[0].stride * h;
1576 tbm_surface_unmap(tbm_surface);
1577 tbm_surface_destroy(tbm_surface);
1579 /* create dump lists */
1580 for (i = 0; i < count; i++) {
1581 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1582 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1583 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1589 buf_info->index = i;
1591 buf_info->size = buffer_size;
1593 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1596 g_dump_info->path = path;
1597 g_dump_info->link = &g_dump_info->surface_list;
1599 TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1603 /* free resources */
1604 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1605 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1606 tbm_bo_unref(buf_info->bo);
1611 TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1620 tbm_surface_internal_dump_end(void)
1622 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1623 tbm_bo_handle bo_handle;
1629 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1630 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1633 if (buf_info->dirty) {
1637 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1638 if (bo_handle.ptr == NULL)
1641 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1642 TBM_LOG_I("Dump File.. %s generated.\n", file);
1644 switch (buf_info->info.format) {
1645 case TBM_FORMAT_ARGB8888:
1646 case TBM_FORMAT_XRGB8888:
1647 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1648 buf_info->info.planes[0].stride >> 2, buf_info->info.height);
1650 case TBM_FORMAT_YVU420:
1651 case TBM_FORMAT_YUV420:
1652 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1653 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1654 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1655 buf_info->info.planes[0].stride * buf_info->info.height,
1657 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1659 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1661 case TBM_FORMAT_NV12:
1662 case TBM_FORMAT_NV21:
1663 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1664 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1665 buf_info->info.planes[0].stride * buf_info->info.height,
1667 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1670 case TBM_FORMAT_YUYV:
1671 case TBM_FORMAT_UYVY:
1672 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1673 buf_info->info.planes[0].stride * buf_info->info.height,
1677 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1678 tbm_bo_unmap(buf_info->bo);
1682 tbm_bo_unmap(buf_info->bo);
1683 } else if (buf_info->dirty_shm) {
1684 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1685 if (bo_handle.ptr == NULL)
1688 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1689 TBM_LOG_I("Dump File.. %s generated.\n", file);
1691 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1692 buf_info->shm_stride >> 2, buf_info->shm_h);
1694 tbm_bo_unmap(buf_info->bo);
1699 /* free resources */
1700 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1701 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1702 tbm_bo_unref(buf_info->bo);
1710 TBM_LOG_I("Dump End..\n");
1714 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1716 TBM_RETURN_IF_FAIL(surface != NULL);
1717 TBM_RETURN_IF_FAIL(type != NULL);
1719 tbm_surface_dump_buf_info *buf_info;
1720 tbm_surface_info_s info;
1721 struct list_head *next_link;
1722 tbm_bo_handle bo_handle;
1724 const char *postfix;
1729 next_link = g_dump_info->link->next;
1730 TBM_RETURN_IF_FAIL(next_link != NULL);
1732 if (next_link == &g_dump_info->surface_list) {
1733 next_link = next_link->next;
1734 TBM_RETURN_IF_FAIL(next_link != NULL);
1737 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1738 TBM_RETURN_IF_FAIL(buf_info != NULL);
1740 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1741 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1743 if (info.size > buf_info->size) {
1744 TBM_LOG_W("Dump skip. surface over created buffer size(%d, %d)\n", info.size, buf_info->size);
1745 tbm_surface_unmap(surface);
1749 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1750 postfix = dump_postfix[0];
1752 postfix = dump_postfix[1];
1754 /* make the file information */
1755 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1758 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1759 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1760 memset(bo_handle.ptr, 0x00, buf_info->size);
1762 switch (info.format) {
1763 case TBM_FORMAT_ARGB8888:
1764 case TBM_FORMAT_XRGB8888:
1765 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d_%p-%s.%s",
1766 _tbm_surface_internal_get_time(),
1767 g_dump_info->count++, surface, type, postfix);
1768 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1770 case TBM_FORMAT_YVU420:
1771 case TBM_FORMAT_YUV420:
1772 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1773 _tbm_surface_internal_get_time(),
1774 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1775 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1776 bo_handle.ptr += info.planes[0].stride * info.height;
1777 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1778 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1779 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1781 case TBM_FORMAT_NV12:
1782 case TBM_FORMAT_NV21:
1783 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1784 _tbm_surface_internal_get_time(),
1785 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1786 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1787 bo_handle.ptr += info.planes[0].stride * info.height;
1788 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1790 case TBM_FORMAT_YUYV:
1791 case TBM_FORMAT_UYVY:
1792 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1793 _tbm_surface_internal_get_time(),
1794 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1795 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1798 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1799 tbm_bo_unmap(buf_info->bo);
1803 tbm_bo_unmap(buf_info->bo);
1805 tbm_surface_unmap(surface);
1807 buf_info->dirty = 1;
1808 buf_info->dirty_shm = 0;
1810 if (g_dump_info->count == 1000)
1811 g_dump_info->count = 0;
1813 g_dump_info->link = next_link;
1815 TBM_LOG_I("Dump %s \n", buf_info->name);
1818 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride, const char *type)
1820 TBM_RETURN_IF_FAIL(ptr != NULL);
1821 TBM_RETURN_IF_FAIL(w > 0);
1822 TBM_RETURN_IF_FAIL(h > 0);
1823 TBM_RETURN_IF_FAIL(stride > 0);
1824 TBM_RETURN_IF_FAIL(type != NULL);
1826 tbm_surface_dump_buf_info *buf_info;
1827 struct list_head *next_link;
1828 tbm_bo_handle bo_handle;
1833 next_link = g_dump_info->link->next;
1834 TBM_RETURN_IF_FAIL(next_link != NULL);
1836 if (next_link == &g_dump_info->surface_list) {
1837 next_link = next_link->next;
1838 TBM_RETURN_IF_FAIL(next_link != NULL);
1841 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1842 TBM_RETURN_IF_FAIL(buf_info != NULL);
1844 if (stride * h > buf_info->size) {
1845 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n", stride * h, buf_info->size);
1850 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1851 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1852 memset(bo_handle.ptr, 0x00, buf_info->size);
1853 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1855 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1856 _tbm_surface_internal_get_time(),
1857 g_dump_info->count++, type, dump_postfix[0]);
1858 memcpy(bo_handle.ptr, ptr, stride * h);
1860 tbm_bo_unmap(buf_info->bo);
1862 buf_info->dirty = 0;
1863 buf_info->dirty_shm = 1;
1864 buf_info->shm_stride = stride;
1865 buf_info->shm_h = h;
1867 if (g_dump_info->count == 1000)
1868 g_dump_info->count = 0;
1870 g_dump_info->link = next_link;
1872 TBM_LOG_I("Dump %s \n", buf_info->name);