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