fix memory leak in tbm_surface_internal_set_debug_data()
[platform/core/uifw/libtbm.git] / src / tbm_surface_internal.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6
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>
9
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:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
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.
29
30 **************************************************************************/
31
32 #include "config.h"
33
34 #include <stdio.h>
35 #include <time.h>
36 #include <sys/time.h>
37 #include "tbm_bufmgr.h"
38 #include "tbm_bufmgr_int.h"
39 #include "tbm_surface_internal.h"
40 #include "list.h"
41 #include <png.h>
42
43 static tbm_bufmgr g_surface_bufmgr;
44 static pthread_mutex_t tbm_surface_lock;
45 void _tbm_surface_mutex_unlock(void);
46
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])
52
53 /* check condition */
54 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
55         if (!(cond)) {\
56                 TBM_LOG_E("'%s' failed.\n", #cond);\
57                 _tbm_surface_mutex_unlock();\
58                 return;\
59         } \
60 }
61
62 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
63         if (!(cond)) {\
64                 TBM_LOG_E("'%s' failed.\n", #cond);\
65                 _tbm_surface_mutex_unlock();\
66                 return val;\
67         } \
68 }
69
70 /* LCOV_EXCL_START */
71
72 static double
73 _tbm_surface_internal_get_time(void)
74 {
75         struct timespec tp;
76         unsigned int time;
77
78         clock_gettime(CLOCK_MONOTONIC, &tp);
79         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
80
81         return time / 1000.0;
82 }
83
84 static void
85 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
86 {
87         LIST_DEL(&debug_data->item_link);
88
89         if (debug_data->key) free(debug_data->key);
90         if (debug_data->value) free(debug_data->value);
91         free(debug_data);
92 }
93
94 char *
95 _tbm_surface_internal_format_to_str(tbm_format format)
96 {
97         switch (format) {
98         case TBM_FORMAT_C8:
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";
216         default:
217                 return "unknwon";
218         }
219 }
220 /* LCOV_EXCL_STOP */
221
222 static bool
223 _tbm_surface_mutex_init(void)
224 {
225         static bool tbm_surface_mutex_init = false;
226
227         if (tbm_surface_mutex_init)
228                 return true;
229
230         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
231                 TBM_LOG_E("fail: tbm_surface mutex init\n");
232                 return false;
233         }
234
235         tbm_surface_mutex_init = true;
236
237         return true;
238 }
239
240 void
241 _tbm_surface_mutex_lock(void)
242 {
243         if (!_tbm_surface_mutex_init())
244                 return;
245
246         pthread_mutex_lock(&tbm_surface_lock);
247 }
248
249 void
250 _tbm_surface_mutex_unlock(void)
251 {
252         pthread_mutex_unlock(&tbm_surface_lock);
253 }
254
255 static void
256 _init_surface_bufmgr(void)
257 {
258         g_surface_bufmgr = tbm_bufmgr_init(-1);
259 }
260
261 static void
262 _deinit_surface_bufmgr(void)
263 {
264         if (!g_surface_bufmgr)
265                 return;
266
267         tbm_bufmgr_deinit(g_surface_bufmgr);
268         g_surface_bufmgr = NULL;
269 }
270
271 static int
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)
274 {
275         TBM_RETURN_VAL_IF_FAIL(surface, 0);
276         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
277
278         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
279         struct _tbm_bufmgr *mgr = surf->bufmgr;
280         int ret = 0;
281
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);
286
287         if (!mgr->backend->surface_get_plane_data)
288                 return 0;
289
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);
292         if (!ret)
293                 return 0;
294
295         return 1;
296 }
297
298 static void
299 _tbm_surface_internal_destroy(tbm_surface_h surface)
300 {
301         int i;
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;
305
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);
311                 }
312         }
313
314         for (i = 0; i < surface->num_bos; i++) {
315                 surface->bos[i]->surface = NULL;
316
317                 tbm_bo_unref(surface->bos[i]);
318                 surface->bos[i] = NULL;
319         }
320
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);
324         }
325
326         LIST_DEL(&surface->item_link);
327
328         free(surface);
329         surface = NULL;
330
331         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
332                 LIST_DELINIT(&bufmgr->surf_list);
333
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);
337                         }
338                 }
339
340                 _deinit_surface_bufmgr();
341         }
342 }
343
344 int
345 tbm_surface_internal_is_valid(tbm_surface_h surface)
346 {
347         tbm_surface_h old_data = NULL;
348
349         if (surface == NULL || g_surface_bufmgr == NULL) {
350                 TBM_TRACE("error: tbm_surface(%p)\n", surface);
351                 return 0;
352         }
353
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);
358                                 return 1;
359                         }
360                 }
361         }
362         TBM_TRACE("error: tbm_surface(%p)\n", surface);
363         return 0;
364 }
365
366 int
367 tbm_surface_internal_query_supported_formats(uint32_t **formats,
368                 uint32_t *num)
369 {
370         struct _tbm_bufmgr *mgr;
371         int ret = 0;
372         bool bufmgr_initialized = false;
373
374         _tbm_surface_mutex_lock();
375
376         if (!g_surface_bufmgr) {
377                 _init_surface_bufmgr();
378                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
379                 bufmgr_initialized = true;
380         }
381
382         mgr = g_surface_bufmgr;
383
384         if (!mgr->backend->surface_supported_format)
385                 goto fail;
386
387         ret = mgr->backend->surface_supported_format(formats, num);
388         if (!ret)
389                 goto fail;
390
391         TBM_TRACE("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
392
393         _tbm_surface_mutex_unlock();
394
395         return ret;
396
397 fail:
398         if (bufmgr_initialized) {
399                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
400                 _deinit_surface_bufmgr();
401         }
402         _tbm_surface_mutex_unlock();
403         TBM_TRACE("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
404         return 0;
405 }
406
407 int
408 tbm_surface_internal_get_num_planes(tbm_format format)
409 {
410         int num_planes = 0;
411
412         switch (format) {
413         case TBM_FORMAT_C8:
414         case TBM_FORMAT_RGB332:
415         case TBM_FORMAT_BGR233:
416         case TBM_FORMAT_XRGB4444:
417         case TBM_FORMAT_XBGR4444:
418         case TBM_FORMAT_RGBX4444:
419         case TBM_FORMAT_BGRX4444:
420         case TBM_FORMAT_ARGB4444:
421         case TBM_FORMAT_ABGR4444:
422         case TBM_FORMAT_RGBA4444:
423         case TBM_FORMAT_BGRA4444:
424         case TBM_FORMAT_XRGB1555:
425         case TBM_FORMAT_XBGR1555:
426         case TBM_FORMAT_RGBX5551:
427         case TBM_FORMAT_BGRX5551:
428         case TBM_FORMAT_ARGB1555:
429         case TBM_FORMAT_ABGR1555:
430         case TBM_FORMAT_RGBA5551:
431         case TBM_FORMAT_BGRA5551:
432         case TBM_FORMAT_RGB565:
433         case TBM_FORMAT_BGR565:
434         case TBM_FORMAT_RGB888:
435         case TBM_FORMAT_BGR888:
436         case TBM_FORMAT_XRGB8888:
437         case TBM_FORMAT_XBGR8888:
438         case TBM_FORMAT_RGBX8888:
439         case TBM_FORMAT_BGRX8888:
440         case TBM_FORMAT_ARGB8888:
441         case TBM_FORMAT_ABGR8888:
442         case TBM_FORMAT_RGBA8888:
443         case TBM_FORMAT_BGRA8888:
444         case TBM_FORMAT_XRGB2101010:
445         case TBM_FORMAT_XBGR2101010:
446         case TBM_FORMAT_RGBX1010102:
447         case TBM_FORMAT_BGRX1010102:
448         case TBM_FORMAT_ARGB2101010:
449         case TBM_FORMAT_ABGR2101010:
450         case TBM_FORMAT_RGBA1010102:
451         case TBM_FORMAT_BGRA1010102:
452         case TBM_FORMAT_YUYV:
453         case TBM_FORMAT_YVYU:
454         case TBM_FORMAT_UYVY:
455         case TBM_FORMAT_VYUY:
456         case TBM_FORMAT_AYUV:
457                 num_planes = 1;
458                 break;
459         case TBM_FORMAT_NV12:
460         case TBM_FORMAT_NV12MT:
461         case TBM_FORMAT_NV21:
462         case TBM_FORMAT_NV16:
463         case TBM_FORMAT_NV61:
464                 num_planes = 2;
465                 break;
466         case TBM_FORMAT_YUV410:
467         case TBM_FORMAT_YVU410:
468         case TBM_FORMAT_YUV411:
469         case TBM_FORMAT_YVU411:
470         case TBM_FORMAT_YUV420:
471         case TBM_FORMAT_YVU420:
472         case TBM_FORMAT_YUV422:
473         case TBM_FORMAT_YVU422:
474         case TBM_FORMAT_YUV444:
475         case TBM_FORMAT_YVU444:
476                 num_planes = 3;
477                 break;
478
479         default:
480                 break;
481         }
482
483         TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
484
485         return num_planes;
486 }
487
488 int
489 tbm_surface_internal_get_bpp(tbm_format format)
490 {
491
492         int bpp = 0;
493
494         switch (format) {
495         case TBM_FORMAT_C8:
496         case TBM_FORMAT_RGB332:
497         case TBM_FORMAT_BGR233:
498                 bpp = 8;
499                 break;
500         case TBM_FORMAT_XRGB4444:
501         case TBM_FORMAT_XBGR4444:
502         case TBM_FORMAT_RGBX4444:
503         case TBM_FORMAT_BGRX4444:
504         case TBM_FORMAT_ARGB4444:
505         case TBM_FORMAT_ABGR4444:
506         case TBM_FORMAT_RGBA4444:
507         case TBM_FORMAT_BGRA4444:
508         case TBM_FORMAT_XRGB1555:
509         case TBM_FORMAT_XBGR1555:
510         case TBM_FORMAT_RGBX5551:
511         case TBM_FORMAT_BGRX5551:
512         case TBM_FORMAT_ARGB1555:
513         case TBM_FORMAT_ABGR1555:
514         case TBM_FORMAT_RGBA5551:
515         case TBM_FORMAT_BGRA5551:
516         case TBM_FORMAT_RGB565:
517         case TBM_FORMAT_BGR565:
518                 bpp = 16;
519                 break;
520         case TBM_FORMAT_RGB888:
521         case TBM_FORMAT_BGR888:
522                 bpp = 24;
523                 break;
524         case TBM_FORMAT_XRGB8888:
525         case TBM_FORMAT_XBGR8888:
526         case TBM_FORMAT_RGBX8888:
527         case TBM_FORMAT_BGRX8888:
528         case TBM_FORMAT_ARGB8888:
529         case TBM_FORMAT_ABGR8888:
530         case TBM_FORMAT_RGBA8888:
531         case TBM_FORMAT_BGRA8888:
532         case TBM_FORMAT_XRGB2101010:
533         case TBM_FORMAT_XBGR2101010:
534         case TBM_FORMAT_RGBX1010102:
535         case TBM_FORMAT_BGRX1010102:
536         case TBM_FORMAT_ARGB2101010:
537         case TBM_FORMAT_ABGR2101010:
538         case TBM_FORMAT_RGBA1010102:
539         case TBM_FORMAT_BGRA1010102:
540         case TBM_FORMAT_YUYV:
541         case TBM_FORMAT_YVYU:
542         case TBM_FORMAT_UYVY:
543         case TBM_FORMAT_VYUY:
544         case TBM_FORMAT_AYUV:
545                 bpp = 32;
546                 break;
547         case TBM_FORMAT_NV12:
548         case TBM_FORMAT_NV12MT:
549         case TBM_FORMAT_NV21:
550                 bpp = 12;
551                 break;
552         case TBM_FORMAT_NV16:
553         case TBM_FORMAT_NV61:
554                 bpp = 16;
555                 break;
556         case TBM_FORMAT_YUV410:
557         case TBM_FORMAT_YVU410:
558                 bpp = 9;
559                 break;
560         case TBM_FORMAT_YUV411:
561         case TBM_FORMAT_YVU411:
562         case TBM_FORMAT_YUV420:
563         case TBM_FORMAT_YVU420:
564                 bpp = 12;
565                 break;
566         case TBM_FORMAT_YUV422:
567         case TBM_FORMAT_YVU422:
568                 bpp = 16;
569                 break;
570         case TBM_FORMAT_YUV444:
571         case TBM_FORMAT_YVU444:
572                 bpp = 24;
573                 break;
574         default:
575                 break;
576         }
577
578         TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
579
580         return bpp;
581 }
582
583 tbm_surface_h
584 tbm_surface_internal_create_with_flags(int width, int height,
585                                        int format, int flags)
586 {
587         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
588         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
589
590         struct _tbm_bufmgr *mgr;
591         struct _tbm_surface *surf = NULL;
592         uint32_t size = 0;
593         uint32_t offset = 0;
594         uint32_t stride = 0;
595         uint32_t bo_size = 0;
596         int bo_idx;
597         int i, j;
598         bool bufmgr_initialized = false;
599
600         _tbm_surface_mutex_lock();
601
602         if (!g_surface_bufmgr) {
603                 _init_surface_bufmgr();
604                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
605                 bufmgr_initialized = true;
606         }
607
608         mgr = g_surface_bufmgr;
609         if (!TBM_BUFMGR_IS_VALID(mgr)) {
610                 TBM_LOG_E("The bufmgr is invalid\n");
611                 goto check_valid_fail;
612         }
613
614         surf = calloc(1, sizeof(struct _tbm_surface));
615         if (!surf) {
616                 TBM_LOG_E("fail to alloc surf\n");
617                 goto alloc_surf_fail;
618         }
619
620         surf->bufmgr = mgr;
621         surf->info.width = width;
622         surf->info.height = height;
623         surf->info.format = format;
624         surf->info.bpp = tbm_surface_internal_get_bpp(format);
625         surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
626         surf->refcnt = 1;
627
628         /* get size, stride and offset bo_idx */
629         for (i = 0; i < surf->info.num_planes; i++) {
630                 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
631                                                 &offset, &stride, &bo_idx)) {
632                         TBM_LOG_E("fail to query plane data\n");
633                         goto query_plane_data_fail;
634                 }
635
636                 surf->info.planes[i].size = size;
637                 surf->info.planes[i].offset = offset;
638                 surf->info.planes[i].stride = stride;
639                 surf->planes_bo_idx[i] = bo_idx;
640         }
641
642         surf->num_bos = 1;
643
644         for (i = 0; i < surf->info.num_planes; i++) {
645                 surf->info.size += surf->info.planes[i].size;
646
647                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
648                         surf->num_bos = surf->planes_bo_idx[i] + 1;
649         }
650
651         surf->flags = flags;
652
653         for (i = 0; i < surf->num_bos; i++) {
654                 bo_size = 0;
655                 for (j = 0; j < surf->info.num_planes; j++) {
656                         if (surf->planes_bo_idx[j] == i)
657                                 bo_size += surf->info.planes[j].size;
658                 }
659
660                 if (mgr->backend->surface_bo_alloc) {
661                         /* LCOV_EXCL_START */
662                         tbm_bo bo = NULL;
663                         void *bo_priv = NULL;
664
665                         bo = calloc(1, sizeof(struct _tbm_bo));
666                         if (!bo) {
667                                 TBM_LOG_E("fail to alloc bo struct\n");
668                                 goto alloc_bo_fail;
669                         }
670
671                         bo->bufmgr = surf->bufmgr;
672
673                         pthread_mutex_lock(&surf->bufmgr->lock);
674
675                         bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
676                         if (!bo_priv) {
677                                 TBM_LOG_E("fail to alloc bo priv\n");
678                                 free(bo);
679                                 pthread_mutex_unlock(&surf->bufmgr->lock);
680                                 goto alloc_bo_fail;
681                         }
682
683                         bo->ref_cnt = 1;
684                         bo->flags = flags;
685                         bo->priv = bo_priv;
686
687                         LIST_INITHEAD(&bo->user_data_list);
688
689                         LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
690
691                         pthread_mutex_unlock(&surf->bufmgr->lock);
692
693                         surf->bos[i] = bo;
694                         /* LCOV_EXCL_STOP */
695                 } else {
696                         surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
697                         if (!surf->bos[i]) {
698                                 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
699                                 goto alloc_bo_fail;
700                         }
701                 }
702
703                 _tbm_bo_set_surface(surf->bos[i], surf);
704         }
705
706         TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
707                         _tbm_surface_internal_format_to_str(format), flags, surf);
708
709         LIST_INITHEAD(&surf->user_data_list);
710         LIST_INITHEAD(&surf->debug_data_list);
711
712         LIST_ADD(&surf->item_link, &mgr->surf_list);
713
714         _tbm_surface_mutex_unlock();
715
716         return surf;
717
718 alloc_bo_fail:
719         for (j = 0; j < i; j++) {
720                 if (surf->bos[j])
721                         tbm_bo_unref(surf->bos[j]);
722         }
723 query_plane_data_fail:
724         free(surf);
725 alloc_surf_fail:
726 check_valid_fail:
727         if (bufmgr_initialized && mgr) {
728                 LIST_DELINIT(&mgr->surf_list);
729                 _deinit_surface_bufmgr();
730         }
731         _tbm_surface_mutex_unlock();
732         TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
733                         width, height,
734                         _tbm_surface_internal_format_to_str(format), flags);
735         return NULL;
736 }
737
738 tbm_surface_h
739 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
740                                      tbm_bo *bos, int num)
741 {
742         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
743         TBM_RETURN_VAL_IF_FAIL(info, NULL);
744         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
745
746         struct _tbm_bufmgr *mgr;
747         struct _tbm_surface *surf = NULL;
748         int i;
749         bool bufmgr_initialized = false;
750
751         _tbm_surface_mutex_lock();
752
753         if (!g_surface_bufmgr) {
754                 _init_surface_bufmgr();
755                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
756                 bufmgr_initialized = true;
757         }
758
759         mgr = g_surface_bufmgr;
760         if (!TBM_BUFMGR_IS_VALID(mgr))
761                 goto check_valid_fail;
762
763         surf = calloc(1, sizeof(struct _tbm_surface));
764         if (!surf)
765                 goto alloc_surf_fail;
766
767         surf->bufmgr = mgr;
768         surf->info.width = info->width;
769         surf->info.height = info->height;
770         surf->info.format = info->format;
771         surf->info.bpp = info->bpp;
772         surf->info.num_planes = info->num_planes;
773         surf->refcnt = 1;
774
775         /* get size, stride and offset */
776         for (i = 0; i < info->num_planes; i++) {
777                 surf->info.planes[i].offset = info->planes[i].offset;
778                 surf->info.planes[i].stride = info->planes[i].stride;
779
780                 if (info->planes[i].size > 0)
781                         surf->info.planes[i].size = info->planes[i].size;
782                 else
783                         surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
784
785                 if (num == 1)
786                         surf->planes_bo_idx[i] = 0;
787                 else
788                         surf->planes_bo_idx[i] = i;
789         }
790
791         if (info->size > 0) {
792                 surf->info.size = info->size;
793         } else {
794                 surf->info.size = 0;
795                 for (i = 0; i < info->num_planes; i++)
796                         surf->info.size += surf->info.planes[i].size;
797         }
798
799         surf->flags = TBM_BO_DEFAULT;
800
801         /* create only one bo */
802         surf->num_bos = num;
803         for (i = 0; i < num; i++) {
804                 if (bos[i] == NULL)
805                         goto check_bo_fail;
806
807                 surf->bos[i] = tbm_bo_ref(bos[i]);
808                 _tbm_bo_set_surface(bos[i], surf);
809         }
810
811         TBM_TRACE("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
812                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
813
814         LIST_INITHEAD(&surf->user_data_list);
815         LIST_INITHEAD(&surf->debug_data_list);
816
817         LIST_ADD(&surf->item_link, &mgr->surf_list);
818
819         _tbm_surface_mutex_unlock();
820
821         return surf;
822
823 check_bo_fail:
824         for (i = 0; i < num; i++) {
825                 if (surf->bos[i])
826                         tbm_bo_unref(surf->bos[i]);
827         }
828         free(surf);
829 alloc_surf_fail:
830 check_valid_fail:
831         if (bufmgr_initialized && mgr) {
832                 LIST_DELINIT(&mgr->surf_list);
833                 _deinit_surface_bufmgr();
834         }
835         _tbm_surface_mutex_unlock();
836         TBM_TRACE("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
837                         info->width, info->height,
838                         _tbm_surface_internal_format_to_str(info->format), num);
839         return NULL;
840 }
841
842 void
843 tbm_surface_internal_destroy(tbm_surface_h surface)
844 {
845         _tbm_surface_mutex_lock();
846
847         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
848
849         surface->refcnt--;
850
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();
854                 return;
855         }
856
857         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
858
859         if (surface->refcnt == 0)
860                 _tbm_surface_internal_destroy(surface);
861
862         _tbm_surface_mutex_unlock();
863 }
864
865 void
866 tbm_surface_internal_ref(tbm_surface_h surface)
867 {
868         _tbm_surface_mutex_lock();
869
870         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
871
872         surface->refcnt++;
873
874         TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
875
876         _tbm_surface_mutex_unlock();
877 }
878
879 void
880 tbm_surface_internal_unref(tbm_surface_h surface)
881 {
882         _tbm_surface_mutex_lock();
883
884         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
885
886         surface->refcnt--;
887
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();
891                 return;
892         }
893
894         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
895
896         if (surface->refcnt == 0)
897                 _tbm_surface_internal_destroy(surface);
898
899         _tbm_surface_mutex_unlock();
900 }
901
902 int
903 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
904 {
905         struct _tbm_surface *surf;
906         int num;
907
908         _tbm_surface_mutex_lock();
909
910         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
911
912         surf = (struct _tbm_surface *)surface;
913         num = surf->num_bos;
914
915         TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
916
917         _tbm_surface_mutex_unlock();
918
919         return num;
920 }
921
922 tbm_bo
923 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
924 {
925         struct _tbm_surface *surf;
926         tbm_bo bo;
927
928         _tbm_surface_mutex_lock();
929
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);
932
933         surf = (struct _tbm_surface *)surface;
934         bo = surf->bos[bo_idx];
935
936         TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
937
938         _tbm_surface_mutex_unlock();
939
940         return bo;
941 }
942
943 unsigned int
944 tbm_surface_internal_get_size(tbm_surface_h surface)
945 {
946         struct _tbm_surface *surf;
947         unsigned int size;
948
949         _tbm_surface_mutex_lock();
950
951         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
952
953         surf = (struct _tbm_surface *)surface;
954         size = surf->info.size;
955
956         TBM_TRACE("tbm_surface(%p) size(%u)\n", surface, size);
957
958         _tbm_surface_mutex_unlock();
959
960         return size;
961 }
962
963 int
964 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
965                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
966 {
967         struct _tbm_surface *surf;
968
969         _tbm_surface_mutex_lock();
970
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);
973
974         surf = (struct _tbm_surface *)surface;
975
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();
979                 return 0;
980         }
981
982         if (size)
983                 *size = surf->info.planes[plane_idx].size;
984
985         if (offset)
986                 *offset = surf->info.planes[plane_idx].offset;
987
988         if (pitch)
989                 *pitch = surf->info.planes[plane_idx].stride;
990
991         TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
992                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
993                                 surf->info.planes[plane_idx].stride);
994
995         _tbm_surface_mutex_unlock();
996
997         return 1;
998 }
999
1000 int
1001 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1002                               tbm_surface_info_s *info, int map)
1003 {
1004         struct _tbm_surface *surf;
1005         tbm_bo_handle bo_handles[4];
1006         int i, j;
1007
1008         _tbm_surface_mutex_lock();
1009
1010         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1011
1012         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1013
1014         surf = (struct _tbm_surface *)surface;
1015
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;
1023
1024         if (map == 1) {
1025                 for (i = 0; i < surf->num_bos; i++) {
1026                         _tbm_surface_mutex_unlock();
1027                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1028                         _tbm_surface_mutex_lock();
1029                         if (bo_handles[i].ptr == NULL) {
1030                                 for (j = 0; j < i; j++)
1031                                         tbm_bo_unmap(surf->bos[j]);
1032
1033                                 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1034                                 _tbm_surface_mutex_unlock();
1035                                 return 0;
1036                         }
1037                 }
1038         } else {
1039                 for (i = 0; i < surf->num_bos; i++) {
1040                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1041                         if (bo_handles[i].ptr == NULL) {
1042                                 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1043                                 _tbm_surface_mutex_unlock();
1044                                 return 0;
1045                         }
1046                 }
1047         }
1048
1049         for (i = 0; i < surf->info.num_planes; i++) {
1050                 info->planes[i].size = surf->info.planes[i].size;
1051                 info->planes[i].offset = surf->info.planes[i].offset;
1052                 info->planes[i].stride = surf->info.planes[i].stride;
1053
1054                 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1055                         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1056                                               surf->info.planes[i].offset;
1057         }
1058
1059         TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1060
1061         _tbm_surface_mutex_unlock();
1062
1063         return 1;
1064 }
1065
1066 void
1067 tbm_surface_internal_unmap(tbm_surface_h surface)
1068 {
1069         struct _tbm_surface *surf;
1070         int i;
1071
1072         _tbm_surface_mutex_lock();
1073
1074         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1075
1076         surf = (struct _tbm_surface *)surface;
1077
1078         for (i = 0; i < surf->num_bos; i++)
1079                 tbm_bo_unmap(surf->bos[i]);
1080
1081         TBM_TRACE("tbm_surface(%p)\n", surface);
1082
1083         _tbm_surface_mutex_unlock();
1084 }
1085
1086 unsigned int
1087 tbm_surface_internal_get_width(tbm_surface_h surface)
1088 {
1089         struct _tbm_surface *surf;
1090         unsigned int width;
1091
1092         _tbm_surface_mutex_lock();
1093
1094         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1095
1096         surf = (struct _tbm_surface *)surface;
1097         width = surf->info.width;
1098
1099         TBM_TRACE("tbm_surface(%p) width(%u)\n", surface, width);
1100
1101         _tbm_surface_mutex_unlock();
1102
1103         return width;
1104 }
1105
1106 unsigned int
1107 tbm_surface_internal_get_height(tbm_surface_h surface)
1108 {
1109         struct _tbm_surface *surf;
1110         unsigned int height;
1111
1112         _tbm_surface_mutex_lock();
1113
1114         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1115
1116         surf = (struct _tbm_surface *)surface;
1117         height = surf->info.height;
1118
1119         TBM_TRACE("tbm_surface(%p) height(%u)\n", surface, height);
1120
1121         _tbm_surface_mutex_unlock();
1122
1123         return height;
1124
1125 }
1126
1127 tbm_format
1128 tbm_surface_internal_get_format(tbm_surface_h surface)
1129 {
1130         struct _tbm_surface *surf;
1131         tbm_format format;
1132
1133         _tbm_surface_mutex_lock();
1134
1135         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1136
1137         surf = (struct _tbm_surface *)surface;
1138         format = surf->info.format;
1139
1140         TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1141
1142         _tbm_surface_mutex_unlock();
1143
1144         return format;
1145 }
1146
1147 int
1148 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1149 {
1150         struct _tbm_surface *surf;
1151         int bo_idx;
1152
1153         _tbm_surface_mutex_lock();
1154
1155         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1156         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1157
1158         surf = (struct _tbm_surface *)surface;
1159         bo_idx = surf->planes_bo_idx[plane_idx];
1160
1161         TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1162
1163         _tbm_surface_mutex_unlock();
1164
1165         return bo_idx;
1166 }
1167
1168 int
1169 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1170                                    tbm_data_free data_free_func)
1171 {
1172         tbm_user_data *data;
1173
1174         _tbm_surface_mutex_lock();
1175
1176         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1177
1178         /* check if the data according to the key exist if so, return false. */
1179         data = user_data_lookup(&surface->user_data_list, key);
1180         if (data) {
1181                 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1182                 _tbm_surface_mutex_unlock();
1183                 return 0;
1184         }
1185
1186         data = user_data_create(key, data_free_func);
1187         if (!data) {
1188                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1189                 _tbm_surface_mutex_unlock();
1190                 return 0;
1191         }
1192
1193         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1194
1195         LIST_ADD(&data->item_link, &surface->user_data_list);
1196
1197         _tbm_surface_mutex_unlock();
1198
1199         return 1;
1200 }
1201
1202 int
1203 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1204                                    void *data)
1205 {
1206         tbm_user_data *old_data;
1207
1208         _tbm_surface_mutex_lock();
1209
1210         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1211
1212         old_data = user_data_lookup(&surface->user_data_list, key);
1213         if (!old_data) {
1214                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1215                 _tbm_surface_mutex_unlock();
1216                 return 0;
1217         }
1218
1219         if (old_data->data && old_data->free_func)
1220                 old_data->free_func(old_data->data);
1221
1222         old_data->data = data;
1223
1224         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1225
1226         _tbm_surface_mutex_unlock();
1227
1228         return 1;
1229 }
1230
1231 int
1232 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1233                                    void **data)
1234 {
1235         tbm_user_data *old_data;
1236
1237         _tbm_surface_mutex_lock();
1238
1239         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1240
1241         if (!data) {
1242                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1243                 _tbm_surface_mutex_unlock();
1244                 return 0;
1245         }
1246         *data = NULL;
1247
1248         old_data = user_data_lookup(&surface->user_data_list, key);
1249         if (!old_data) {
1250                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1251                 _tbm_surface_mutex_unlock();
1252                 return 0;
1253         }
1254
1255         *data = old_data->data;
1256
1257         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1258
1259         _tbm_surface_mutex_unlock();
1260
1261         return 1;
1262 }
1263
1264 int
1265 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1266                                       unsigned long key)
1267 {
1268         tbm_user_data *old_data = (void *)0;
1269
1270         _tbm_surface_mutex_lock();
1271
1272         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1273
1274         old_data = user_data_lookup(&surface->user_data_list, key);
1275         if (!old_data) {
1276                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1277                 _tbm_surface_mutex_unlock();
1278                 return 0;
1279         }
1280
1281         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1282
1283         user_data_delete(old_data);
1284
1285         _tbm_surface_mutex_unlock();
1286
1287         return 1;
1288 }
1289
1290 /* LCOV_EXCL_START */
1291 unsigned int
1292 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1293 {
1294         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1295
1296         return surface->debug_pid;
1297 }
1298
1299 void
1300 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1301 {
1302         _tbm_surface_mutex_lock();
1303
1304         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1305
1306         surface->debug_pid = pid;
1307
1308         _tbm_surface_mutex_unlock();
1309 }
1310
1311 static tbm_surface_debug_data *
1312 _tbm_surface_internal_debug_data_create(char *key, char *value)
1313 {
1314         tbm_surface_debug_data *debug_data = NULL;
1315
1316         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1317         if (!debug_data)
1318                 return NULL;
1319
1320         if (key) debug_data->key = strdup(key);
1321         if (value) debug_data->value = strdup(value);
1322
1323         return debug_data;
1324 }
1325
1326 int
1327 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1328 {
1329         tbm_surface_debug_data *debug_data = NULL;
1330         tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1331         tbm_bufmgr bufmgr = NULL;
1332
1333         _tbm_surface_mutex_lock();
1334
1335         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1336         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1337
1338         bufmgr = surface->bufmgr;
1339
1340         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1341
1342         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1343                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1344                         if (!strcmp(old_data->key, key)) {
1345                                 if (old_data->value && value && !strncmp(old_data->value, value, strlen(old_data->value))) {
1346                                         TBM_TRACE("tbm_surface(%p) Already exist key(%s) and value(%s)!\n", surface, key, value);
1347                                         goto add_debug_key_list;
1348                                 }
1349
1350                                 if (old_data->value)
1351                                         free(old_data->value);
1352
1353                                 if (value)
1354                                         old_data->value = strdup(value);
1355                                 else
1356                                         old_data->value = NULL;
1357                         }
1358                 }
1359         }
1360
1361         debug_data = _tbm_surface_internal_debug_data_create(key, value);
1362         if (!debug_data) {
1363                 TBM_TRACE("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1364                 _tbm_surface_mutex_unlock();
1365                 return 0;
1366         }
1367
1368         TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1369
1370         LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1371
1372 add_debug_key_list:
1373         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1374                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1375                         if (!strcmp(old_data->key, key)) {
1376                                 _tbm_surface_mutex_unlock();
1377                                 return 1;
1378                         }
1379                 }
1380         }
1381
1382         debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1383         LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1384
1385         _tbm_surface_mutex_unlock();
1386
1387         return 1;
1388 }
1389
1390 char *
1391 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1392 {
1393         tbm_surface_debug_data *old_data = NULL;
1394
1395         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1396
1397         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1398                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1399                         if (!strcmp(old_data->key, key)) {
1400                                 return old_data->value;
1401                         }
1402                 }
1403         }
1404
1405         return NULL;
1406 }
1407
1408 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1409 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1410
1411 struct _tbm_surface_dump_buf_info {
1412         int index;
1413         tbm_bo bo;
1414         int size;
1415         int dirty;
1416         int dirty_shm;
1417         int shm_stride;
1418         int shm_h;
1419         char name[1024];
1420
1421         tbm_surface_info_s info;
1422
1423         struct list_head link;
1424 };
1425
1426 struct _tbm_surface_dump_info {
1427         char *path;  // copy???
1428         int dump_max;
1429         int count;
1430         struct list_head *link;
1431         struct list_head surface_list; /* link of surface */
1432 };
1433
1434 static tbm_surface_dump_info *g_dump_info = NULL;
1435 static const char *dump_postfix[2] = {"png", "yuv"};
1436
1437 static void
1438 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1439                                 void *data2, int size2, void *data3, int size3)
1440 {
1441         FILE *fp = fopen(file, "w+");
1442         TBM_RETURN_IF_FAIL(fp != NULL);
1443         unsigned int *blocks;
1444
1445         blocks = (unsigned int *)data1;
1446         fwrite(blocks, 1, size1, fp);
1447
1448         if (size2 > 0) {
1449                 blocks = (unsigned int *)data2;
1450                 fwrite(blocks, 1, size2, fp);
1451         }
1452
1453         if (size3 > 0) {
1454                 blocks = (unsigned int *)data3;
1455                 fwrite(blocks, 1, size3, fp);
1456         }
1457
1458         fclose(fp);
1459 }
1460
1461 static void
1462 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height)
1463 {
1464         unsigned int *blocks = (unsigned int *)data;
1465         FILE *fp = fopen(file, "wb");
1466         TBM_RETURN_IF_FAIL(fp != NULL);
1467         const int pixel_size = 4;       // RGBA
1468         png_bytep *row_pointers;
1469         int depth = 8, y;
1470
1471         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1472                                                         NULL, NULL, NULL);
1473         if (!pPngStruct) {
1474                 fclose(fp);
1475                 return;
1476         }
1477
1478         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1479         if (!pPngInfo) {
1480                 png_destroy_write_struct(&pPngStruct, NULL);
1481                 fclose(fp);
1482                 return;
1483         }
1484
1485         png_init_io(pPngStruct, fp);
1486         png_set_IHDR(pPngStruct,
1487                         pPngInfo,
1488                         width,
1489                         height,
1490                         depth,
1491                         PNG_COLOR_TYPE_RGBA,
1492                         PNG_INTERLACE_NONE,
1493                         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1494
1495         png_set_bgr(pPngStruct);
1496         png_write_info(pPngStruct, pPngInfo);
1497
1498         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1499         if (!row_pointers) {
1500                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1501                 fclose(fp);
1502                 return;
1503         }
1504
1505         for (y = 0; y < height; ++y) {
1506                 png_bytep row;
1507                 int x = 0;
1508
1509                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1510                 if (!row) {
1511                         for (x = 0; x < y; x++)
1512                                 png_free(pPngStruct, row_pointers[x]);
1513                         png_free(pPngStruct, row_pointers);
1514                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1515                         fclose(fp);
1516                         return;
1517                 }
1518                 row_pointers[y] = (png_bytep)row;
1519
1520                 for (x = 0; x < width; ++x) {
1521                         unsigned int curBlock = blocks[y * width + x];
1522
1523                         row[x * pixel_size] = (curBlock & 0xFF);
1524                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1525                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1526                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1527                 }
1528         }
1529
1530         png_write_image(pPngStruct, row_pointers);
1531         png_write_end(pPngStruct, pPngInfo);
1532
1533         for (y = 0; y < height; y++)
1534                 png_free(pPngStruct, row_pointers[y]);
1535         png_free(pPngStruct, row_pointers);
1536
1537         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1538
1539         fclose(fp);
1540 }
1541
1542 void
1543 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1544 {
1545         TBM_RETURN_IF_FAIL(path != NULL);
1546         TBM_RETURN_IF_FAIL(w > 0);
1547         TBM_RETURN_IF_FAIL(h > 0);
1548         TBM_RETURN_IF_FAIL(count > 0);
1549
1550         tbm_surface_dump_buf_info *buf_info = NULL;
1551         tbm_surface_h tbm_surface;
1552         tbm_surface_info_s info;
1553         int buffer_size, i;
1554
1555         /* check running */
1556         if (g_dump_info) {
1557                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1558                 return;
1559         }
1560
1561         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1562         TBM_RETURN_IF_FAIL(g_dump_info);
1563
1564         LIST_INITHEAD(&g_dump_info->surface_list);
1565         g_dump_info->count = 0;
1566         g_dump_info->dump_max = count;
1567
1568         /* get buffer size */
1569         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1570         if (tbm_surface == NULL) {
1571                 TBM_LOG_E("tbm_surface_create fail\n");
1572                 free(g_dump_info);
1573                 g_dump_info = NULL;
1574                 return;
1575         }
1576
1577         if (TBM_SURFACE_ERROR_NONE != tbm_surface_map(tbm_surface,
1578                                                 TBM_SURF_OPTION_READ, &info)) {
1579                 TBM_LOG_E("tbm_surface_map fail\n");
1580                 tbm_surface_destroy(tbm_surface);
1581                 free(g_dump_info);
1582                 g_dump_info = NULL;
1583                 return;
1584         }
1585         buffer_size = info.planes[0].stride * h;
1586
1587         tbm_surface_unmap(tbm_surface);
1588         tbm_surface_destroy(tbm_surface);
1589
1590         /* create dump lists */
1591         for (i = 0; i < count; i++) {
1592                 tbm_bo bo = NULL;
1593
1594                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1595                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1596
1597                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1598                 if (bo == NULL) {
1599                         free(buf_info);
1600                         goto fail;
1601                 }
1602
1603                 buf_info->index = i;
1604                 buf_info->bo = bo;
1605                 buf_info->size = buffer_size;
1606
1607                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1608         }
1609
1610         g_dump_info->path = path;
1611         g_dump_info->link = &g_dump_info->surface_list;
1612
1613         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1614
1615         return;
1616
1617 fail:
1618         /* free resources */
1619         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1620                 tbm_surface_dump_buf_info *tmp;
1621
1622                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1623                         tbm_bo_unref(buf_info->bo);
1624                         LIST_DEL(&buf_info->link);
1625                         free(buf_info);
1626                 }
1627         }
1628
1629         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1630
1631         free(g_dump_info);
1632         g_dump_info = NULL;
1633
1634         return;
1635 }
1636
1637 void
1638 tbm_surface_internal_dump_end(void)
1639 {
1640         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1641         tbm_bo_handle bo_handle;
1642
1643         if (!g_dump_info)
1644                 return;
1645
1646         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1647                 free(g_dump_info);
1648                 g_dump_info = NULL;
1649                 return;
1650         }
1651
1652         /* make files */
1653         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1654                 char file[2048];
1655
1656                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1657                 if (bo_handle.ptr == NULL) {
1658                         tbm_bo_unref(buf_info->bo);
1659                         LIST_DEL(&buf_info->link);
1660                         free(buf_info);
1661                         continue;
1662                 }
1663
1664                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1665                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1666
1667                 if (buf_info->dirty) {
1668                         void *ptr1 = NULL, *ptr2 = NULL;
1669
1670                         switch (buf_info->info.format) {
1671                         case TBM_FORMAT_ARGB8888:
1672                         case TBM_FORMAT_XRGB8888:
1673                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1674                                                         buf_info->info.planes[0].stride >> 2,
1675                                                         buf_info->info.height);
1676                                 break;
1677                         case TBM_FORMAT_YVU420:
1678                         case TBM_FORMAT_YUV420:
1679                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1680                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1681                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1682                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1683                                                         ptr1,
1684                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1685                                                         ptr2,
1686                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1687                                 break;
1688                         case TBM_FORMAT_NV12:
1689                         case TBM_FORMAT_NV21:
1690                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1691                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1692                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1693                                                         ptr1,
1694                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1695                                                         NULL, 0);
1696                                 break;
1697                         case TBM_FORMAT_YUYV:
1698                         case TBM_FORMAT_UYVY:
1699                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1700                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1701                                                         NULL, 0, NULL, 0);
1702                                 break;
1703                         default:
1704                                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1705                                 break;
1706                         }
1707                 } else if (buf_info->dirty_shm)
1708                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1709                                                         buf_info->shm_stride >> 2,
1710                                                         buf_info->shm_h);
1711
1712                 tbm_bo_unmap(buf_info->bo);
1713                 tbm_bo_unref(buf_info->bo);
1714                 LIST_DEL(&buf_info->link);
1715                 free(buf_info);
1716         }
1717
1718         free(g_dump_info);
1719         g_dump_info = NULL;
1720
1721         TBM_LOG_I("Dump End..\n");
1722 }
1723
1724 void
1725 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1726 {
1727         TBM_RETURN_IF_FAIL(surface != NULL);
1728         TBM_RETURN_IF_FAIL(type != NULL);
1729
1730         tbm_surface_dump_buf_info *buf_info;
1731         struct list_head *next_link;
1732         tbm_surface_info_s info;
1733         tbm_bo_handle bo_handle;
1734         const char *postfix;
1735         int ret;
1736
1737         if (!g_dump_info)
1738                 return;
1739
1740         next_link = g_dump_info->link->next;
1741         TBM_RETURN_IF_FAIL(next_link != NULL);
1742
1743         if (next_link == &g_dump_info->surface_list) {
1744                 next_link = next_link->next;
1745                 TBM_RETURN_IF_FAIL(next_link != NULL);
1746         }
1747
1748         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1749         TBM_RETURN_IF_FAIL(buf_info != NULL);
1750
1751         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1752         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1753
1754         if (info.size > buf_info->size) {
1755                 TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1756                                 info.size, buf_info->size);
1757                 tbm_surface_unmap(surface);
1758                 return;
1759         }
1760
1761         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1762                 postfix = dump_postfix[0];
1763         else
1764                 postfix = dump_postfix[1];
1765
1766         /* make the file information */
1767         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1768
1769         /* dump */
1770         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1771         if (!bo_handle.ptr) {
1772                 TBM_LOG_E("fail to map bo");
1773                 tbm_surface_unmap(surface);
1774                 return;
1775         }
1776         memset(bo_handle.ptr, 0x00, buf_info->size);
1777
1778         switch (info.format) {
1779         case TBM_FORMAT_ARGB8888:
1780         case TBM_FORMAT_XRGB8888:
1781                 snprintf(buf_info->name, sizeof(buf_info->name),
1782                                 "%10.3f_%03d_%p-%s.%s",
1783                                  _tbm_surface_internal_get_time(),
1784                                  g_dump_info->count++, surface, type, postfix);
1785                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1786                 break;
1787         case TBM_FORMAT_YVU420:
1788         case TBM_FORMAT_YUV420:
1789                 snprintf(buf_info->name, sizeof(buf_info->name),
1790                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1791                                  _tbm_surface_internal_get_time(),
1792                                  g_dump_info->count++, type, info.planes[0].stride,
1793                                 info.height, FOURCC_STR(info.format), postfix);
1794                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1795                 bo_handle.ptr += info.planes[0].stride * info.height;
1796                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1797                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1798                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1799                 break;
1800         case TBM_FORMAT_NV12:
1801         case TBM_FORMAT_NV21:
1802                 snprintf(buf_info->name, sizeof(buf_info->name),
1803                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1804                                  _tbm_surface_internal_get_time(),
1805                                  g_dump_info->count++, type, info.planes[0].stride,
1806                                 info.height, FOURCC_STR(info.format), postfix);
1807                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1808                 bo_handle.ptr += info.planes[0].stride * info.height;
1809                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1810                 break;
1811         case TBM_FORMAT_YUYV:
1812         case TBM_FORMAT_UYVY:
1813                 snprintf(buf_info->name, sizeof(buf_info->name),
1814                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1815                                  _tbm_surface_internal_get_time(),
1816                                  g_dump_info->count++, type, info.planes[0].stride,
1817                                 info.height, FOURCC_STR(info.format), postfix);
1818                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1819                 break;
1820         default:
1821                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1822                 tbm_bo_unmap(buf_info->bo);
1823                 tbm_surface_unmap(surface);
1824                 return;
1825         }
1826
1827         tbm_bo_unmap(buf_info->bo);
1828
1829         tbm_surface_unmap(surface);
1830
1831         buf_info->dirty = 1;
1832         buf_info->dirty_shm = 0;
1833
1834         if (g_dump_info->count == 1000)
1835                 g_dump_info->count = 0;
1836
1837         g_dump_info->link = next_link;
1838
1839         TBM_LOG_I("Dump %s \n", buf_info->name);
1840 }
1841
1842 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
1843                                                 const char *type)
1844 {
1845         TBM_RETURN_IF_FAIL(ptr != NULL);
1846         TBM_RETURN_IF_FAIL(w > 0);
1847         TBM_RETURN_IF_FAIL(h > 0);
1848         TBM_RETURN_IF_FAIL(stride > 0);
1849         TBM_RETURN_IF_FAIL(type != NULL);
1850
1851         tbm_surface_dump_buf_info *buf_info;
1852         struct list_head *next_link;
1853         tbm_bo_handle bo_handle;
1854         int size;
1855
1856         if (!g_dump_info)
1857                 return;
1858
1859         next_link = g_dump_info->link->next;
1860         TBM_RETURN_IF_FAIL(next_link != NULL);
1861
1862         if (next_link == &g_dump_info->surface_list) {
1863                 next_link = next_link->next;
1864                 TBM_RETURN_IF_FAIL(next_link != NULL);
1865         }
1866
1867         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1868         TBM_RETURN_IF_FAIL(buf_info != NULL);
1869
1870         size = stride * h;
1871         if (size > buf_info->size) {
1872                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
1873                                 size, buf_info->size);
1874                 return;
1875         }
1876
1877         /* dump */
1878         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1879         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1880
1881         memset(bo_handle.ptr, 0x00, buf_info->size);
1882         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1883
1884         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1885                          _tbm_surface_internal_get_time(),
1886                          g_dump_info->count++, type, dump_postfix[0]);
1887         memcpy(bo_handle.ptr, ptr, size);
1888
1889         tbm_bo_unmap(buf_info->bo);
1890
1891         buf_info->dirty = 0;
1892         buf_info->dirty_shm = 1;
1893         buf_info->shm_stride = stride;
1894         buf_info->shm_h = h;
1895
1896         if (g_dump_info->count == 1000)
1897                 g_dump_info->count = 0;
1898
1899         g_dump_info->link = next_link;
1900
1901         TBM_LOG_I("Dump %s \n", buf_info->name);
1902 }
1903
1904 int
1905 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
1906 {
1907         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
1908         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1909         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
1910
1911         tbm_surface_info_s info;
1912         const char *postfix;
1913         int ret;
1914         char file[1024];
1915
1916         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1917         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
1918
1919         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1920                 postfix = dump_postfix[0];
1921         else
1922                 postfix = dump_postfix[1];
1923
1924         if (strcmp(postfix, type)) {
1925                 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
1926                 tbm_surface_unmap(surface);
1927                 return 0;
1928         }
1929
1930         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
1931
1932         if (!access(file, 0)) {
1933                 TBM_LOG_E("can't capture  buffer, exist file %s", file);
1934                 tbm_surface_unmap(surface);
1935                 return 0;
1936         }
1937
1938         switch (info.format) {
1939         case TBM_FORMAT_ARGB8888:
1940         case TBM_FORMAT_XRGB8888:
1941                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
1942                                                         info.planes[0].stride >> 2,
1943                                                         info.height);
1944                 break;
1945         case TBM_FORMAT_YVU420:
1946         case TBM_FORMAT_YUV420:
1947                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
1948                                 info.planes[0].stride * info.height,
1949                                 info.planes[1].ptr,
1950                                 info.planes[1].stride * (info.height >> 1),
1951                                 info.planes[2].ptr,
1952                                 info.planes[2].stride * (info.height >> 1));
1953                 break;
1954         case TBM_FORMAT_NV12:
1955         case TBM_FORMAT_NV21:
1956                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
1957                                         info.planes[0].stride * info.height,
1958                                         info.planes[1].ptr,
1959                                         info.planes[1].stride * (info.height >> 1),
1960                                         NULL, 0);
1961                 break;
1962         case TBM_FORMAT_YUYV:
1963         case TBM_FORMAT_UYVY:
1964                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
1965                                         info.planes[0].stride * info.height,
1966                                         NULL, 0, NULL, 0);
1967                 break;
1968         default:
1969                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
1970                 tbm_surface_unmap(surface);
1971                 return 0;
1972         }
1973
1974         tbm_surface_unmap(surface);
1975
1976         TBM_LOG_I("Capture %s \n", file);
1977
1978         return 1;
1979 }
1980
1981 int
1982 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
1983                                                 const char *path, const char *name, const char *type)
1984 {
1985         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
1986         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
1987         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
1988         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
1989         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1990         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
1991
1992         char file[1024];
1993
1994         if (strcmp(dump_postfix[0], type)) {
1995                 TBM_LOG_E("Not supported type:%s'", type);
1996                 return 0;
1997         }
1998
1999         if (!access(file, 0)) {
2000                 TBM_LOG_E("can't capture buffer, exist file %s", file);
2001                 return 0;
2002         }
2003
2004         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2005
2006         _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2007
2008         TBM_LOG_I("Capture %s \n", file);
2009
2010         return 1;
2011 }
2012 /*LCOV_EXCL_STOP*/