tbm_surface_internal: clean up tbm_surface_internal_create_with_flags()
[platform/core/uifw/libtbm.git] / src / tbm_surface_internal.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include "config.h"
33
34 #include <stdio.h>
35 #include <time.h>
36 #include <sys/time.h>
37 #include "tbm_bufmgr.h"
38 #include "tbm_bufmgr_int.h"
39 #include "tbm_surface_internal.h"
40 #include "list.h"
41 #include <png.h>
42
43 static tbm_bufmgr g_surface_bufmgr;
44 static pthread_mutex_t tbm_surface_lock;
45 void _tbm_surface_mutex_unlock(void);
46
47 #define C(b, m)              (((b) >> (m)) & 0xFF)
48 #define B(c, s)              ((((unsigned int)(c)) & 0xff) << (s))
49 #define FOURCC(a, b, c, d)     (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
50 #define FOURCC_STR(id)      C(id, 0), C(id, 8), C(id, 16), C(id, 24)
51 #define FOURCC_ID(str)      FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3])
52
53 /* check condition */
54 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
55         if (!(cond)) {\
56                 TBM_LOG_E("'%s' failed.\n", #cond);\
57                 _tbm_surface_mutex_unlock();\
58                 return;\
59         } \
60 }
61
62 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
63         if (!(cond)) {\
64                 TBM_LOG_E("'%s' failed.\n", #cond);\
65                 _tbm_surface_mutex_unlock();\
66                 return val;\
67         } \
68 }
69
70 /* LCOV_EXCL_START */
71
72 static double
73 _tbm_surface_internal_get_time(void)
74 {
75         struct timespec tp;
76         unsigned int time;
77
78         clock_gettime(CLOCK_MONOTONIC, &tp);
79         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
80
81         return time / 1000.0;
82 }
83
84 static void
85 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
86 {
87         LIST_DEL(&debug_data->item_link);
88
89         if (debug_data->key) free(debug_data->key);
90         if (debug_data->value) free(debug_data->value);
91         free(debug_data);
92 }
93
94 char *
95 _tbm_surface_internal_format_to_str(tbm_format format)
96 {
97         switch (format) {
98         case TBM_FORMAT_C8:
99                 return "TBM_FORMAT_C8";
100         case TBM_FORMAT_RGB332:
101                 return "TBM_FORMAT_RGB332";
102         case TBM_FORMAT_BGR233:
103                 return "TBM_FORMAT_BGR233";
104         case TBM_FORMAT_XRGB4444:
105                 return "TBM_FORMAT_XRGB4444";
106         case TBM_FORMAT_XBGR4444:
107                 return "TBM_FORMAT_XBGR4444";
108         case TBM_FORMAT_RGBX4444:
109                 return "TBM_FORMAT_RGBX4444";
110         case TBM_FORMAT_BGRX4444:
111                 return "TBM_FORMAT_BGRX4444";
112         case TBM_FORMAT_ARGB4444:
113                 return "TBM_FORMAT_ARGB4444";
114         case TBM_FORMAT_ABGR4444:
115                 return "TBM_FORMAT_ABGR4444";
116         case TBM_FORMAT_RGBA4444:
117                 return "TBM_FORMAT_RGBA4444";
118         case TBM_FORMAT_BGRA4444:
119                 return "TBM_FORMAT_BGRA4444";
120         case TBM_FORMAT_XRGB1555:
121                 return "TBM_FORMAT_XRGB1555";
122         case TBM_FORMAT_XBGR1555:
123                 return "TBM_FORMAT_XBGR1555";
124         case TBM_FORMAT_RGBX5551:
125                 return "TBM_FORMAT_RGBX5551";
126         case TBM_FORMAT_BGRX5551:
127                 return "TBM_FORMAT_BGRX5551";
128         case TBM_FORMAT_ARGB1555:
129                 return "TBM_FORMAT_ARGB1555";
130         case TBM_FORMAT_ABGR1555:
131                 return "TBM_FORMAT_ABGR1555";
132         case TBM_FORMAT_RGBA5551:
133                 return "TBM_FORMAT_RGBA5551";
134         case TBM_FORMAT_BGRA5551:
135                 return "TBM_FORMAT_BGRA5551";
136         case TBM_FORMAT_RGB565:
137                 return "TBM_FORMAT_RGB565";
138         case TBM_FORMAT_BGR565:
139                 return "TBM_FORMAT_BGR565";
140         case TBM_FORMAT_RGB888:
141                 return "TBM_FORMAT_RGB888";
142         case TBM_FORMAT_BGR888:
143                 return "TBM_FORMAT_BGR888";
144         case TBM_FORMAT_XRGB8888:
145                 return "TBM_FORMAT_XRGB8888";
146         case TBM_FORMAT_XBGR8888:
147                 return "TBM_FORMAT_XBGR8888";
148         case TBM_FORMAT_RGBX8888:
149                 return "TBM_FORMAT_RGBX8888";
150         case TBM_FORMAT_BGRX8888:
151                 return "TBM_FORMAT_BGRX8888";
152         case TBM_FORMAT_ARGB8888:
153                 return "TBM_FORMAT_ARGB8888";
154         case TBM_FORMAT_ABGR8888:
155                 return "TBM_FORMAT_ABGR8888";
156         case TBM_FORMAT_RGBA8888:
157                 return "TBM_FORMAT_RGBA8888";
158         case TBM_FORMAT_BGRA8888:
159                 return "TBM_FORMAT_BGRA8888";
160         case TBM_FORMAT_XRGB2101010:
161                 return "TBM_FORMAT_XRGB2101010";
162         case TBM_FORMAT_XBGR2101010:
163                 return "TBM_FORMAT_XBGR2101010";
164         case TBM_FORMAT_RGBX1010102:
165                 return "TBM_FORMAT_RGBX1010102";
166         case TBM_FORMAT_BGRX1010102:
167                 return "TBM_FORMAT_BGRX1010102";
168         case TBM_FORMAT_ARGB2101010:
169                 return "TBM_FORMAT_ARGB2101010";
170         case TBM_FORMAT_ABGR2101010:
171                 return "TBM_FORMAT_ABGR2101010";
172         case TBM_FORMAT_RGBA1010102:
173                 return "TBM_FORMAT_RGBA1010102";
174         case TBM_FORMAT_BGRA1010102:
175                 return "TBM_FORMAT_BGRA1010102";
176         case TBM_FORMAT_YUYV:
177                 return "TBM_FORMAT_YUYV";
178         case TBM_FORMAT_YVYU:
179                 return "TBM_FORMAT_YVYU";
180         case TBM_FORMAT_UYVY:
181                 return "TBM_FORMAT_UYVY";
182         case TBM_FORMAT_VYUY:
183                 return "TBM_FORMAT_VYUY";
184         case TBM_FORMAT_AYUV:
185                 return "TBM_FORMAT_AYUV";
186         case TBM_FORMAT_NV12:
187                 return "TBM_FORMAT_NV12";
188         case TBM_FORMAT_NV21:
189                 return "TBM_FORMAT_NV21";
190         case TBM_FORMAT_NV16:
191                 return "TBM_FORMAT_NV16";
192         case TBM_FORMAT_NV61:
193                 return "TBM_FORMAT_NV61";
194         case TBM_FORMAT_YUV410:
195                 return "TBM_FORMAT_YUV410";
196         case TBM_FORMAT_YVU410:
197                 return "TBM_FORMAT_YVU410";
198         case TBM_FORMAT_YUV411:
199                 return "TBM_FORMAT_YUV411";
200         case TBM_FORMAT_YVU411:
201                 return "TBM_FORMAT_YVU411";
202         case TBM_FORMAT_YUV420:
203                 return "TBM_FORMAT_YUV420";
204         case TBM_FORMAT_YVU420:
205                 return "TBM_FORMAT_YVU420";
206         case TBM_FORMAT_YUV422:
207                 return "TBM_FORMAT_YUV422";
208         case TBM_FORMAT_YVU422:
209                 return "TBM_FORMAT_YVU422";
210         case TBM_FORMAT_YUV444:
211                 return "TBM_FORMAT_YUV444";
212         case TBM_FORMAT_YVU444:
213                 return "TBM_FORMAT_YVU444";
214         case TBM_FORMAT_NV12MT:
215                 return "TBM_FORMAT_NV12MT";
216         default:
217                 return "unknwon";
218         }
219 }
220 /* LCOV_EXCL_STOP */
221
222 static bool
223 _tbm_surface_mutex_init(void)
224 {
225         static bool tbm_surface_mutex_init = false;
226
227         if (tbm_surface_mutex_init)
228                 return true;
229
230         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
231                 TBM_LOG_E("fail: tbm_surface mutex init\n");
232                 return false;
233         }
234
235         tbm_surface_mutex_init = true;
236
237         return true;
238 }
239
240 void
241 _tbm_surface_mutex_lock(void)
242 {
243         if (!_tbm_surface_mutex_init())
244                 return;
245
246         pthread_mutex_lock(&tbm_surface_lock);
247 }
248
249 void
250 _tbm_surface_mutex_unlock(void)
251 {
252         pthread_mutex_unlock(&tbm_surface_lock);
253 }
254
255 static void
256 _init_surface_bufmgr(void)
257 {
258         g_surface_bufmgr = tbm_bufmgr_init(-1);
259 }
260
261 static void
262 _deinit_surface_bufmgr(void)
263 {
264         if (!g_surface_bufmgr)
265                 return;
266
267         tbm_bufmgr_deinit(g_surface_bufmgr);
268         g_surface_bufmgr = NULL;
269 }
270
271 static int
272 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
273                                        int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
274 {
275         TBM_RETURN_VAL_IF_FAIL(surface, 0);
276         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
277
278         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
279         struct _tbm_bufmgr *mgr = surf->bufmgr;
280         int ret = 0;
281
282         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
283         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
284         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
285         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
286
287         if (!mgr->backend->surface_get_plane_data)
288                 return 0;
289
290         ret = mgr->backend->surface_get_plane_data(surf->info.width,
291                         surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
292         if (!ret)
293                 return 0;
294
295         return 1;
296 }
297
298 static void
299 _tbm_surface_internal_destroy(tbm_surface_h surface)
300 {
301         int i;
302         tbm_bufmgr bufmgr = surface->bufmgr;
303         tbm_user_data *old_data = NULL, *tmp = NULL;
304         tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
305
306         /* destory the user_data_list */
307         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
308                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
309                         TBM_DBG("free user_data\n");
310                         user_data_delete(old_data);
311                 }
312         }
313
314         for (i = 0; i < surface->num_bos; i++) {
315                 surface->bos[i]->surface = NULL;
316
317                 tbm_bo_unref(surface->bos[i]);
318                 surface->bos[i] = NULL;
319         }
320
321         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
322                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
323                         _tbm_surface_internal_debug_data_delete(debug_old_data);
324         }
325
326         LIST_DEL(&surface->item_link);
327
328         free(surface);
329         surface = NULL;
330
331         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
332                 LIST_DELINIT(&bufmgr->surf_list);
333
334                 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
335                         LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
336                                 _tbm_surface_internal_debug_data_delete(debug_old_data);
337                         }
338                 }
339
340                 _deinit_surface_bufmgr();
341         }
342 }
343
344 int
345 tbm_surface_internal_is_valid(tbm_surface_h surface)
346 {
347         tbm_surface_h old_data = NULL;
348
349         if (surface == NULL || g_surface_bufmgr == NULL) {
350                 TBM_TRACE("error: tbm_surface(%p)\n", surface);
351                 return 0;
352         }
353
354         if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
355                 LIST_FOR_EACH_ENTRY(old_data, &g_surface_bufmgr->surf_list, item_link) {
356                         if (old_data == surface) {
357                                 TBM_TRACE("tbm_surface(%p)\n", surface);
358                                 return 1;
359                         }
360                 }
361         }
362         TBM_TRACE("error: tbm_surface(%p)\n", surface);
363         return 0;
364 }
365
366 int
367 tbm_surface_internal_query_supported_formats(uint32_t **formats,
368                 uint32_t *num)
369 {
370         struct _tbm_bufmgr *mgr;
371         int ret = 0;
372
373         _tbm_surface_mutex_lock();
374
375         if (!g_surface_bufmgr) {
376                 _init_surface_bufmgr();
377                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
378         }
379
380         mgr = g_surface_bufmgr;
381
382         if (!mgr->backend->surface_supported_format) {
383                 TBM_TRACE("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
384                 _tbm_surface_mutex_unlock();
385                 return 0;
386         }
387
388         ret = mgr->backend->surface_supported_format(formats, num);
389
390         TBM_TRACE("tbm_bufmgr(%p) format num(%d)\n", g_surface_bufmgr, *num);
391
392         _tbm_surface_mutex_unlock();
393
394         return ret;
395 }
396
397 int
398 tbm_surface_internal_get_num_planes(tbm_format format)
399 {
400         int num_planes = 0;
401
402         switch (format) {
403         case TBM_FORMAT_C8:
404         case TBM_FORMAT_RGB332:
405         case TBM_FORMAT_BGR233:
406         case TBM_FORMAT_XRGB4444:
407         case TBM_FORMAT_XBGR4444:
408         case TBM_FORMAT_RGBX4444:
409         case TBM_FORMAT_BGRX4444:
410         case TBM_FORMAT_ARGB4444:
411         case TBM_FORMAT_ABGR4444:
412         case TBM_FORMAT_RGBA4444:
413         case TBM_FORMAT_BGRA4444:
414         case TBM_FORMAT_XRGB1555:
415         case TBM_FORMAT_XBGR1555:
416         case TBM_FORMAT_RGBX5551:
417         case TBM_FORMAT_BGRX5551:
418         case TBM_FORMAT_ARGB1555:
419         case TBM_FORMAT_ABGR1555:
420         case TBM_FORMAT_RGBA5551:
421         case TBM_FORMAT_BGRA5551:
422         case TBM_FORMAT_RGB565:
423         case TBM_FORMAT_BGR565:
424         case TBM_FORMAT_RGB888:
425         case TBM_FORMAT_BGR888:
426         case TBM_FORMAT_XRGB8888:
427         case TBM_FORMAT_XBGR8888:
428         case TBM_FORMAT_RGBX8888:
429         case TBM_FORMAT_BGRX8888:
430         case TBM_FORMAT_ARGB8888:
431         case TBM_FORMAT_ABGR8888:
432         case TBM_FORMAT_RGBA8888:
433         case TBM_FORMAT_BGRA8888:
434         case TBM_FORMAT_XRGB2101010:
435         case TBM_FORMAT_XBGR2101010:
436         case TBM_FORMAT_RGBX1010102:
437         case TBM_FORMAT_BGRX1010102:
438         case TBM_FORMAT_ARGB2101010:
439         case TBM_FORMAT_ABGR2101010:
440         case TBM_FORMAT_RGBA1010102:
441         case TBM_FORMAT_BGRA1010102:
442         case TBM_FORMAT_YUYV:
443         case TBM_FORMAT_YVYU:
444         case TBM_FORMAT_UYVY:
445         case TBM_FORMAT_VYUY:
446         case TBM_FORMAT_AYUV:
447                 num_planes = 1;
448                 break;
449         case TBM_FORMAT_NV12:
450         case TBM_FORMAT_NV12MT:
451         case TBM_FORMAT_NV21:
452         case TBM_FORMAT_NV16:
453         case TBM_FORMAT_NV61:
454                 num_planes = 2;
455                 break;
456         case TBM_FORMAT_YUV410:
457         case TBM_FORMAT_YVU410:
458         case TBM_FORMAT_YUV411:
459         case TBM_FORMAT_YVU411:
460         case TBM_FORMAT_YUV420:
461         case TBM_FORMAT_YVU420:
462         case TBM_FORMAT_YUV422:
463         case TBM_FORMAT_YVU422:
464         case TBM_FORMAT_YUV444:
465         case TBM_FORMAT_YVU444:
466                 num_planes = 3;
467                 break;
468
469         default:
470                 break;
471         }
472
473         TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
474
475         return num_planes;
476 }
477
478 int
479 tbm_surface_internal_get_bpp(tbm_format format)
480 {
481
482         int bpp = 0;
483
484         switch (format) {
485         case TBM_FORMAT_C8:
486         case TBM_FORMAT_RGB332:
487         case TBM_FORMAT_BGR233:
488                 bpp = 8;
489                 break;
490         case TBM_FORMAT_XRGB4444:
491         case TBM_FORMAT_XBGR4444:
492         case TBM_FORMAT_RGBX4444:
493         case TBM_FORMAT_BGRX4444:
494         case TBM_FORMAT_ARGB4444:
495         case TBM_FORMAT_ABGR4444:
496         case TBM_FORMAT_RGBA4444:
497         case TBM_FORMAT_BGRA4444:
498         case TBM_FORMAT_XRGB1555:
499         case TBM_FORMAT_XBGR1555:
500         case TBM_FORMAT_RGBX5551:
501         case TBM_FORMAT_BGRX5551:
502         case TBM_FORMAT_ARGB1555:
503         case TBM_FORMAT_ABGR1555:
504         case TBM_FORMAT_RGBA5551:
505         case TBM_FORMAT_BGRA5551:
506         case TBM_FORMAT_RGB565:
507         case TBM_FORMAT_BGR565:
508                 bpp = 16;
509                 break;
510         case TBM_FORMAT_RGB888:
511         case TBM_FORMAT_BGR888:
512                 bpp = 24;
513                 break;
514         case TBM_FORMAT_XRGB8888:
515         case TBM_FORMAT_XBGR8888:
516         case TBM_FORMAT_RGBX8888:
517         case TBM_FORMAT_BGRX8888:
518         case TBM_FORMAT_ARGB8888:
519         case TBM_FORMAT_ABGR8888:
520         case TBM_FORMAT_RGBA8888:
521         case TBM_FORMAT_BGRA8888:
522         case TBM_FORMAT_XRGB2101010:
523         case TBM_FORMAT_XBGR2101010:
524         case TBM_FORMAT_RGBX1010102:
525         case TBM_FORMAT_BGRX1010102:
526         case TBM_FORMAT_ARGB2101010:
527         case TBM_FORMAT_ABGR2101010:
528         case TBM_FORMAT_RGBA1010102:
529         case TBM_FORMAT_BGRA1010102:
530         case TBM_FORMAT_YUYV:
531         case TBM_FORMAT_YVYU:
532         case TBM_FORMAT_UYVY:
533         case TBM_FORMAT_VYUY:
534         case TBM_FORMAT_AYUV:
535                 bpp = 32;
536                 break;
537         case TBM_FORMAT_NV12:
538         case TBM_FORMAT_NV12MT:
539         case TBM_FORMAT_NV21:
540                 bpp = 12;
541                 break;
542         case TBM_FORMAT_NV16:
543         case TBM_FORMAT_NV61:
544                 bpp = 16;
545                 break;
546         case TBM_FORMAT_YUV410:
547         case TBM_FORMAT_YVU410:
548                 bpp = 9;
549                 break;
550         case TBM_FORMAT_YUV411:
551         case TBM_FORMAT_YVU411:
552         case TBM_FORMAT_YUV420:
553         case TBM_FORMAT_YVU420:
554                 bpp = 12;
555                 break;
556         case TBM_FORMAT_YUV422:
557         case TBM_FORMAT_YVU422:
558                 bpp = 16;
559                 break;
560         case TBM_FORMAT_YUV444:
561         case TBM_FORMAT_YVU444:
562                 bpp = 24;
563                 break;
564         default:
565                 break;
566         }
567
568         TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
569
570         return bpp;
571 }
572
573 tbm_surface_h
574 tbm_surface_internal_create_with_flags(int width, int height,
575                                        int format, int flags)
576 {
577         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
578         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
579
580         struct _tbm_bufmgr *mgr;
581         struct _tbm_surface *surf = NULL;
582         uint32_t size = 0;
583         uint32_t offset = 0;
584         uint32_t stride = 0;
585         uint32_t bo_size = 0;
586         int bo_idx;
587         int i, j;
588         bool bufmgr_initialized = false;
589
590         _tbm_surface_mutex_lock();
591
592         if (!g_surface_bufmgr) {
593                 _init_surface_bufmgr();
594                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
595                 bufmgr_initialized = true;
596         }
597
598         mgr = g_surface_bufmgr;
599         if (!TBM_BUFMGR_IS_VALID(mgr)) {
600                 TBM_LOG_E("The bufmgr is invalid\n");
601                 goto check_valid_fail;
602         }
603
604         surf = calloc(1, sizeof(struct _tbm_surface));
605         if (!surf) {
606                 TBM_LOG_E("fail to alloc surf\n");
607                 goto alloc_surf_fail;
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                 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
621                                                 &offset, &stride, &bo_idx)) {
622                         TBM_LOG_E("fail to query plane data\n");
623                         goto query_plane_data_fail;
624                 }
625
626                 surf->info.planes[i].size = size;
627                 surf->info.planes[i].offset = offset;
628                 surf->info.planes[i].stride = stride;
629                 surf->planes_bo_idx[i] = bo_idx;
630         }
631
632         surf->num_bos = 1;
633
634         for (i = 0; i < surf->info.num_planes; i++) {
635                 surf->info.size += surf->info.planes[i].size;
636
637                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
638                         surf->num_bos = surf->planes_bo_idx[i] + 1;
639         }
640
641         surf->flags = flags;
642
643         for (i = 0; i < surf->num_bos; i++) {
644                 bo_size = 0;
645                 for (j = 0; j < surf->info.num_planes; j++) {
646                         if (surf->planes_bo_idx[j] == i)
647                                 bo_size += surf->info.planes[j].size;
648                 }
649
650                 if (mgr->backend->surface_bo_alloc) {
651                         /* LCOV_EXCL_START */
652                         tbm_bo bo = NULL;
653                         void *bo_priv = NULL;
654
655                         bo = calloc(1, sizeof(struct _tbm_bo));
656                         if (!bo) {
657                                 TBM_LOG_E("fail to alloc bo struct\n");
658                                 goto alloc_bo_fail;
659                         }
660
661                         bo->bufmgr = surf->bufmgr;
662
663                         pthread_mutex_lock(&surf->bufmgr->lock);
664
665                         bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
666                         if (!bo_priv) {
667                                 TBM_LOG_E("fail to alloc bo priv\n");
668                                 free(bo);
669                                 pthread_mutex_unlock(&surf->bufmgr->lock);
670                                 goto alloc_bo_fail;
671                         }
672
673                         bo->ref_cnt = 1;
674                         bo->flags = flags;
675                         bo->priv = bo_priv;
676
677                         LIST_INITHEAD(&bo->user_data_list);
678
679                         LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
680
681                         pthread_mutex_unlock(&surf->bufmgr->lock);
682
683                         surf->bos[i] = bo;
684                         /* LCOV_EXCL_STOP */
685                 } else {
686                         surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
687                         if (!surf->bos[i]) {
688                                 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
689                                 goto alloc_bo_fail;
690                         }
691                 }
692
693                 _tbm_bo_set_surface(surf->bos[i], surf);
694         }
695
696         TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
697                         _tbm_surface_internal_format_to_str(format), flags, surf);
698
699         LIST_INITHEAD(&surf->user_data_list);
700         LIST_INITHEAD(&surf->debug_data_list);
701
702         LIST_ADD(&surf->item_link, &mgr->surf_list);
703
704         _tbm_surface_mutex_unlock();
705
706         return surf;
707
708 alloc_bo_fail:
709         for (j = 0; j < i; j++) {
710                 if (surf->bos[j])
711                         tbm_bo_unref(surf->bos[j]);
712         }
713 query_plane_data_fail:
714         free(surf);
715 alloc_surf_fail:
716 check_valid_fail:
717         if (bufmgr_initialized) {
718                 LIST_DELINIT(&mgr->surf_list);
719                 _deinit_surface_bufmgr();
720         }
721         _tbm_surface_mutex_unlock();
722         TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
723                         width, height,
724                         _tbm_surface_internal_format_to_str(format), flags);
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                         _tbm_surface_mutex_unlock();
1026                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1027                         _tbm_surface_mutex_lock();
1028                         if (bo_handles[i].ptr == NULL) {
1029                                 for (j = 0; j < i; j++)
1030                                         tbm_bo_unmap(surf->bos[j]);
1031
1032                                 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1033                                 _tbm_surface_mutex_unlock();
1034                                 return 0;
1035                         }
1036                 }
1037         } else {
1038                 for (i = 0; i < surf->num_bos; i++)
1039                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1040         }
1041
1042         for (i = 0; i < surf->info.num_planes; i++) {
1043                 info->planes[i].size = surf->info.planes[i].size;
1044                 info->planes[i].offset = surf->info.planes[i].offset;
1045                 info->planes[i].stride = surf->info.planes[i].stride;
1046
1047                 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1048                         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1049                                               surf->info.planes[i].offset;
1050         }
1051
1052         TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1053
1054         _tbm_surface_mutex_unlock();
1055
1056         return 1;
1057 }
1058
1059 void
1060 tbm_surface_internal_unmap(tbm_surface_h surface)
1061 {
1062         struct _tbm_surface *surf;
1063         int i;
1064
1065         _tbm_surface_mutex_lock();
1066
1067         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1068
1069         surf = (struct _tbm_surface *)surface;
1070
1071         for (i = 0; i < surf->num_bos; i++)
1072                 tbm_bo_unmap(surf->bos[i]);
1073
1074         TBM_TRACE("tbm_surface(%p)\n", surface);
1075
1076         _tbm_surface_mutex_unlock();
1077 }
1078
1079 unsigned int
1080 tbm_surface_internal_get_width(tbm_surface_h surface)
1081 {
1082         struct _tbm_surface *surf;
1083         unsigned int width;
1084
1085         _tbm_surface_mutex_lock();
1086
1087         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1088
1089         surf = (struct _tbm_surface *)surface;
1090         width = surf->info.width;
1091
1092         TBM_TRACE("tbm_surface(%p) width(%d)\n", surface, width);
1093
1094         _tbm_surface_mutex_unlock();
1095
1096         return width;
1097 }
1098
1099 unsigned int
1100 tbm_surface_internal_get_height(tbm_surface_h surface)
1101 {
1102         struct _tbm_surface *surf;
1103         unsigned int height;
1104
1105         _tbm_surface_mutex_lock();
1106
1107         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1108
1109         surf = (struct _tbm_surface *)surface;
1110         height = surf->info.height;
1111
1112         TBM_TRACE("tbm_surface(%p) height(%d)\n", surface, height);
1113
1114         _tbm_surface_mutex_unlock();
1115
1116         return height;
1117
1118 }
1119
1120 tbm_format
1121 tbm_surface_internal_get_format(tbm_surface_h surface)
1122 {
1123         struct _tbm_surface *surf;
1124         tbm_format format;
1125
1126         _tbm_surface_mutex_lock();
1127
1128         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1129
1130         surf = (struct _tbm_surface *)surface;
1131         format = surf->info.format;
1132
1133         TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1134
1135         _tbm_surface_mutex_unlock();
1136
1137         return format;
1138 }
1139
1140 int
1141 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1142 {
1143         struct _tbm_surface *surf;
1144         int bo_idx;
1145
1146         _tbm_surface_mutex_lock();
1147
1148         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1149         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1150
1151         surf = (struct _tbm_surface *)surface;
1152         bo_idx = surf->planes_bo_idx[plane_idx];
1153
1154         TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1155
1156         _tbm_surface_mutex_unlock();
1157
1158         return bo_idx;
1159 }
1160
1161 int
1162 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1163                                    tbm_data_free data_free_func)
1164 {
1165         tbm_user_data *data;
1166
1167         _tbm_surface_mutex_lock();
1168
1169         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1170
1171         /* check if the data according to the key exist if so, return false. */
1172         data = user_data_lookup(&surface->user_data_list, key);
1173         if (data) {
1174                 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1175                 _tbm_surface_mutex_unlock();
1176                 return 0;
1177         }
1178
1179         data = user_data_create(key, data_free_func);
1180         if (!data) {
1181                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1182                 _tbm_surface_mutex_unlock();
1183                 return 0;
1184         }
1185
1186         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1187
1188         LIST_ADD(&data->item_link, &surface->user_data_list);
1189
1190         _tbm_surface_mutex_unlock();
1191
1192         return 1;
1193 }
1194
1195 int
1196 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1197                                    void *data)
1198 {
1199         tbm_user_data *old_data;
1200
1201         _tbm_surface_mutex_lock();
1202
1203         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1204
1205         if (LIST_IS_EMPTY(&surface->user_data_list)) {
1206                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1207                 _tbm_surface_mutex_unlock();
1208                 return 0;
1209         }
1210
1211         old_data = user_data_lookup(&surface->user_data_list, key);
1212         if (!old_data) {
1213                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1214                 _tbm_surface_mutex_unlock();
1215                 return 0;
1216         }
1217
1218         if (old_data->data && old_data->free_func)
1219                 old_data->free_func(old_data->data);
1220
1221         old_data->data = data;
1222
1223         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1224
1225         _tbm_surface_mutex_unlock();
1226
1227         return 1;
1228 }
1229
1230 int
1231 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1232                                    void **data)
1233 {
1234         tbm_user_data *old_data;
1235
1236         _tbm_surface_mutex_lock();
1237
1238         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1239
1240         if (!data || LIST_IS_EMPTY(&surface->user_data_list)) {
1241                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1242                 _tbm_surface_mutex_unlock();
1243                 return 0;
1244         }
1245
1246         old_data = user_data_lookup(&surface->user_data_list, key);
1247         if (!old_data) {
1248                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1249                 *data = NULL;
1250                 _tbm_surface_mutex_unlock();
1251                 return 0;
1252         }
1253
1254         *data = old_data->data;
1255
1256         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1257
1258         _tbm_surface_mutex_unlock();
1259
1260         return 1;
1261 }
1262
1263 int
1264 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1265                                       unsigned long key)
1266 {
1267         tbm_user_data *old_data = (void *)0;
1268
1269         _tbm_surface_mutex_lock();
1270
1271         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1272
1273         if (LIST_IS_EMPTY(&surface->user_data_list)) {
1274                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1275                 _tbm_surface_mutex_unlock();
1276                 return 0;
1277         }
1278
1279         old_data = user_data_lookup(&surface->user_data_list, key);
1280         if (!old_data) {
1281                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1282                 _tbm_surface_mutex_unlock();
1283                 return 0;
1284         }
1285
1286         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1287
1288         user_data_delete(old_data);
1289
1290         _tbm_surface_mutex_unlock();
1291
1292         return 1;
1293 }
1294
1295 /* LCOV_EXCL_START */
1296 unsigned int
1297 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1298 {
1299         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1300
1301         return surface->debug_pid;
1302 }
1303
1304 void
1305 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1306 {
1307         _tbm_surface_mutex_lock();
1308
1309         TBM_SURFACE_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1310
1311         surface->debug_pid = pid;
1312
1313         _tbm_surface_mutex_unlock();
1314 }
1315
1316 static tbm_surface_debug_data *
1317 _tbm_surface_internal_debug_data_create(char *key, char *value)
1318 {
1319         tbm_surface_debug_data *debug_data = NULL;
1320
1321         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1322         if (!debug_data)
1323                 return NULL;
1324
1325         if (key) debug_data->key = strdup(key);
1326         if (value) debug_data->value = strdup(value);
1327
1328         return debug_data;
1329 }
1330
1331 int
1332 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1333 {
1334         tbm_surface_debug_data *debug_data = NULL;
1335         tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1336         tbm_bufmgr bufmgr = NULL;
1337
1338         _tbm_surface_mutex_lock();
1339
1340         TBM_SURFACE_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1341         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1342
1343         bufmgr = surface->bufmgr;
1344
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                                 _tbm_surface_mutex_unlock();
1399                                 return old_data->value;
1400                         }
1401                 }
1402         }
1403
1404         _tbm_surface_mutex_unlock();
1405
1406         return NULL;
1407 }
1408
1409 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1410 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1411
1412 struct _tbm_surface_dump_buf_info {
1413         int index;
1414         tbm_bo bo;
1415         int size;
1416         int dirty;
1417         int dirty_shm;
1418         int shm_stride;
1419         int shm_h;
1420         char name[1024];
1421
1422         tbm_surface_info_s info;
1423
1424         struct list_head link;
1425 };
1426
1427 struct _tbm_surface_dump_info {
1428         char *path;  // copy???
1429         int dump_max;
1430         int count;
1431         struct list_head *link;
1432         struct list_head surface_list; /* link of surface */
1433 };
1434
1435 static tbm_surface_dump_info *g_dump_info = NULL;
1436 static const char *dump_postfix[2] = {"png", "yuv"};
1437
1438 static void
1439 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1, void *data2,
1440                 int size2, void *data3, int size3)
1441 {
1442         unsigned int *blocks;
1443         FILE *fp = fopen(file, "w+");
1444         TBM_RETURN_IF_FAIL(fp != NULL);
1445
1446         blocks = (unsigned int *)data1;
1447         fwrite(blocks, 1, size1, fp);
1448
1449         if (size2 > 0) {
1450                 blocks = (unsigned int *)data2;
1451                 fwrite(blocks, 1, size2, fp);
1452         }
1453
1454         if (size3 > 0) {
1455                 blocks = (unsigned int *)data3;
1456                 fwrite(blocks, 1, size3, fp);
1457         }
1458
1459         fclose(fp);
1460 }
1461
1462 static void
1463 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width,
1464                 int height)
1465 {
1466         FILE *fp = fopen(file, "wb");
1467         TBM_RETURN_IF_FAIL(fp != NULL);
1468         int depth = 8;
1469
1470         png_structp pPngStruct =
1471                 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1472         if (!pPngStruct) {
1473                 fclose(fp);
1474                 return;
1475         }
1476
1477         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1478         if (!pPngInfo) {
1479                 png_destroy_write_struct(&pPngStruct, NULL);
1480                 fclose(fp);
1481                 return;
1482         }
1483
1484         png_init_io(pPngStruct, fp);
1485         png_set_IHDR(pPngStruct,
1486                         pPngInfo,
1487                         width,
1488                         height,
1489                         depth,
1490                         PNG_COLOR_TYPE_RGBA,
1491                         PNG_INTERLACE_NONE,
1492                         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1493
1494         png_set_bgr(pPngStruct);
1495         png_write_info(pPngStruct, pPngInfo);
1496
1497         const int pixel_size = 4;       // RGBA
1498         png_bytep *row_pointers =
1499                         png_malloc(pPngStruct, height * sizeof(png_byte *));
1500
1501         unsigned int *blocks = (unsigned int *)data;
1502         int y = 0;
1503         int x = 0;
1504
1505         for (; y < height; ++y) {
1506                 png_bytep row =
1507                         png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1508                 row_pointers[y] = (png_bytep)row;
1509                 for (x = 0; x < width; ++x) {
1510                         unsigned int curBlock = blocks[y * width + x];
1511                         row[x * pixel_size] = (curBlock & 0xFF);
1512                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1513                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1514                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1515                 }
1516         }
1517
1518         png_write_image(pPngStruct, row_pointers);
1519         png_write_end(pPngStruct, pPngInfo);
1520
1521         for (y = 0; y < height; y++)
1522                 png_free(pPngStruct, row_pointers[y]);
1523         png_free(pPngStruct, row_pointers);
1524
1525         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1526
1527         fclose(fp);
1528 }
1529
1530 void
1531 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1532 {
1533         TBM_RETURN_IF_FAIL(path != NULL);
1534         TBM_RETURN_IF_FAIL(w > 0);
1535         TBM_RETURN_IF_FAIL(h > 0);
1536         TBM_RETURN_IF_FAIL(count > 0);
1537
1538         tbm_surface_dump_buf_info *buf_info = NULL;
1539         tbm_surface_dump_buf_info *tmp;
1540         tbm_bo bo = NULL;
1541         int i;
1542         int buffer_size;
1543         tbm_surface_h tbm_surface;
1544         tbm_surface_info_s info;
1545         tbm_surface_error_e err;
1546
1547         /* check running */
1548         if (g_dump_info) {
1549                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1550                 return;
1551         }
1552
1553         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1554         TBM_RETURN_IF_FAIL(g_dump_info);
1555
1556         LIST_INITHEAD(&g_dump_info->surface_list);
1557         g_dump_info->count = 0;
1558         g_dump_info->dump_max = count;
1559
1560         /* get buffer size */
1561         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1562         if (tbm_surface == NULL) {
1563                 TBM_LOG_E("tbm_surface_create fail\n");
1564                 free(g_dump_info);
1565                 g_dump_info = NULL;
1566                 return;
1567         }
1568         err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
1569         if (err != TBM_SURFACE_ERROR_NONE) {
1570                 TBM_LOG_E("tbm_surface_map fail\n");
1571                 tbm_surface_destroy(tbm_surface);
1572                 free(g_dump_info);
1573                 g_dump_info = NULL;
1574                 return;
1575         }
1576         buffer_size = info.planes[0].stride * h;
1577         tbm_surface_unmap(tbm_surface);
1578         tbm_surface_destroy(tbm_surface);
1579
1580         /* create dump lists */
1581         for (i = 0; i < count; i++)     {
1582                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1583                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1584                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1585                 if (bo == NULL) {
1586                         free(buf_info);
1587                         goto fail;
1588                 }
1589
1590                 buf_info->index = i;
1591                 buf_info->bo = bo;
1592                 buf_info->size = buffer_size;
1593
1594                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1595         }
1596
1597         g_dump_info->path = path;
1598         g_dump_info->link = &g_dump_info->surface_list;
1599
1600         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1601
1602         return;
1603 fail:
1604         /* free resources */
1605         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1606                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1607                         tbm_bo_unref(buf_info->bo);
1608                         free(buf_info);
1609                 }
1610         }
1611
1612         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1613
1614         free(g_dump_info);
1615         g_dump_info = NULL;
1616
1617         return;
1618 }
1619
1620 void
1621 tbm_surface_internal_dump_end(void)
1622 {
1623         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1624         tbm_bo_handle bo_handle;
1625
1626         if (!g_dump_info)
1627                 return;
1628
1629         /* make files */
1630         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1631                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1632                         char file[2048];
1633
1634                         if (buf_info->dirty) {
1635                                 void *ptr1 = NULL;
1636                                 void *ptr2 = NULL;
1637
1638                                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1639                                 if (bo_handle.ptr == NULL)
1640                                         continue;
1641
1642                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1643                                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1644
1645                                 switch (buf_info->info.format) {
1646                                 case TBM_FORMAT_ARGB8888:
1647                                 case TBM_FORMAT_XRGB8888:
1648                                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1649                                                                         buf_info->info.planes[0].stride >> 2, buf_info->info.height);
1650                                         break;
1651                                 case TBM_FORMAT_YVU420:
1652                                 case TBM_FORMAT_YUV420:
1653                                         ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1654                                         ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1655                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1656                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1657                                                                         ptr1,
1658                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1659                                                                         ptr2,
1660                                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1661                                         break;
1662                                 case TBM_FORMAT_NV12:
1663                                 case TBM_FORMAT_NV21:
1664                                         ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1665                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1666                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1667                                                                         ptr1,
1668                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1669                                                                         NULL, 0);
1670                                         break;
1671                                 case TBM_FORMAT_YUYV:
1672                                 case TBM_FORMAT_UYVY:
1673                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1674                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1675                                                                         NULL, 0, NULL, 0);
1676                                         break;
1677                                 default:
1678                                         TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1679                                         tbm_bo_unmap(buf_info->bo);
1680                                         return;
1681                                 }
1682
1683                                 tbm_bo_unmap(buf_info->bo);
1684                         } else if (buf_info->dirty_shm) {
1685                                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1686                                 if (bo_handle.ptr == NULL)
1687                                         continue;
1688
1689                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1690                                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1691
1692                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1693                                                                 buf_info->shm_stride >> 2, buf_info->shm_h);
1694
1695                                 tbm_bo_unmap(buf_info->bo);
1696                         }
1697                 }
1698         }
1699
1700         /* free resources */
1701         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1702                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1703                         tbm_bo_unref(buf_info->bo);
1704                         free(buf_info);
1705                 }
1706         }
1707
1708         free(g_dump_info);
1709         g_dump_info = NULL;
1710
1711         TBM_LOG_I("Dump End..\n");
1712 }
1713
1714 void
1715 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1716 {
1717         TBM_RETURN_IF_FAIL(surface != NULL);
1718         TBM_RETURN_IF_FAIL(type != NULL);
1719
1720         tbm_surface_dump_buf_info *buf_info;
1721         tbm_surface_info_s info;
1722         struct list_head *next_link;
1723         tbm_bo_handle bo_handle;
1724         int ret;
1725         const char *postfix;
1726
1727         if (!g_dump_info)
1728                 return;
1729
1730         next_link = g_dump_info->link->next;
1731         TBM_RETURN_IF_FAIL(next_link != NULL);
1732
1733         if (next_link == &g_dump_info->surface_list) {
1734                 next_link = next_link->next;
1735                 TBM_RETURN_IF_FAIL(next_link != NULL);
1736         }
1737
1738         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1739         TBM_RETURN_IF_FAIL(buf_info != NULL);
1740
1741         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1742         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1743
1744         if (info.size > buf_info->size) {
1745                 TBM_LOG_W("Dump skip. surface over created buffer size(%d, %d)\n", info.size, buf_info->size);
1746                 tbm_surface_unmap(surface);
1747                 return;
1748         }
1749
1750         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1751                 postfix = dump_postfix[0];
1752         else
1753                 postfix = dump_postfix[1];
1754
1755         /* make the file information */
1756         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1757
1758         /* dump */
1759         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1760         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1761         memset(bo_handle.ptr, 0x00, buf_info->size);
1762
1763         switch (info.format) {
1764         case TBM_FORMAT_ARGB8888:
1765         case TBM_FORMAT_XRGB8888:
1766                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d_%p-%s.%s",
1767                                  _tbm_surface_internal_get_time(),
1768                                  g_dump_info->count++, surface, type, postfix);
1769                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1770                 break;
1771         case TBM_FORMAT_YVU420:
1772         case TBM_FORMAT_YUV420:
1773                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1774                                  _tbm_surface_internal_get_time(),
1775                                  g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1776                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1777                 bo_handle.ptr += info.planes[0].stride * info.height;
1778                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1779                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1780                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1781                 break;
1782         case TBM_FORMAT_NV12:
1783         case TBM_FORMAT_NV21:
1784                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1785                                  _tbm_surface_internal_get_time(),
1786                                  g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1787                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1788                 bo_handle.ptr += info.planes[0].stride * info.height;
1789                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1790                 break;
1791         case TBM_FORMAT_YUYV:
1792         case TBM_FORMAT_UYVY:
1793                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1794                                  _tbm_surface_internal_get_time(),
1795                                  g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1796                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1797                 break;
1798         default:
1799                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1800                 tbm_bo_unmap(buf_info->bo);
1801                 return;
1802         }
1803
1804         tbm_bo_unmap(buf_info->bo);
1805
1806         tbm_surface_unmap(surface);
1807
1808         buf_info->dirty = 1;
1809         buf_info->dirty_shm = 0;
1810
1811         if (g_dump_info->count == 1000)
1812                 g_dump_info->count = 0;
1813
1814         g_dump_info->link = next_link;
1815
1816         TBM_LOG_I("Dump %s \n", buf_info->name);
1817 }
1818
1819 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int  stride, const char *type)
1820 {
1821         TBM_RETURN_IF_FAIL(ptr != NULL);
1822         TBM_RETURN_IF_FAIL(w > 0);
1823         TBM_RETURN_IF_FAIL(h > 0);
1824         TBM_RETURN_IF_FAIL(stride > 0);
1825         TBM_RETURN_IF_FAIL(type != NULL);
1826
1827         tbm_surface_dump_buf_info *buf_info;
1828         struct list_head *next_link;
1829         tbm_bo_handle bo_handle;
1830
1831         if (!g_dump_info)
1832                 return;
1833
1834         next_link = g_dump_info->link->next;
1835         TBM_RETURN_IF_FAIL(next_link != NULL);
1836
1837         if (next_link == &g_dump_info->surface_list) {
1838                 next_link = next_link->next;
1839                 TBM_RETURN_IF_FAIL(next_link != NULL);
1840         }
1841
1842         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1843         TBM_RETURN_IF_FAIL(buf_info != NULL);
1844
1845         if (stride * h > buf_info->size) {
1846                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n", stride * h, buf_info->size);
1847                 return;
1848         }
1849
1850         /* dump */
1851         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1852         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1853         memset(bo_handle.ptr, 0x00, buf_info->size);
1854         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1855
1856         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1857                          _tbm_surface_internal_get_time(),
1858                          g_dump_info->count++, type, dump_postfix[0]);
1859         memcpy(bo_handle.ptr, ptr, stride * h);
1860
1861         tbm_bo_unmap(buf_info->bo);
1862
1863         buf_info->dirty = 0;
1864         buf_info->dirty_shm = 1;
1865         buf_info->shm_stride = stride;
1866         buf_info->shm_h = h;
1867
1868         if (g_dump_info->count == 1000)
1869                 g_dump_info->count = 0;
1870
1871         g_dump_info->link = next_link;
1872
1873         TBM_LOG_I("Dump %s \n", buf_info->name);
1874 }
1875 /*LCOV_EXCL_STOP*/