wrap surface mutex lock in tbm_surface_interal_is_valid
[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 (!strcmp(old_data->key, key)) {
1359                                 if (old_data->value && value && !strncmp(old_data->value, value, strlen(old_data->value))) {
1360                                         TBM_TRACE("tbm_surface(%p) Already exist key(%s) and value(%s)!\n", surface, key, value);
1361                                         goto add_debug_key_list;
1362                                 }
1363
1364                                 if (old_data->value)
1365                                         free(old_data->value);
1366
1367                                 if (value)
1368                                         old_data->value = strdup(value);
1369                                 else
1370                                         old_data->value = NULL;
1371                         }
1372                 }
1373         }
1374
1375         debug_data = _tbm_surface_internal_debug_data_create(key, value);
1376         if (!debug_data) {
1377                 TBM_TRACE("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1378                 _tbm_surface_mutex_unlock();
1379                 return 0;
1380         }
1381
1382         TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1383
1384         LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1385
1386 add_debug_key_list:
1387         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1388                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1389                         if (!strcmp(old_data->key, key)) {
1390                                 _tbm_surface_mutex_unlock();
1391                                 return 1;
1392                         }
1393                 }
1394         }
1395
1396         debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1397         LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1398
1399         _tbm_surface_mutex_unlock();
1400
1401         return 1;
1402 }
1403
1404 char *
1405 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1406 {
1407         tbm_surface_debug_data *old_data = NULL;
1408
1409         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1410
1411         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1412                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1413                         if (!strcmp(old_data->key, key))
1414                                 return old_data->value;
1415                 }
1416         }
1417
1418         return NULL;
1419 }
1420
1421 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1422 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1423
1424 struct _tbm_surface_dump_buf_info {
1425         int index;
1426         tbm_bo bo;
1427         int size;
1428         int dirty;
1429         int dirty_shm;
1430         int shm_stride;
1431         int shm_h;
1432         char name[1024];
1433
1434         tbm_surface_info_s info;
1435
1436         struct list_head link;
1437 };
1438
1439 struct _tbm_surface_dump_info {
1440         char *path;  // copy???
1441         int dump_max;
1442         int count;
1443         struct list_head *link;
1444         struct list_head surface_list; /* link of surface */
1445 };
1446
1447 static tbm_surface_dump_info *g_dump_info = NULL;
1448 static const char *dump_postfix[2] = {"png", "yuv"};
1449
1450 static void
1451 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1452                                 void *data2, int size2, void *data3, int size3)
1453 {
1454         FILE *fp = fopen(file, "w+");
1455         TBM_RETURN_IF_FAIL(fp != NULL);
1456         unsigned int *blocks;
1457
1458         blocks = (unsigned int *)data1;
1459         fwrite(blocks, 1, size1, fp);
1460
1461         if (size2 > 0) {
1462                 blocks = (unsigned int *)data2;
1463                 fwrite(blocks, 1, size2, fp);
1464         }
1465
1466         if (size3 > 0) {
1467                 blocks = (unsigned int *)data3;
1468                 fwrite(blocks, 1, size3, fp);
1469         }
1470
1471         fclose(fp);
1472 }
1473
1474 static void
1475 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height)
1476 {
1477         unsigned int *blocks = (unsigned int *)data;
1478         FILE *fp = fopen(file, "wb");
1479         TBM_RETURN_IF_FAIL(fp != NULL);
1480         const int pixel_size = 4;       // RGBA
1481         png_bytep *row_pointers;
1482         int depth = 8, y;
1483
1484         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1485                                                         NULL, NULL, NULL);
1486         if (!pPngStruct) {
1487                 fclose(fp);
1488                 return;
1489         }
1490
1491         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1492         if (!pPngInfo) {
1493                 png_destroy_write_struct(&pPngStruct, NULL);
1494                 fclose(fp);
1495                 return;
1496         }
1497
1498         png_init_io(pPngStruct, fp);
1499         png_set_IHDR(pPngStruct,
1500                         pPngInfo,
1501                         width,
1502                         height,
1503                         depth,
1504                         PNG_COLOR_TYPE_RGBA,
1505                         PNG_INTERLACE_NONE,
1506                         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1507
1508         png_set_bgr(pPngStruct);
1509         png_write_info(pPngStruct, pPngInfo);
1510
1511         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1512         if (!row_pointers) {
1513                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1514                 fclose(fp);
1515                 return;
1516         }
1517
1518         for (y = 0; y < height; ++y) {
1519                 png_bytep row;
1520                 int x = 0;
1521
1522                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1523                 if (!row) {
1524                         for (x = 0; x < y; x++)
1525                                 png_free(pPngStruct, row_pointers[x]);
1526                         png_free(pPngStruct, row_pointers);
1527                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1528                         fclose(fp);
1529                         return;
1530                 }
1531                 row_pointers[y] = (png_bytep)row;
1532
1533                 for (x = 0; x < width; ++x) {
1534                         unsigned int curBlock = blocks[y * width + x];
1535
1536                         row[x * pixel_size] = (curBlock & 0xFF);
1537                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1538                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1539                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1540                 }
1541         }
1542
1543         png_write_image(pPngStruct, row_pointers);
1544         png_write_end(pPngStruct, pPngInfo);
1545
1546         for (y = 0; y < height; y++)
1547                 png_free(pPngStruct, row_pointers[y]);
1548         png_free(pPngStruct, row_pointers);
1549
1550         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1551
1552         fclose(fp);
1553 }
1554
1555 void
1556 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1557 {
1558         TBM_RETURN_IF_FAIL(path != NULL);
1559         TBM_RETURN_IF_FAIL(w > 0);
1560         TBM_RETURN_IF_FAIL(h > 0);
1561         TBM_RETURN_IF_FAIL(count > 0);
1562
1563         tbm_surface_dump_buf_info *buf_info = NULL;
1564         tbm_surface_h tbm_surface;
1565         tbm_surface_info_s info;
1566         int buffer_size, i;
1567
1568         /* check running */
1569         if (g_dump_info) {
1570                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1571                 return;
1572         }
1573
1574         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1575         TBM_RETURN_IF_FAIL(g_dump_info);
1576
1577         LIST_INITHEAD(&g_dump_info->surface_list);
1578         g_dump_info->count = 0;
1579         g_dump_info->dump_max = count;
1580
1581         /* get buffer size */
1582         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1583         if (tbm_surface == NULL) {
1584                 TBM_LOG_E("tbm_surface_create fail\n");
1585                 free(g_dump_info);
1586                 g_dump_info = NULL;
1587                 return;
1588         }
1589
1590         if (TBM_SURFACE_ERROR_NONE != tbm_surface_map(tbm_surface,
1591                                                 TBM_SURF_OPTION_READ, &info)) {
1592                 TBM_LOG_E("tbm_surface_map fail\n");
1593                 tbm_surface_destroy(tbm_surface);
1594                 free(g_dump_info);
1595                 g_dump_info = NULL;
1596                 return;
1597         }
1598         buffer_size = info.planes[0].stride * h;
1599
1600         tbm_surface_unmap(tbm_surface);
1601         tbm_surface_destroy(tbm_surface);
1602
1603         /* create dump lists */
1604         for (i = 0; i < count; i++) {
1605                 tbm_bo bo = NULL;
1606
1607                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1608                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1609
1610                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1611                 if (bo == NULL) {
1612                         free(buf_info);
1613                         goto fail;
1614                 }
1615
1616                 buf_info->index = i;
1617                 buf_info->bo = bo;
1618                 buf_info->size = buffer_size;
1619
1620                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1621         }
1622
1623         g_dump_info->path = path;
1624         g_dump_info->link = &g_dump_info->surface_list;
1625
1626         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1627
1628         return;
1629
1630 fail:
1631         /* free resources */
1632         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1633                 tbm_surface_dump_buf_info *tmp;
1634
1635                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1636                         tbm_bo_unref(buf_info->bo);
1637                         LIST_DEL(&buf_info->link);
1638                         free(buf_info);
1639                 }
1640         }
1641
1642         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1643
1644         free(g_dump_info);
1645         g_dump_info = NULL;
1646
1647         return;
1648 }
1649
1650 void
1651 tbm_surface_internal_dump_end(void)
1652 {
1653         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1654         tbm_bo_handle bo_handle;
1655
1656         if (!g_dump_info)
1657                 return;
1658
1659         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1660                 free(g_dump_info);
1661                 g_dump_info = NULL;
1662                 return;
1663         }
1664
1665         /* make files */
1666         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1667                 char file[2048];
1668
1669                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1670                 if (bo_handle.ptr == NULL) {
1671                         tbm_bo_unref(buf_info->bo);
1672                         LIST_DEL(&buf_info->link);
1673                         free(buf_info);
1674                         continue;
1675                 }
1676
1677                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1678                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1679
1680                 if (buf_info->dirty) {
1681                         void *ptr1 = NULL, *ptr2 = NULL;
1682
1683                         switch (buf_info->info.format) {
1684                         case TBM_FORMAT_ARGB8888:
1685                         case TBM_FORMAT_XRGB8888:
1686                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1687                                                         buf_info->info.planes[0].stride >> 2,
1688                                                         buf_info->info.height);
1689                                 break;
1690                         case TBM_FORMAT_YVU420:
1691                         case TBM_FORMAT_YUV420:
1692                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1693                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1694                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1695                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1696                                                         ptr1,
1697                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1698                                                         ptr2,
1699                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1700                                 break;
1701                         case TBM_FORMAT_NV12:
1702                         case TBM_FORMAT_NV21:
1703                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1704                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1705                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1706                                                         ptr1,
1707                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1708                                                         NULL, 0);
1709                                 break;
1710                         case TBM_FORMAT_YUYV:
1711                         case TBM_FORMAT_UYVY:
1712                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1713                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1714                                                         NULL, 0, NULL, 0);
1715                                 break;
1716                         default:
1717                                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1718                                 break;
1719                         }
1720                 } else if (buf_info->dirty_shm)
1721                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1722                                                         buf_info->shm_stride >> 2,
1723                                                         buf_info->shm_h);
1724
1725                 tbm_bo_unmap(buf_info->bo);
1726                 tbm_bo_unref(buf_info->bo);
1727                 LIST_DEL(&buf_info->link);
1728                 free(buf_info);
1729         }
1730
1731         free(g_dump_info);
1732         g_dump_info = NULL;
1733
1734         TBM_LOG_I("Dump End..\n");
1735 }
1736
1737 void
1738 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1739 {
1740         TBM_RETURN_IF_FAIL(surface != NULL);
1741         TBM_RETURN_IF_FAIL(type != NULL);
1742
1743         tbm_surface_dump_buf_info *buf_info;
1744         struct list_head *next_link;
1745         tbm_surface_info_s info;
1746         tbm_bo_handle bo_handle;
1747         const char *postfix;
1748         int ret;
1749
1750         if (!g_dump_info)
1751                 return;
1752
1753         next_link = g_dump_info->link->next;
1754         TBM_RETURN_IF_FAIL(next_link != NULL);
1755
1756         if (next_link == &g_dump_info->surface_list) {
1757                 next_link = next_link->next;
1758                 TBM_RETURN_IF_FAIL(next_link != NULL);
1759         }
1760
1761         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1762         TBM_RETURN_IF_FAIL(buf_info != NULL);
1763
1764         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1765         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1766
1767         if (info.size > buf_info->size) {
1768                 TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1769                                 info.size, buf_info->size);
1770                 tbm_surface_unmap(surface);
1771                 return;
1772         }
1773
1774         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1775                 postfix = dump_postfix[0];
1776         else
1777                 postfix = dump_postfix[1];
1778
1779         /* make the file information */
1780         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1781
1782         /* dump */
1783         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1784         if (!bo_handle.ptr) {
1785                 TBM_LOG_E("fail to map bo");
1786                 tbm_surface_unmap(surface);
1787                 return;
1788         }
1789         memset(bo_handle.ptr, 0x00, buf_info->size);
1790
1791         switch (info.format) {
1792         case TBM_FORMAT_ARGB8888:
1793         case TBM_FORMAT_XRGB8888:
1794                 snprintf(buf_info->name, sizeof(buf_info->name),
1795                                 "%10.3f_%03d_%p-%s.%s",
1796                                  _tbm_surface_internal_get_time(),
1797                                  g_dump_info->count++, surface, type, postfix);
1798                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1799                 break;
1800         case TBM_FORMAT_YVU420:
1801         case TBM_FORMAT_YUV420:
1802                 snprintf(buf_info->name, sizeof(buf_info->name),
1803                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1804                                  _tbm_surface_internal_get_time(),
1805                                  g_dump_info->count++, type, info.planes[0].stride,
1806                                 info.height, FOURCC_STR(info.format), postfix);
1807                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1808                 bo_handle.ptr += info.planes[0].stride * info.height;
1809                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1810                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1811                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1812                 break;
1813         case TBM_FORMAT_NV12:
1814         case TBM_FORMAT_NV21:
1815                 snprintf(buf_info->name, sizeof(buf_info->name),
1816                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1817                                  _tbm_surface_internal_get_time(),
1818                                  g_dump_info->count++, type, info.planes[0].stride,
1819                                 info.height, FOURCC_STR(info.format), postfix);
1820                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1821                 bo_handle.ptr += info.planes[0].stride * info.height;
1822                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1823                 break;
1824         case TBM_FORMAT_YUYV:
1825         case TBM_FORMAT_UYVY:
1826                 snprintf(buf_info->name, sizeof(buf_info->name),
1827                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1828                                  _tbm_surface_internal_get_time(),
1829                                  g_dump_info->count++, type, info.planes[0].stride,
1830                                 info.height, FOURCC_STR(info.format), postfix);
1831                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1832                 break;
1833         default:
1834                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1835                 tbm_bo_unmap(buf_info->bo);
1836                 tbm_surface_unmap(surface);
1837                 return;
1838         }
1839
1840         tbm_bo_unmap(buf_info->bo);
1841
1842         tbm_surface_unmap(surface);
1843
1844         buf_info->dirty = 1;
1845         buf_info->dirty_shm = 0;
1846
1847         if (g_dump_info->count == 1000)
1848                 g_dump_info->count = 0;
1849
1850         g_dump_info->link = next_link;
1851
1852         TBM_LOG_I("Dump %s \n", buf_info->name);
1853 }
1854
1855 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
1856                                                 const char *type)
1857 {
1858         TBM_RETURN_IF_FAIL(ptr != NULL);
1859         TBM_RETURN_IF_FAIL(w > 0);
1860         TBM_RETURN_IF_FAIL(h > 0);
1861         TBM_RETURN_IF_FAIL(stride > 0);
1862         TBM_RETURN_IF_FAIL(type != NULL);
1863
1864         tbm_surface_dump_buf_info *buf_info;
1865         struct list_head *next_link;
1866         tbm_bo_handle bo_handle;
1867         int size;
1868
1869         if (!g_dump_info)
1870                 return;
1871
1872         next_link = g_dump_info->link->next;
1873         TBM_RETURN_IF_FAIL(next_link != NULL);
1874
1875         if (next_link == &g_dump_info->surface_list) {
1876                 next_link = next_link->next;
1877                 TBM_RETURN_IF_FAIL(next_link != NULL);
1878         }
1879
1880         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1881         TBM_RETURN_IF_FAIL(buf_info != NULL);
1882
1883         size = stride * h;
1884         if (size > buf_info->size) {
1885                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
1886                                 size, buf_info->size);
1887                 return;
1888         }
1889
1890         /* dump */
1891         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1892         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1893
1894         memset(bo_handle.ptr, 0x00, buf_info->size);
1895         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1896
1897         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1898                          _tbm_surface_internal_get_time(),
1899                          g_dump_info->count++, type, dump_postfix[0]);
1900         memcpy(bo_handle.ptr, ptr, size);
1901
1902         tbm_bo_unmap(buf_info->bo);
1903
1904         buf_info->dirty = 0;
1905         buf_info->dirty_shm = 1;
1906         buf_info->shm_stride = stride;
1907         buf_info->shm_h = h;
1908
1909         if (g_dump_info->count == 1000)
1910                 g_dump_info->count = 0;
1911
1912         g_dump_info->link = next_link;
1913
1914         TBM_LOG_I("Dump %s \n", buf_info->name);
1915 }
1916
1917 int
1918 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
1919 {
1920         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
1921         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1922         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
1923
1924         tbm_surface_info_s info;
1925         const char *postfix;
1926         int ret;
1927         char file[1024];
1928
1929         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1930         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
1931
1932         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1933                 postfix = dump_postfix[0];
1934         else
1935                 postfix = dump_postfix[1];
1936
1937         if (strcmp(postfix, type)) {
1938                 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
1939                 tbm_surface_unmap(surface);
1940                 return 0;
1941         }
1942
1943         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
1944
1945         if (!access(file, 0)) {
1946                 TBM_LOG_E("can't capture  buffer, exist file %s", file);
1947                 tbm_surface_unmap(surface);
1948                 return 0;
1949         }
1950
1951         switch (info.format) {
1952         case TBM_FORMAT_ARGB8888:
1953         case TBM_FORMAT_XRGB8888:
1954                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
1955                                                         info.planes[0].stride >> 2,
1956                                                         info.height);
1957                 break;
1958         case TBM_FORMAT_YVU420:
1959         case TBM_FORMAT_YUV420:
1960                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
1961                                 info.planes[0].stride * info.height,
1962                                 info.planes[1].ptr,
1963                                 info.planes[1].stride * (info.height >> 1),
1964                                 info.planes[2].ptr,
1965                                 info.planes[2].stride * (info.height >> 1));
1966                 break;
1967         case TBM_FORMAT_NV12:
1968         case TBM_FORMAT_NV21:
1969                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
1970                                         info.planes[0].stride * info.height,
1971                                         info.planes[1].ptr,
1972                                         info.planes[1].stride * (info.height >> 1),
1973                                         NULL, 0);
1974                 break;
1975         case TBM_FORMAT_YUYV:
1976         case TBM_FORMAT_UYVY:
1977                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
1978                                         info.planes[0].stride * info.height,
1979                                         NULL, 0, NULL, 0);
1980                 break;
1981         default:
1982                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
1983                 tbm_surface_unmap(surface);
1984                 return 0;
1985         }
1986
1987         tbm_surface_unmap(surface);
1988
1989         TBM_LOG_I("Capture %s \n", file);
1990
1991         return 1;
1992 }
1993
1994 int
1995 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
1996                                                 const char *path, const char *name, const char *type)
1997 {
1998         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
1999         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2000         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2001         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2002         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2003         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2004
2005         char file[1024];
2006
2007         if (strcmp(dump_postfix[0], type)) {
2008                 TBM_LOG_E("Not supported type:%s'", type);
2009                 return 0;
2010         }
2011
2012         if (!access(file, 0)) {
2013                 TBM_LOG_E("can't capture buffer, exist file %s", file);
2014                 return 0;
2015         }
2016
2017         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2018
2019         _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2020
2021         TBM_LOG_I("Capture %s \n", file);
2022
2023         return 1;
2024 }
2025 /*LCOV_EXCL_STOP*/