enforce the thread safety of the tbm_surface
[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 #include <stdio.h>
34 #include <time.h>
35 #include <sys/time.h>
36 #include "tbm_bufmgr.h"
37 #include "tbm_bufmgr_int.h"
38 #include "tbm_surface_internal.h"
39 #include "list.h"
40 #include <png.h>
41
42 static tbm_bufmgr g_surface_bufmgr;
43 static pthread_mutex_t tbm_surface_lock;
44 void _tbm_surface_mutex_unlock(void);
45
46 #define C(b, m)              (((b) >> (m)) & 0xFF)
47 #define B(c, s)              ((((unsigned int)(c)) & 0xff) << (s))
48 #define FOURCC(a, b, c, d)     (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
49 #define FOURCC_STR(id)      C(id, 0), C(id, 8), C(id, 16), C(id, 24)
50 #define FOURCC_ID(str)      FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3])
51
52 /* check condition */
53 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
54         if (!(cond)) {\
55                 TBM_LOG_E("'%s' failed.\n", #cond);\
56                 _tbm_surface_mutex_unlock();\
57                 return;\
58         } \
59 }
60
61 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
62         if (!(cond)) {\
63                 TBM_LOG_E("'%s' failed.\n", #cond);\
64                 _tbm_surface_mutex_unlock();\
65                 return val;\
66         } \
67 }
68
69 /* LCOV_EXCL_START */
70 #define USE_REALTIME 1
71
72 static double
73 _tbm_surface_internal_get_time(void)
74 {
75         struct timespec tp;
76         unsigned int time;
77
78 #if USE_REALTIME
79         clock_gettime(CLOCK_REALTIME, &tp);
80 #else /* USE_MONOTONIC */
81         clock_gettime(CLOCK_MONOTONIC, &tp);
82 #endif
83         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
84
85         return time / 1000.0;
86 }
87
88 static void
89 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
90 {
91         LIST_DEL(&debug_data->item_link);
92
93         if (debug_data->key) free(debug_data->key);
94         if (debug_data->value) free(debug_data->value);
95         free(debug_data);
96 }
97
98 char *
99 _tbm_surface_internal_format_to_str(tbm_format format)
100 {
101         switch (format) {
102         case TBM_FORMAT_C8:
103                 return "TBM_FORMAT_C8";
104         case TBM_FORMAT_RGB332:
105                 return "TBM_FORMAT_RGB332";
106         case TBM_FORMAT_BGR233:
107                 return "TBM_FORMAT_BGR233";
108         case TBM_FORMAT_XRGB4444:
109                 return "TBM_FORMAT_XRGB4444";
110         case TBM_FORMAT_XBGR4444:
111                 return "TBM_FORMAT_XBGR4444";
112         case TBM_FORMAT_RGBX4444:
113                 return "TBM_FORMAT_RGBX4444";
114         case TBM_FORMAT_BGRX4444:
115                 return "TBM_FORMAT_BGRX4444";
116         case TBM_FORMAT_ARGB4444:
117                 return "TBM_FORMAT_ARGB4444";
118         case TBM_FORMAT_ABGR4444:
119                 return "TBM_FORMAT_ABGR4444";
120         case TBM_FORMAT_RGBA4444:
121                 return "TBM_FORMAT_RGBA4444";
122         case TBM_FORMAT_BGRA4444:
123                 return "TBM_FORMAT_BGRA4444";
124         case TBM_FORMAT_XRGB1555:
125                 return "TBM_FORMAT_XRGB1555";
126         case TBM_FORMAT_XBGR1555:
127                 return "TBM_FORMAT_XBGR1555";
128         case TBM_FORMAT_RGBX5551:
129                 return "TBM_FORMAT_RGBX5551";
130         case TBM_FORMAT_BGRX5551:
131                 return "TBM_FORMAT_BGRX5551";
132         case TBM_FORMAT_ARGB1555:
133                 return "TBM_FORMAT_ARGB1555";
134         case TBM_FORMAT_ABGR1555:
135                 return "TBM_FORMAT_ABGR1555";
136         case TBM_FORMAT_RGBA5551:
137                 return "TBM_FORMAT_RGBA5551";
138         case TBM_FORMAT_BGRA5551:
139                 return "TBM_FORMAT_BGRA5551";
140         case TBM_FORMAT_RGB565:
141                 return "TBM_FORMAT_RGB565";
142         case TBM_FORMAT_BGR565:
143                 return "TBM_FORMAT_BGR565";
144         case TBM_FORMAT_RGB888:
145                 return "TBM_FORMAT_RGB888";
146         case TBM_FORMAT_BGR888:
147                 return "TBM_FORMAT_BGR888";
148         case TBM_FORMAT_XRGB8888:
149                 return "TBM_FORMAT_XRGB8888";
150         case TBM_FORMAT_XBGR8888:
151                 return "TBM_FORMAT_XBGR8888";
152         case TBM_FORMAT_RGBX8888:
153                 return "TBM_FORMAT_RGBX8888";
154         case TBM_FORMAT_BGRX8888:
155                 return "TBM_FORMAT_BGRX8888";
156         case TBM_FORMAT_ARGB8888:
157                 return "TBM_FORMAT_ARGB8888";
158         case TBM_FORMAT_ABGR8888:
159                 return "TBM_FORMAT_ABGR8888";
160         case TBM_FORMAT_RGBA8888:
161                 return "TBM_FORMAT_RGBA8888";
162         case TBM_FORMAT_BGRA8888:
163                 return "TBM_FORMAT_BGRA8888";
164         case TBM_FORMAT_XRGB2101010:
165                 return "TBM_FORMAT_XRGB2101010";
166         case TBM_FORMAT_XBGR2101010:
167                 return "TBM_FORMAT_XBGR2101010";
168         case TBM_FORMAT_RGBX1010102:
169                 return "TBM_FORMAT_RGBX1010102";
170         case TBM_FORMAT_BGRX1010102:
171                 return "TBM_FORMAT_BGRX1010102";
172         case TBM_FORMAT_ARGB2101010:
173                 return "TBM_FORMAT_ARGB2101010";
174         case TBM_FORMAT_ABGR2101010:
175                 return "TBM_FORMAT_ABGR2101010";
176         case TBM_FORMAT_RGBA1010102:
177                 return "TBM_FORMAT_RGBA1010102";
178         case TBM_FORMAT_BGRA1010102:
179                 return "TBM_FORMAT_BGRA1010102";
180         case TBM_FORMAT_YUYV:
181                 return "TBM_FORMAT_YUYV";
182         case TBM_FORMAT_YVYU:
183                 return "TBM_FORMAT_YVYU";
184         case TBM_FORMAT_UYVY:
185                 return "TBM_FORMAT_UYVY";
186         case TBM_FORMAT_VYUY:
187                 return "TBM_FORMAT_VYUY";
188         case TBM_FORMAT_AYUV:
189                 return "TBM_FORMAT_AYUV";
190         case TBM_FORMAT_NV12:
191                 return "TBM_FORMAT_NV12";
192         case TBM_FORMAT_NV21:
193                 return "TBM_FORMAT_NV21";
194         case TBM_FORMAT_NV16:
195                 return "TBM_FORMAT_NV16";
196         case TBM_FORMAT_NV61:
197                 return "TBM_FORMAT_NV61";
198         case TBM_FORMAT_YUV410:
199                 return "TBM_FORMAT_YUV410";
200         case TBM_FORMAT_YVU410:
201                 return "TBM_FORMAT_YVU410";
202         case TBM_FORMAT_YUV411:
203                 return "TBM_FORMAT_YUV411";
204         case TBM_FORMAT_YVU411:
205                 return "TBM_FORMAT_YVU411";
206         case TBM_FORMAT_YUV420:
207                 return "TBM_FORMAT_YUV420";
208         case TBM_FORMAT_YVU420:
209                 return "TBM_FORMAT_YVU420";
210         case TBM_FORMAT_YUV422:
211                 return "TBM_FORMAT_YUV422";
212         case TBM_FORMAT_YVU422:
213                 return "TBM_FORMAT_YVU422";
214         case TBM_FORMAT_YUV444:
215                 return "TBM_FORMAT_YUV444";
216         case TBM_FORMAT_YVU444:
217                 return "TBM_FORMAT_YVU444";
218         case TBM_FORMAT_NV12MT:
219                 return "TBM_FORMAT_NV12MT";
220         default:
221                 return "unknwon";
222         }
223 }
224 /* LCOV_EXCL_STOP */
225
226 static bool
227 _tbm_surface_mutex_init(void)
228 {
229         static bool tbm_surface_mutex_init = false;
230
231         if (tbm_surface_mutex_init)
232                 return true;
233
234         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
235                 TBM_LOG_E("fail: tbm_surface mutex init\n");
236                 return false;
237         }
238
239         tbm_surface_mutex_init = true;
240
241         return true;
242 }
243
244 void
245 _tbm_surface_mutex_lock(void)
246 {
247         if (!_tbm_surface_mutex_init())
248                 return;
249
250         pthread_mutex_lock(&tbm_surface_lock);
251 }
252
253 void
254 _tbm_surface_mutex_unlock(void)
255 {
256         pthread_mutex_unlock(&tbm_surface_lock);
257 }
258
259 static void
260 _init_surface_bufmgr(void)
261 {
262         g_surface_bufmgr = tbm_bufmgr_init(-1);
263 }
264
265 static void
266 _deinit_surface_bufmgr(void)
267 {
268         if (!g_surface_bufmgr)
269                 return;
270
271         tbm_bufmgr_deinit(g_surface_bufmgr);
272         g_surface_bufmgr = NULL;
273 }
274
275 static int
276 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
277                                        int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
278 {
279         TBM_RETURN_VAL_IF_FAIL(surface, 0);
280         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
281
282         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
283         struct _tbm_bufmgr *mgr = surf->bufmgr;
284         int ret = 0;
285
286         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
287         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
288         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
289         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
290
291         if (!mgr->backend->surface_get_plane_data)
292                 return 0;
293
294         ret = mgr->backend->surface_get_plane_data(surf->info.width,
295                         surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
296         if (!ret)
297                 return 0;
298
299         return 1;
300 }
301
302 static void
303 _tbm_surface_internal_destroy(tbm_surface_h surface)
304 {
305         int i;
306         tbm_bufmgr bufmgr = surface->bufmgr;
307         tbm_user_data *old_data = NULL, *tmp = NULL;
308         tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
309
310         /* destory the user_data_list */
311         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
312                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
313                         DBG("free user_data\n");
314                         user_data_delete(old_data);
315                 }
316         }
317
318         for (i = 0; i < surface->num_bos; i++) {
319                 surface->bos[i]->surface = NULL;
320
321                 tbm_bo_unref(surface->bos[i]);
322                 surface->bos[i] = NULL;
323         }
324
325         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
326                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
327                         _tbm_surface_internal_debug_data_delete(debug_old_data);
328         }
329
330         LIST_DEL(&surface->item_link);
331
332         free(surface);
333         surface = NULL;
334
335         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
336                 LIST_DELINIT(&bufmgr->surf_list);
337
338                 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
339                         LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
340                                 _tbm_surface_internal_debug_data_delete(debug_old_data);
341                         }
342                 }
343
344                 _deinit_surface_bufmgr();
345         }
346 }
347
348 int
349 tbm_surface_internal_is_valid(tbm_surface_h surface)
350 {
351         tbm_surface_h old_data = NULL, tmp = NULL;
352
353         if (surface == NULL || g_surface_bufmgr == NULL) {
354                 TBM_TRACE("error: tbm_surface(%p)\n", surface);
355                 return 0;
356         }
357
358         if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
359                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &g_surface_bufmgr->surf_list, item_link) {
360                         if (old_data == surface) {
361                                 TBM_TRACE("tbm_surface(%p)\n", surface);
362                                 return 1;
363                         }
364                 }
365         }
366         TBM_TRACE("error: tbm_surface(%p)\n", surface);
367         return 0;
368 }
369
370 int
371 tbm_surface_internal_query_supported_formats(uint32_t **formats,
372                 uint32_t *num)
373 {
374         struct _tbm_bufmgr *mgr;
375         int ret = 0;
376
377         _tbm_surface_mutex_lock();
378
379         if (!g_surface_bufmgr) {
380                 _init_surface_bufmgr();
381                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
382         }
383
384         mgr = g_surface_bufmgr;
385
386         if (!mgr->backend->surface_supported_format) {
387                 TBM_TRACE("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
388                 _tbm_surface_mutex_unlock();
389                 return 0;
390         }
391
392         ret = mgr->backend->surface_supported_format(formats, num);
393
394         TBM_TRACE("tbm_bufmgr(%p) format num(%d)\n", g_surface_bufmgr, *num);
395
396         _tbm_surface_mutex_unlock();
397
398         return ret;
399 }
400
401 int
402 tbm_surface_internal_get_num_planes(tbm_format format)
403 {
404         int num_planes = 0;
405
406         switch (format) {
407         case TBM_FORMAT_C8:
408         case TBM_FORMAT_RGB332:
409         case TBM_FORMAT_BGR233:
410         case TBM_FORMAT_XRGB4444:
411         case TBM_FORMAT_XBGR4444:
412         case TBM_FORMAT_RGBX4444:
413         case TBM_FORMAT_BGRX4444:
414         case TBM_FORMAT_ARGB4444:
415         case TBM_FORMAT_ABGR4444:
416         case TBM_FORMAT_RGBA4444:
417         case TBM_FORMAT_BGRA4444:
418         case TBM_FORMAT_XRGB1555:
419         case TBM_FORMAT_XBGR1555:
420         case TBM_FORMAT_RGBX5551:
421         case TBM_FORMAT_BGRX5551:
422         case TBM_FORMAT_ARGB1555:
423         case TBM_FORMAT_ABGR1555:
424         case TBM_FORMAT_RGBA5551:
425         case TBM_FORMAT_BGRA5551:
426         case TBM_FORMAT_RGB565:
427         case TBM_FORMAT_BGR565:
428         case TBM_FORMAT_RGB888:
429         case TBM_FORMAT_BGR888:
430         case TBM_FORMAT_XRGB8888:
431         case TBM_FORMAT_XBGR8888:
432         case TBM_FORMAT_RGBX8888:
433         case TBM_FORMAT_BGRX8888:
434         case TBM_FORMAT_ARGB8888:
435         case TBM_FORMAT_ABGR8888:
436         case TBM_FORMAT_RGBA8888:
437         case TBM_FORMAT_BGRA8888:
438         case TBM_FORMAT_XRGB2101010:
439         case TBM_FORMAT_XBGR2101010:
440         case TBM_FORMAT_RGBX1010102:
441         case TBM_FORMAT_BGRX1010102:
442         case TBM_FORMAT_ARGB2101010:
443         case TBM_FORMAT_ABGR2101010:
444         case TBM_FORMAT_RGBA1010102:
445         case TBM_FORMAT_BGRA1010102:
446         case TBM_FORMAT_YUYV:
447         case TBM_FORMAT_YVYU:
448         case TBM_FORMAT_UYVY:
449         case TBM_FORMAT_VYUY:
450         case TBM_FORMAT_AYUV:
451                 num_planes = 1;
452                 break;
453         case TBM_FORMAT_NV12:
454         case TBM_FORMAT_NV12MT:
455         case TBM_FORMAT_NV21:
456         case TBM_FORMAT_NV16:
457         case TBM_FORMAT_NV61:
458                 num_planes = 2;
459                 break;
460         case TBM_FORMAT_YUV410:
461         case TBM_FORMAT_YVU410:
462         case TBM_FORMAT_YUV411:
463         case TBM_FORMAT_YVU411:
464         case TBM_FORMAT_YUV420:
465         case TBM_FORMAT_YVU420:
466         case TBM_FORMAT_YUV422:
467         case TBM_FORMAT_YVU422:
468         case TBM_FORMAT_YUV444:
469         case TBM_FORMAT_YVU444:
470                 num_planes = 3;
471                 break;
472
473         default:
474                 break;
475         }
476
477         TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
478
479         return num_planes;
480 }
481
482 int
483 tbm_surface_internal_get_bpp(tbm_format format)
484 {
485
486         int bpp = 0;
487
488         switch (format) {
489         case TBM_FORMAT_C8:
490         case TBM_FORMAT_RGB332:
491         case TBM_FORMAT_BGR233:
492                 bpp = 8;
493                 break;
494         case TBM_FORMAT_XRGB4444:
495         case TBM_FORMAT_XBGR4444:
496         case TBM_FORMAT_RGBX4444:
497         case TBM_FORMAT_BGRX4444:
498         case TBM_FORMAT_ARGB4444:
499         case TBM_FORMAT_ABGR4444:
500         case TBM_FORMAT_RGBA4444:
501         case TBM_FORMAT_BGRA4444:
502         case TBM_FORMAT_XRGB1555:
503         case TBM_FORMAT_XBGR1555:
504         case TBM_FORMAT_RGBX5551:
505         case TBM_FORMAT_BGRX5551:
506         case TBM_FORMAT_ARGB1555:
507         case TBM_FORMAT_ABGR1555:
508         case TBM_FORMAT_RGBA5551:
509         case TBM_FORMAT_BGRA5551:
510         case TBM_FORMAT_RGB565:
511         case TBM_FORMAT_BGR565:
512                 bpp = 16;
513                 break;
514         case TBM_FORMAT_RGB888:
515         case TBM_FORMAT_BGR888:
516                 bpp = 24;
517                 break;
518         case TBM_FORMAT_XRGB8888:
519         case TBM_FORMAT_XBGR8888:
520         case TBM_FORMAT_RGBX8888:
521         case TBM_FORMAT_BGRX8888:
522         case TBM_FORMAT_ARGB8888:
523         case TBM_FORMAT_ABGR8888:
524         case TBM_FORMAT_RGBA8888:
525         case TBM_FORMAT_BGRA8888:
526         case TBM_FORMAT_XRGB2101010:
527         case TBM_FORMAT_XBGR2101010:
528         case TBM_FORMAT_RGBX1010102:
529         case TBM_FORMAT_BGRX1010102:
530         case TBM_FORMAT_ARGB2101010:
531         case TBM_FORMAT_ABGR2101010:
532         case TBM_FORMAT_RGBA1010102:
533         case TBM_FORMAT_BGRA1010102:
534         case TBM_FORMAT_YUYV:
535         case TBM_FORMAT_YVYU:
536         case TBM_FORMAT_UYVY:
537         case TBM_FORMAT_VYUY:
538         case TBM_FORMAT_AYUV:
539                 bpp = 32;
540                 break;
541         case TBM_FORMAT_NV12:
542         case TBM_FORMAT_NV12MT:
543         case TBM_FORMAT_NV21:
544                 bpp = 12;
545                 break;
546         case TBM_FORMAT_NV16:
547         case TBM_FORMAT_NV61:
548                 bpp = 16;
549                 break;
550         case TBM_FORMAT_YUV410:
551         case TBM_FORMAT_YVU410:
552                 bpp = 9;
553                 break;
554         case TBM_FORMAT_YUV411:
555         case TBM_FORMAT_YVU411:
556         case TBM_FORMAT_YUV420:
557         case TBM_FORMAT_YVU420:
558                 bpp = 12;
559                 break;
560         case TBM_FORMAT_YUV422:
561         case TBM_FORMAT_YVU422:
562                 bpp = 16;
563                 break;
564         case TBM_FORMAT_YUV444:
565         case TBM_FORMAT_YVU444:
566                 bpp = 24;
567                 break;
568         default:
569                 break;
570         }
571
572         TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
573
574         return bpp;
575 }
576
577 tbm_surface_h
578 tbm_surface_internal_create_with_flags(int width, int height,
579                                        int format, int flags)
580 {
581         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
582         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
583
584         struct _tbm_bufmgr *mgr;
585         struct _tbm_surface *surf = NULL;
586         uint32_t size = 0;
587         uint32_t offset = 0;
588         uint32_t stride = 0;
589         uint32_t bo_size = 0;
590         int bo_idx;
591         int i, j;
592
593         _tbm_surface_mutex_lock();
594
595         if (!g_surface_bufmgr) {
596                 _init_surface_bufmgr();
597                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
598         }
599
600         mgr = g_surface_bufmgr;
601         if (!TBM_BUFMGR_IS_VALID(mgr)) {
602                 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
603                                 width, height, _tbm_surface_internal_format_to_str(format), flags);
604                 _tbm_surface_mutex_unlock();
605                 return NULL;
606         }
607         surf = calloc(1, sizeof(struct _tbm_surface));
608         if (!surf) {
609                 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
610                                 width, height, _tbm_surface_internal_format_to_str(format), flags);
611                 _tbm_surface_mutex_unlock();
612                 return NULL;
613         }
614
615         surf->bufmgr = mgr;
616         surf->info.width = width;
617         surf->info.height = height;
618         surf->info.format = format;
619         surf->info.bpp = tbm_surface_internal_get_bpp(format);
620         surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
621         surf->refcnt = 1;
622
623         /* get size, stride and offset bo_idx */
624         for (i = 0; i < surf->info.num_planes; i++) {
625                 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride,
626                                                        &bo_idx);
627                 surf->info.planes[i].size = size;
628                 surf->info.planes[i].offset = offset;
629                 surf->info.planes[i].stride = stride;
630                 surf->planes_bo_idx[i] = bo_idx;
631         }
632
633         surf->num_bos = 1;
634
635         for (i = 0; i < surf->info.num_planes; i++) {
636                 surf->info.size += surf->info.planes[i].size;
637
638                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
639                         surf->num_bos = surf->planes_bo_idx[i] + 1;
640         }
641
642         surf->flags = flags;
643
644         for (i = 0; i < surf->num_bos; i++) {
645                 bo_size = 0;
646                 for (j = 0; j < surf->info.num_planes; j++) {
647                         if (surf->planes_bo_idx[j] == i)
648                                 bo_size += surf->info.planes[j].size;
649                 }
650
651                 if (mgr->backend->surface_bo_alloc) {
652                         /* LCOV_EXCL_START */
653                         tbm_bo bo = NULL;
654                         void *bo_priv = NULL;
655
656                         bo = calloc(1, sizeof(struct _tbm_bo));
657                         if (!bo) {
658                                 TBM_LOG_E("fail to alloc bo struct\n");
659                                 goto alloc_fail;
660                         }
661
662                         bo->bufmgr = surf->bufmgr;
663
664                         pthread_mutex_lock(&surf->bufmgr->lock);
665
666                         bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
667                         if (!bo_priv) {
668                                 TBM_LOG_E("fail to alloc bo priv\n");
669                                 free(bo);
670                                 pthread_mutex_unlock(&surf->bufmgr->lock);
671                                 goto alloc_fail;
672                         }
673
674                         bo->ref_cnt = 1;
675                         bo->flags = flags;
676                         bo->priv = bo_priv;
677
678                         LIST_INITHEAD(&bo->user_data_list);
679
680                         LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
681
682                         pthread_mutex_unlock(&surf->bufmgr->lock);
683
684                         surf->bos[i] = bo;
685                         /* LCOV_EXCL_STOP */
686                 } else {
687                         surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
688                 }
689
690                 if (!surf->bos[i]) {
691                         TBM_LOG_E("fail to alloc bo idx:%d\n", i);
692                         goto alloc_fail;
693                 }
694
695                 _tbm_bo_set_surface(surf->bos[i], surf);
696
697         }
698
699         TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
700                         _tbm_surface_internal_format_to_str(format), flags, surf);
701
702         LIST_INITHEAD(&surf->user_data_list);
703         LIST_INITHEAD(&surf->debug_data_list);
704
705         LIST_ADD(&surf->item_link, &mgr->surf_list);
706
707         _tbm_surface_mutex_unlock();
708
709         return surf;
710
711 alloc_fail:
712
713         TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
714                         width, height, _tbm_surface_internal_format_to_str(format), flags);
715
716         for (j = 0; j < i; j++) {
717                 if (surf->bos[j])
718                         tbm_bo_unref(surf->bos[j]);
719         }
720
721         free(surf);
722         surf = NULL;
723
724         if (LIST_IS_EMPTY(&mgr->surf_list)) {
725                 LIST_DELINIT(&mgr->surf_list);
726                 _deinit_surface_bufmgr();
727         }
728
729         _tbm_surface_mutex_unlock();
730         return NULL;
731 }
732
733 tbm_surface_h
734 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
735                                      tbm_bo *bos, int num)
736 {
737         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
738         TBM_RETURN_VAL_IF_FAIL(info, NULL);
739         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
740
741         struct _tbm_bufmgr *mgr;
742         struct _tbm_surface *surf = NULL;
743         int i;
744
745         _tbm_surface_mutex_lock();
746
747         if (!g_surface_bufmgr) {
748                 _init_surface_bufmgr();
749                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
750         }
751
752         mgr = g_surface_bufmgr;
753         if (!TBM_BUFMGR_IS_VALID(mgr)) {
754                 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
755                                 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
756                 _tbm_surface_mutex_unlock();
757                 return NULL;
758         }
759
760         surf = calloc(1, sizeof(struct _tbm_surface));
761         if (!surf) {
762                 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
763                                 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
764                 _tbm_surface_mutex_unlock();
765                 return NULL;
766         }
767
768         surf->bufmgr = mgr;
769         surf->info.width = info->width;
770         surf->info.height = info->height;
771         surf->info.format = info->format;
772         surf->info.bpp = info->bpp;
773         surf->info.num_planes = info->num_planes;
774         surf->refcnt = 1;
775
776         /* get size, stride and offset */
777         for (i = 0; i < info->num_planes; i++) {
778                 surf->info.planes[i].offset = info->planes[i].offset;
779                 surf->info.planes[i].stride = info->planes[i].stride;
780
781                 if (info->planes[i].size > 0)
782                         surf->info.planes[i].size = info->planes[i].size;
783                 else
784                         surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
785
786                 if (num == 1)
787                         surf->planes_bo_idx[i] = 0;
788                 else
789                         surf->planes_bo_idx[i] = i;
790         }
791
792         if (info->size > 0) {
793                 surf->info.size = info->size;
794         } else {
795                 surf->info.size = 0;
796                 for (i = 0; i < info->num_planes; i++)
797                         surf->info.size += surf->info.planes[i].size;
798         }
799
800         surf->flags = TBM_BO_DEFAULT;
801
802         /* create only one bo */
803         surf->num_bos = num;
804         for (i = 0; i < num; i++) {
805                 if (bos[i] == NULL)
806                         goto bail1;
807
808                 surf->bos[i] = tbm_bo_ref(bos[i]);
809                 _tbm_bo_set_surface(bos[i], surf);
810         }
811
812         TBM_TRACE("tbm_surface(%p) width(%d) height(%d) format(%s) bo_num(%d)\n", surf,
813                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
814
815         LIST_INITHEAD(&surf->user_data_list);
816         LIST_INITHEAD(&surf->debug_data_list);
817
818         LIST_ADD(&surf->item_link, &mgr->surf_list);
819
820         _tbm_surface_mutex_unlock();
821
822         return surf;
823 bail1:
824         TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
825                                 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
826         for (i = 0; i < num; i++) {
827                 if (surf->bos[i]) {
828                         tbm_bo_unref(surf->bos[i]);
829                         surf->bos[i] = NULL;
830                 }
831         }
832
833         free(surf);
834         surf = NULL;
835
836         if (LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
837                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
838                 _deinit_surface_bufmgr();
839         }
840
841         _tbm_surface_mutex_unlock();
842
843         return NULL;
844 }
845
846 void
847 tbm_surface_internal_destroy(tbm_surface_h surface)
848 {
849         _tbm_surface_mutex_lock();
850
851         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
852
853         surface->refcnt--;
854
855         if (surface->refcnt > 0) {
856                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
857                 _tbm_surface_mutex_unlock();
858                 return;
859         }
860
861         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
862
863         if (surface->refcnt == 0)
864                 _tbm_surface_internal_destroy(surface);
865
866         _tbm_surface_mutex_unlock();
867 }
868
869 void
870 tbm_surface_internal_ref(tbm_surface_h surface)
871 {
872         _tbm_surface_mutex_lock();
873
874         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
875
876         surface->refcnt++;
877
878         TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
879
880         _tbm_surface_mutex_unlock();
881 }
882
883 void
884 tbm_surface_internal_unref(tbm_surface_h surface)
885 {
886         _tbm_surface_mutex_lock();
887
888         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
889
890         surface->refcnt--;
891
892         if (surface->refcnt > 0) {
893                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
894                 _tbm_surface_mutex_unlock();
895                 return;
896         }
897
898         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
899
900         if (surface->refcnt == 0)
901                 _tbm_surface_internal_destroy(surface);
902
903         _tbm_surface_mutex_unlock();
904 }
905
906 int
907 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
908 {
909         struct _tbm_surface *surf;
910         int num;
911
912         _tbm_surface_mutex_lock();
913
914         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
915
916         surf = (struct _tbm_surface *)surface;
917         num = surf->num_bos;
918
919         TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
920
921         _tbm_surface_mutex_unlock();
922
923         return num;
924 }
925
926 tbm_bo
927 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
928 {
929         struct _tbm_surface *surf;
930         tbm_bo bo;
931
932         _tbm_surface_mutex_lock();
933
934         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), NULL);
935         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
936
937         surf = (struct _tbm_surface *)surface;
938         bo = surf->bos[bo_idx];
939
940         TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
941
942         _tbm_surface_mutex_unlock();
943
944         return bo;
945 }
946
947 int
948 tbm_surface_internal_get_size(tbm_surface_h surface)
949 {
950         struct _tbm_surface *surf;
951         unsigned int size;
952
953         _tbm_surface_mutex_lock();
954
955         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
956
957         surf = (struct _tbm_surface *)surface;
958         size = surf->info.size;
959
960         TBM_TRACE("tbm_surface(%p) size(%d)\n", surface, size);
961
962         _tbm_surface_mutex_unlock();
963
964         return size;
965 }
966
967 int
968 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
969                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
970 {
971         struct _tbm_surface *surf;
972
973         _tbm_surface_mutex_lock();
974
975         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
976         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
977
978         surf = (struct _tbm_surface *)surface;
979
980         if (plane_idx >= surf->info.num_planes) {
981                 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
982                 _tbm_surface_mutex_unlock();
983                 return 0;
984         }
985
986         if (size)
987                 *size = surf->info.planes[plane_idx].size;
988
989         if (offset)
990                 *offset = surf->info.planes[plane_idx].offset;
991
992         if (pitch)
993                 *pitch = surf->info.planes[plane_idx].stride;
994
995         TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%d) offset(%d) pitch(%d)\n", surface, plane_idx,
996                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
997                                 surf->info.planes[plane_idx].stride);
998
999         _tbm_surface_mutex_unlock();
1000
1001         return 1;
1002 }
1003
1004 int
1005 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1006                               tbm_surface_info_s *info, int map)
1007 {
1008         struct _tbm_surface *surf;
1009         tbm_bo_handle bo_handles[4];
1010         int i, j;
1011
1012         _tbm_surface_mutex_lock();
1013
1014         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1015
1016         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1017
1018         surf = (struct _tbm_surface *)surface;
1019
1020         memset(info, 0x00, sizeof(tbm_surface_info_s));
1021         info->width = surf->info.width;
1022         info->height = surf->info.height;
1023         info->format = surf->info.format;
1024         info->bpp = surf->info.bpp;
1025         info->size = surf->info.size;
1026         info->num_planes = surf->info.num_planes;
1027
1028         if (map == 1) {
1029                 for (i = 0; i < surf->num_bos; i++) {
1030                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1031                         if (bo_handles[i].ptr == NULL) {
1032                                 for (j = 0; j < i; j++)
1033                                         tbm_bo_unmap(surf->bos[j]);
1034
1035                                 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1036                                 _tbm_surface_mutex_unlock();
1037                                 return 0;
1038                         }
1039                 }
1040         } else {
1041                 for (i = 0; i < surf->num_bos; i++)
1042                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1043         }
1044
1045         for (i = 0; i < surf->info.num_planes; i++) {
1046                 info->planes[i].size = surf->info.planes[i].size;
1047                 info->planes[i].offset = surf->info.planes[i].offset;
1048                 info->planes[i].stride = surf->info.planes[i].stride;
1049
1050                 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1051                         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1052                                               surf->info.planes[i].offset;
1053         }
1054
1055         TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1056
1057         _tbm_surface_mutex_unlock();
1058
1059         return 1;
1060 }
1061
1062 void
1063 tbm_surface_internal_unmap(tbm_surface_h surface)
1064 {
1065         struct _tbm_surface *surf;
1066         int i;
1067
1068         _tbm_surface_mutex_lock();
1069
1070         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1071
1072         surf = (struct _tbm_surface *)surface;
1073
1074         for (i = 0; i < surf->num_bos; i++)
1075                 tbm_bo_unmap(surf->bos[i]);
1076
1077         TBM_TRACE("tbm_surface(%p)\n", surface);
1078
1079         _tbm_surface_mutex_unlock();
1080 }
1081
1082 unsigned int
1083 tbm_surface_internal_get_width(tbm_surface_h surface)
1084 {
1085         struct _tbm_surface *surf;
1086         unsigned int width;
1087
1088         _tbm_surface_mutex_lock();
1089
1090         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1091
1092         surf = (struct _tbm_surface *)surface;
1093         width = surf->info.width;
1094
1095         TBM_TRACE("tbm_surface(%p) width(%d)\n", surface, width);
1096
1097         _tbm_surface_mutex_unlock();
1098
1099         return width;
1100 }
1101
1102 unsigned int
1103 tbm_surface_internal_get_height(tbm_surface_h surface)
1104 {
1105         struct _tbm_surface *surf;
1106         unsigned int height;
1107
1108         _tbm_surface_mutex_lock();
1109
1110         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1111
1112         surf = (struct _tbm_surface *)surface;
1113         height = surf->info.height;
1114
1115         TBM_TRACE("tbm_surface(%p) height(%d)\n", surface, height);
1116
1117         _tbm_surface_mutex_unlock();
1118
1119         return height;
1120
1121 }
1122
1123 tbm_format
1124 tbm_surface_internal_get_format(tbm_surface_h surface)
1125 {
1126         struct _tbm_surface *surf;
1127         tbm_format format;
1128
1129         _tbm_surface_mutex_lock();
1130
1131         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1132
1133         surf = (struct _tbm_surface *)surface;
1134         format = surf->info.format;
1135
1136         TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1137
1138         _tbm_surface_mutex_unlock();
1139
1140         return format;
1141 }
1142
1143 int
1144 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1145 {
1146         struct _tbm_surface *surf;
1147         int bo_idx;
1148
1149         _tbm_surface_mutex_lock();
1150
1151         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1152         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1153
1154         surf = (struct _tbm_surface *)surface;
1155         bo_idx = surf->planes_bo_idx[plane_idx];
1156
1157         TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1158
1159         _tbm_surface_mutex_unlock();
1160
1161         return bo_idx;
1162 }
1163
1164 int
1165 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1166                                    tbm_data_free data_free_func)
1167 {
1168         tbm_user_data *data;
1169
1170         _tbm_surface_mutex_lock();
1171
1172         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1173
1174         /* check if the data according to the key exist if so, return false. */
1175         data = user_data_lookup(&surface->user_data_list, key);
1176         if (data) {
1177                 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1178                 _tbm_surface_mutex_unlock();
1179                 return 0;
1180         }
1181
1182         data = user_data_create(key, data_free_func);
1183         if (!data) {
1184                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1185                 _tbm_surface_mutex_unlock();
1186                 return 0;
1187         }
1188
1189         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1190
1191         LIST_ADD(&data->item_link, &surface->user_data_list);
1192
1193         _tbm_surface_mutex_unlock();
1194
1195         return 1;
1196 }
1197
1198 int
1199 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1200                                    void *data)
1201 {
1202         tbm_user_data *old_data;
1203
1204         _tbm_surface_mutex_lock();
1205
1206         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1207
1208         if (LIST_IS_EMPTY(&surface->user_data_list)) {
1209                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1210                 _tbm_surface_mutex_unlock();
1211                 return 0;
1212         }
1213
1214         old_data = user_data_lookup(&surface->user_data_list, key);
1215         if (!old_data) {
1216                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1217                 _tbm_surface_mutex_unlock();
1218                 return 0;
1219         }
1220
1221         if (old_data->data && old_data->free_func)
1222                 old_data->free_func(old_data->data);
1223
1224         old_data->data = data;
1225
1226         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1227
1228         _tbm_surface_mutex_unlock();
1229
1230         return 1;
1231 }
1232
1233 int
1234 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1235                                    void **data)
1236 {
1237         tbm_user_data *old_data;
1238
1239         _tbm_surface_mutex_lock();
1240
1241         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1242
1243         if (!data || LIST_IS_EMPTY(&surface->user_data_list)) {
1244                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1245                 _tbm_surface_mutex_unlock();
1246                 return 0;
1247         }
1248
1249         old_data = user_data_lookup(&surface->user_data_list, key);
1250         if (!old_data) {
1251                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1252                 *data = NULL;
1253                 _tbm_surface_mutex_unlock();
1254                 return 0;
1255         }
1256
1257         *data = old_data->data;
1258
1259         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1260
1261         _tbm_surface_mutex_unlock();
1262
1263         return 1;
1264 }
1265
1266 int
1267 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1268                                       unsigned long key)
1269 {
1270         tbm_user_data *old_data = (void *)0;
1271
1272         _tbm_surface_mutex_lock();
1273
1274         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1275
1276         if (LIST_IS_EMPTY(&surface->user_data_list)) {
1277                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1278                 _tbm_surface_mutex_unlock();
1279                 return 0;
1280         }
1281
1282         old_data = user_data_lookup(&surface->user_data_list, key);
1283         if (!old_data) {
1284                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1285                 _tbm_surface_mutex_unlock();
1286                 return 0;
1287         }
1288
1289         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1290
1291         user_data_delete(old_data);
1292
1293         _tbm_surface_mutex_unlock();
1294
1295         return 1;
1296 }
1297
1298 /* LCOV_EXCL_START */
1299 unsigned int
1300 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1301 {
1302         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1303
1304         return surface->debug_pid;
1305 }
1306
1307 void
1308 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1309 {
1310         _tbm_surface_mutex_lock();
1311
1312         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1313
1314         surface->debug_pid = pid;
1315
1316         _tbm_surface_mutex_unlock();
1317 }
1318
1319 static tbm_surface_debug_data *
1320 _tbm_surface_internal_debug_data_create(char *key, char *value)
1321 {
1322         tbm_surface_debug_data *debug_data = NULL;
1323
1324         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1325         if (!debug_data)
1326                 return NULL;
1327
1328         if (key) debug_data->key = strdup(key);
1329         if (value) debug_data->value = strdup(value);
1330
1331         return debug_data;
1332 }
1333
1334 int
1335 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1336 {
1337         tbm_surface_debug_data *debug_data = NULL;
1338         tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1339         tbm_bufmgr bufmgr = surface->bufmgr;
1340
1341         _tbm_surface_mutex_lock();
1342
1343         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1344         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1345         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1346
1347         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1348                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1349                         if (!strcmp(old_data->key, key)) {
1350                                 if (value)
1351                                         old_data->value = strdup(value);
1352                                 else
1353                                         old_data->value = NULL;
1354                         }
1355                 }
1356         }
1357
1358         debug_data = _tbm_surface_internal_debug_data_create(key, value);
1359         if (!debug_data) {
1360                 TBM_TRACE("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1361                 _tbm_surface_mutex_unlock();
1362                 return 0;
1363         }
1364
1365         TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1366
1367         LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1368
1369         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1370                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1371                         if (!strcmp(old_data->key, key)) {
1372                                 _tbm_surface_mutex_unlock();
1373                                 return 1;
1374                         }
1375                 }
1376         }
1377
1378         debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1379         LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1380
1381         _tbm_surface_mutex_unlock();
1382
1383         return 1;
1384 }
1385
1386 char *
1387 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1388 {
1389         tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1390
1391         _tbm_surface_mutex_lock();
1392
1393         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1394
1395         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1396                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1397                         if (!strcmp(old_data->key, key)) {
1398                                 return old_data->value;
1399                         }
1400                 }
1401         }
1402
1403         _tbm_surface_mutex_unlock();
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, void *data2,
1439                 int size2, void *data3, int size3)
1440 {
1441         unsigned int *blocks;
1442         FILE *fp = fopen(file, "w+");
1443         TBM_RETURN_IF_FAIL(fp != NULL);
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,
1463                 int height)
1464 {
1465         FILE *fp = fopen(file, "wb");
1466         TBM_RETURN_IF_FAIL(fp != NULL);
1467         int depth = 8;
1468
1469         png_structp pPngStruct =
1470                 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1471         if (!pPngStruct) {
1472                 fclose(fp);
1473                 return;
1474         }
1475
1476         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1477         if (!pPngInfo) {
1478                 png_destroy_write_struct(&pPngStruct, NULL);
1479                 fclose(fp);
1480                 return;
1481         }
1482
1483         png_init_io(pPngStruct, fp);
1484         png_set_IHDR(pPngStruct,
1485                         pPngInfo,
1486                         width,
1487                         height,
1488                         depth,
1489                         PNG_COLOR_TYPE_RGBA,
1490                         PNG_INTERLACE_NONE,
1491                         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1492
1493         png_set_bgr(pPngStruct);
1494         png_write_info(pPngStruct, pPngInfo);
1495
1496         const int pixel_size = 4;       // RGBA
1497         png_bytep *row_pointers =
1498                         png_malloc(pPngStruct, height * sizeof(png_byte *));
1499
1500         unsigned int *blocks = (unsigned int *)data;
1501         int y = 0;
1502         int x = 0;
1503
1504         for (; y < height; ++y) {
1505                 png_bytep row =
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;
1514                 }
1515         }
1516
1517         png_write_image(pPngStruct, row_pointers);
1518         png_write_end(pPngStruct, pPngInfo);
1519
1520         for (y = 0; y < height; y++)
1521                 png_free(pPngStruct, row_pointers[y]);
1522         png_free(pPngStruct, row_pointers);
1523
1524         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1525
1526         fclose(fp);
1527 }
1528
1529 void
1530 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1531 {
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);
1536
1537         tbm_surface_dump_buf_info *buf_info = NULL;
1538         tbm_surface_dump_buf_info *tmp;
1539         tbm_bo bo = NULL;
1540         int i;
1541         int buffer_size;
1542         tbm_surface_h tbm_surface;
1543         tbm_surface_info_s info;
1544         tbm_surface_error_e err;
1545
1546         /* check running */
1547         if (g_dump_info) {
1548                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1549                 return;
1550         }
1551
1552         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1553         TBM_RETURN_IF_FAIL(g_dump_info);
1554
1555         LIST_INITHEAD(&g_dump_info->surface_list);
1556         g_dump_info->count = 0;
1557         g_dump_info->dump_max = count;
1558
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");
1563                 free(g_dump_info);
1564                 g_dump_info = NULL;
1565                 return;
1566         }
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);
1571                 free(g_dump_info);
1572                 g_dump_info = NULL;
1573                 return;
1574         }
1575         buffer_size = info.planes[0].stride * h;
1576         tbm_surface_unmap(tbm_surface);
1577         tbm_surface_destroy(tbm_surface);
1578
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);
1584                 if (bo == NULL) {
1585                         free(buf_info);
1586                         goto fail;
1587                 }
1588
1589                 buf_info->index = i;
1590                 buf_info->bo = bo;
1591                 buf_info->size = buffer_size;
1592
1593                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1594         }
1595
1596         g_dump_info->path = path;
1597         g_dump_info->link = &g_dump_info->surface_list;
1598
1599         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1600
1601         return;
1602 fail:
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);
1607                         free(buf_info);
1608                 }
1609         }
1610
1611         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1612
1613         free(g_dump_info);
1614         g_dump_info = NULL;
1615
1616         return;
1617 }
1618
1619 void
1620 tbm_surface_internal_dump_end(void)
1621 {
1622         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1623         tbm_bo_handle bo_handle;
1624
1625         if (!g_dump_info)
1626                 return;
1627
1628         /* make files */
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) {
1631                         char file[2048];
1632
1633                         if (buf_info->dirty) {
1634                                 void *ptr1 = NULL;
1635                                 void *ptr2 = NULL;
1636
1637                                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1638                                 if (bo_handle.ptr == NULL)
1639                                         continue;
1640
1641                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1642                                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1643
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);
1649                                         break;
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,
1656                                                                         ptr1,
1657                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1658                                                                         ptr2,
1659                                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1660                                         break;
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,
1666                                                                         ptr1,
1667                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1668                                                                         NULL, 0);
1669                                         break;
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,
1674                                                                         NULL, 0, NULL, 0);
1675                                         break;
1676                                 default:
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);
1679                                         return;
1680                                 }
1681
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)
1686                                         continue;
1687
1688                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1689                                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1690
1691                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1692                                                                 buf_info->shm_stride >> 2, buf_info->shm_h);
1693
1694                                 tbm_bo_unmap(buf_info->bo);
1695                         }
1696                 }
1697         }
1698
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);
1703                         free(buf_info);
1704                 }
1705         }
1706
1707         free(g_dump_info);
1708         g_dump_info = NULL;
1709
1710         TBM_LOG_I("Dump End..\n");
1711 }
1712
1713 void
1714 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1715 {
1716         TBM_RETURN_IF_FAIL(surface != NULL);
1717         TBM_RETURN_IF_FAIL(type != NULL);
1718
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;
1723         int ret;
1724         const char *postfix;
1725
1726         if (!g_dump_info)
1727                 return;
1728
1729         next_link = g_dump_info->link->next;
1730         TBM_RETURN_IF_FAIL(next_link != NULL);
1731
1732         if (next_link == &g_dump_info->surface_list) {
1733                 next_link = next_link->next;
1734                 TBM_RETURN_IF_FAIL(next_link != NULL);
1735         }
1736
1737         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1738         TBM_RETURN_IF_FAIL(buf_info != NULL);
1739
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);
1742
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);
1746                 return;
1747         }
1748
1749         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1750                 postfix = dump_postfix[0];
1751         else
1752                 postfix = dump_postfix[1];
1753
1754         /* make the file information */
1755         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1756
1757         /* dump */
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);
1761
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);
1769                 break;
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));
1780                 break;
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));
1789                 break;
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);
1796                 break;
1797         default:
1798                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1799                 tbm_bo_unmap(buf_info->bo);
1800                 return;
1801         }
1802
1803         tbm_bo_unmap(buf_info->bo);
1804
1805         tbm_surface_unmap(surface);
1806
1807         buf_info->dirty = 1;
1808         buf_info->dirty_shm = 0;
1809
1810         if (g_dump_info->count == 1000)
1811                 g_dump_info->count = 0;
1812
1813         g_dump_info->link = next_link;
1814
1815         TBM_LOG_I("Dump %s \n", buf_info->name);
1816 }
1817
1818 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int  stride, const char *type)
1819 {
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);
1825
1826         tbm_surface_dump_buf_info *buf_info;
1827         struct list_head *next_link;
1828         tbm_bo_handle bo_handle;
1829
1830         if (!g_dump_info)
1831                 return;
1832
1833         next_link = g_dump_info->link->next;
1834         TBM_RETURN_IF_FAIL(next_link != NULL);
1835
1836         if (next_link == &g_dump_info->surface_list) {
1837                 next_link = next_link->next;
1838                 TBM_RETURN_IF_FAIL(next_link != NULL);
1839         }
1840
1841         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1842         TBM_RETURN_IF_FAIL(buf_info != NULL);
1843
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);
1846                 return;
1847         }
1848
1849         /* dump */
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));
1854
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);
1859
1860         tbm_bo_unmap(buf_info->bo);
1861
1862         buf_info->dirty = 0;
1863         buf_info->dirty_shm = 1;
1864         buf_info->shm_stride = stride;
1865         buf_info->shm_h = h;
1866
1867         if (g_dump_info->count == 1000)
1868                 g_dump_info->count = 0;
1869
1870         g_dump_info->link = next_link;
1871
1872         TBM_LOG_I("Dump %s \n", buf_info->name);
1873 }
1874 /*LCOV_EXCL_STOP*/