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