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