surface_internal: make _tbm_surface_internal_get_num_planes function
[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 #include <pixman.h>
43
44 static tbm_bufmgr g_surface_bufmgr;
45 static pthread_mutex_t tbm_surface_lock;
46 void _tbm_surface_mutex_unlock(void);
47
48 #define C(b, m)              (((b) >> (m)) & 0xFF)
49 #define B(c, s)              ((((unsigned int)(c)) & 0xff) << (s))
50 #define FOURCC(a, b, c, d)     (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
51 #define FOURCC_STR(id)      C(id, 0), C(id, 8), C(id, 16), C(id, 24)
52 #define FOURCC_ID(str)      FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3])
53
54 /* check condition */
55 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
56         if (!(cond)) {\
57                 TBM_ERR("'%s' failed.\n", #cond);\
58                 _tbm_surface_mutex_unlock();\
59                 return;\
60         } \
61 }
62
63 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
64         if (!(cond)) {\
65                 TBM_ERR("'%s' failed.\n", #cond);\
66                 _tbm_surface_mutex_unlock();\
67                 return val;\
68         } \
69 }
70
71 /* LCOV_EXCL_START */
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
221 static bool
222 _tbm_surface_mutex_init(void)
223 {
224         static bool tbm_surface_mutex_init = false;
225
226         if (tbm_surface_mutex_init)
227                 return true;
228
229         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
230                 TBM_ERR("fail: pthread_mutex_init for tbm_surface_lock.\n");
231                 return false;
232         }
233
234         tbm_surface_mutex_init = true;
235
236         return true;
237 }
238
239 void
240 _tbm_surface_mutex_lock(void)
241 {
242         if (!_tbm_surface_mutex_init()) {
243                 TBM_ERR("fail: _tbm_surface_mutex_init.\n");
244                 return;
245         }
246
247         pthread_mutex_lock(&tbm_surface_lock);
248 }
249
250 void
251 _tbm_surface_mutex_unlock(void)
252 {
253         pthread_mutex_unlock(&tbm_surface_lock);
254 }
255
256 static void
257 _init_surface_bufmgr(void)
258 {
259         g_surface_bufmgr = tbm_bufmgr_init(-1);
260 }
261
262 static void
263 _deinit_surface_bufmgr(void)
264 {
265         if (!g_surface_bufmgr)
266                 return;
267
268         tbm_bufmgr_deinit(g_surface_bufmgr);
269         g_surface_bufmgr = NULL;
270 }
271 /* LCOV_EXCL_STOP */
272
273 static int
274 _tbm_surface_internal_is_valid(tbm_surface_h surface)
275 {
276         tbm_surface_h old_data = NULL;
277
278         TBM_RETURN_VAL_IF_FAIL(g_surface_bufmgr, 0);
279         TBM_RETURN_VAL_IF_FAIL(surface, 0);
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_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
285                                 return 1;
286                         }
287                 }
288         }
289
290         TBM_ERR("error: No valid tbm_surface(%p)\n", surface);
291
292         return 0;
293 }
294
295 static int
296 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
297                                        int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
298 {
299         TBM_RETURN_VAL_IF_FAIL(surface, 0);
300         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
301
302         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
303         struct _tbm_bufmgr *bufmgr = surf->bufmgr;
304         int ret = 0;
305         tbm_error_e error;
306
307         TBM_RETURN_VAL_IF_FAIL(bufmgr != NULL, 0);
308         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
309         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
310         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
311
312         if (bufmgr->backend_module_data) {
313                 if (!bufmgr->bufmgr_func->bufmgr_get_plane_data)
314                         return 0;
315
316                 error = bufmgr->bufmgr_func->bufmgr_get_plane_data(bufmgr->bufmgr_data, surf->info.format, plane_idx,
317                                                 surf->info.width, surf->info.height, size, offset, pitch, bo_idx);
318                 if (error != TBM_ERROR_NONE) {
319                         /* LCOV_EXCL_START */
320                         TBM_ERR("Fail to surface_get_plane_data. surface(%p) error(%d)\n", surface, error);
321                         return 0;
322                         /* LCOV_EXCL_STOP */
323                 }
324                 ret = 1;
325         } else {
326                 if (!bufmgr->backend->surface_get_plane_data)
327                         return 0;
328
329                 ret = bufmgr->backend->surface_get_plane_data(surf->info.width,
330                                 surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
331                 if (!ret) {
332                         /* LCOV_EXCL_START */
333                         TBM_ERR("Fail to surface_get_plane_data. surface(%p)\n", surface);
334                         return 0;
335                         /* LCOV_EXCL_STOP */
336                 }
337         }
338
339         return ret;
340 }
341
342 static void
343 _tbm_surface_internal_destroy(tbm_surface_h surface)
344 {
345         int i;
346         tbm_bufmgr bufmgr = surface->bufmgr;
347         tbm_user_data *old_data = NULL, *tmp = NULL;
348         tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
349
350         /* destory the user_data_list */
351         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
352                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
353                         TBM_DBG("free user_data\n");
354                         user_data_delete(old_data);
355                 }
356         }
357
358         for (i = 0; i < surface->num_bos; i++) {
359                 surface->bos[i]->surface = NULL;
360
361                 tbm_bo_unref(surface->bos[i]);
362                 surface->bos[i] = NULL;
363         }
364
365         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
366                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
367                         _tbm_surface_internal_debug_data_delete(debug_old_data);
368         }
369
370         LIST_DEL(&surface->item_link);
371
372         free(surface);
373         surface = NULL;
374
375         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
376                 LIST_DELINIT(&bufmgr->surf_list);
377
378                 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
379                         LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
380                                 _tbm_surface_internal_debug_data_delete(debug_old_data);
381                         }
382                 }
383
384                 _deinit_surface_bufmgr();
385         }
386 }
387
388 /* LCOV_EXCL_START */
389 static int
390 _tbm_surface_check_file_is_symbolic_link(const char* path)
391 {
392         struct stat sb;
393
394         if (!path)
395                 return 0;
396
397         if (stat(path, &sb) != 0)
398                 return 0;
399
400         if (S_ISLNK(sb.st_mode))
401                 return 1;
402
403         return 0;
404 }
405 /* LCOV_EXCL_STOP */
406
407 static int
408 _tbm_surface_internal_get_num_planes(tbm_format format)
409 {
410         int num_planes = 0;
411
412         switch (format) {
413         case TBM_FORMAT_C8:
414         case TBM_FORMAT_RGB332:
415         case TBM_FORMAT_BGR233:
416         case TBM_FORMAT_XRGB4444:
417         case TBM_FORMAT_XBGR4444:
418         case TBM_FORMAT_RGBX4444:
419         case TBM_FORMAT_BGRX4444:
420         case TBM_FORMAT_ARGB4444:
421         case TBM_FORMAT_ABGR4444:
422         case TBM_FORMAT_RGBA4444:
423         case TBM_FORMAT_BGRA4444:
424         case TBM_FORMAT_XRGB1555:
425         case TBM_FORMAT_XBGR1555:
426         case TBM_FORMAT_RGBX5551:
427         case TBM_FORMAT_BGRX5551:
428         case TBM_FORMAT_ARGB1555:
429         case TBM_FORMAT_ABGR1555:
430         case TBM_FORMAT_RGBA5551:
431         case TBM_FORMAT_BGRA5551:
432         case TBM_FORMAT_RGB565:
433         case TBM_FORMAT_BGR565:
434         case TBM_FORMAT_RGB888:
435         case TBM_FORMAT_BGR888:
436         case TBM_FORMAT_XRGB8888:
437         case TBM_FORMAT_XBGR8888:
438         case TBM_FORMAT_RGBX8888:
439         case TBM_FORMAT_BGRX8888:
440         case TBM_FORMAT_ARGB8888:
441         case TBM_FORMAT_ABGR8888:
442         case TBM_FORMAT_RGBA8888:
443         case TBM_FORMAT_BGRA8888:
444         case TBM_FORMAT_XRGB2101010:
445         case TBM_FORMAT_XBGR2101010:
446         case TBM_FORMAT_RGBX1010102:
447         case TBM_FORMAT_BGRX1010102:
448         case TBM_FORMAT_ARGB2101010:
449         case TBM_FORMAT_ABGR2101010:
450         case TBM_FORMAT_RGBA1010102:
451         case TBM_FORMAT_BGRA1010102:
452         case TBM_FORMAT_YUYV:
453         case TBM_FORMAT_YVYU:
454         case TBM_FORMAT_UYVY:
455         case TBM_FORMAT_VYUY:
456         case TBM_FORMAT_AYUV:
457                 num_planes = 1;
458                 break;
459         case TBM_FORMAT_NV12:
460         case TBM_FORMAT_NV12MT:
461         case TBM_FORMAT_NV21:
462         case TBM_FORMAT_NV16:
463         case TBM_FORMAT_NV61:
464                 num_planes = 2;
465                 break;
466         case TBM_FORMAT_YUV410:
467         case TBM_FORMAT_YVU410:
468         case TBM_FORMAT_YUV411:
469         case TBM_FORMAT_YVU411:
470         case TBM_FORMAT_YUV420:
471         case TBM_FORMAT_YVU420:
472         case TBM_FORMAT_YUV422:
473         case TBM_FORMAT_YVU422:
474         case TBM_FORMAT_YUV444:
475         case TBM_FORMAT_YVU444:
476                 num_planes = 3;
477                 break;
478
479         default:
480                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
481                 break;
482         }
483
484         return num_planes;
485 }
486
487 int
488 tbm_surface_internal_is_valid(tbm_surface_h surface)
489 {
490         int ret = 0;
491
492         _tbm_surface_mutex_lock();
493
494         /* Return silently if surface is null. */
495         if (!surface) {
496                 _tbm_surface_mutex_unlock();
497                 return 0;
498         }
499
500         ret = _tbm_surface_internal_is_valid(surface);
501
502         _tbm_surface_mutex_unlock();
503
504         return ret;
505 }
506
507 int
508 tbm_surface_internal_query_supported_formats(uint32_t **formats,
509                 uint32_t *num)
510 {
511         TBM_RETURN_VAL_IF_FAIL(formats, 0);
512         TBM_RETURN_VAL_IF_FAIL(num, 0);
513
514         struct _tbm_bufmgr *bufmgr;
515         int ret = 0;
516         bool bufmgr_initialized = false;
517         tbm_error_e error;
518
519         _tbm_surface_mutex_lock();
520
521         if (!g_surface_bufmgr) {
522                 _init_surface_bufmgr();
523                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
524                 bufmgr_initialized = true;
525         }
526
527         bufmgr = g_surface_bufmgr;
528
529         if (bufmgr->backend_module_data) {
530                 if (!bufmgr->bufmgr_func->bufmgr_get_supported_formats)
531                         goto fail;
532
533                 error = bufmgr->bufmgr_func->bufmgr_get_supported_formats(bufmgr->bufmgr_data, formats, num);
534                 if (error != TBM_ERROR_NONE) {
535                         /* LCOV_EXCL_START */
536                         TBM_ERR("Fail to surface_supported_format. error(%d)\n", error);
537                         goto fail;
538                         /* LCOV_EXCL_START */
539                 }
540                 ret = 1;
541         } else {
542                 if (!bufmgr->backend->surface_supported_format)
543                         goto fail;
544
545                 ret = bufmgr->backend->surface_supported_format(formats, num);
546                 if (!ret)  {
547                         /* LCOV_EXCL_START */
548                         TBM_ERR("Fail to surface_supported_format.\n");
549                         goto fail;
550                         /* LCOV_EXCL_START */
551                 }
552         }
553
554         TBM_TRACE_SURFACE_INTERNAL("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
555
556         if (bufmgr_initialized) {
557                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
558                 _deinit_surface_bufmgr();
559         }
560
561         _tbm_surface_mutex_unlock();
562
563         return ret;
564
565 /* LCOV_EXCL_START */
566 fail:
567         if (bufmgr_initialized) {
568                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
569                 _deinit_surface_bufmgr();
570         }
571         _tbm_surface_mutex_unlock();
572
573         TBM_ERR("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
574
575         return 0;
576 /* LCOV_EXCL_STOP */
577 }
578
579 int
580 tbm_surface_internal_get_num_planes(tbm_format format)
581 {
582         int num_planes = 0;
583
584         _tbm_surface_mutex_lock();
585         _tbm_set_last_result(TBM_ERROR_NONE);
586
587         num_planes = _tbm_surface_internal_get_num_planes(format);
588         if (!num_planes) {
589                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
590                 _tbm_surface_mutex_unlock();
591                 return 0;
592         }
593
594         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
595
596         _tbm_surface_mutex_unlock();
597
598         return num_planes;
599 }
600
601 int
602 tbm_surface_internal_get_bpp(tbm_format format)
603 {
604
605         int bpp = 0;
606
607         switch (format) {
608         case TBM_FORMAT_C8:
609         case TBM_FORMAT_RGB332:
610         case TBM_FORMAT_BGR233:
611                 bpp = 8;
612                 break;
613         case TBM_FORMAT_XRGB4444:
614         case TBM_FORMAT_XBGR4444:
615         case TBM_FORMAT_RGBX4444:
616         case TBM_FORMAT_BGRX4444:
617         case TBM_FORMAT_ARGB4444:
618         case TBM_FORMAT_ABGR4444:
619         case TBM_FORMAT_RGBA4444:
620         case TBM_FORMAT_BGRA4444:
621         case TBM_FORMAT_XRGB1555:
622         case TBM_FORMAT_XBGR1555:
623         case TBM_FORMAT_RGBX5551:
624         case TBM_FORMAT_BGRX5551:
625         case TBM_FORMAT_ARGB1555:
626         case TBM_FORMAT_ABGR1555:
627         case TBM_FORMAT_RGBA5551:
628         case TBM_FORMAT_BGRA5551:
629         case TBM_FORMAT_RGB565:
630         case TBM_FORMAT_BGR565:
631                 bpp = 16;
632                 break;
633         case TBM_FORMAT_RGB888:
634         case TBM_FORMAT_BGR888:
635                 bpp = 24;
636                 break;
637         case TBM_FORMAT_XRGB8888:
638         case TBM_FORMAT_XBGR8888:
639         case TBM_FORMAT_RGBX8888:
640         case TBM_FORMAT_BGRX8888:
641         case TBM_FORMAT_ARGB8888:
642         case TBM_FORMAT_ABGR8888:
643         case TBM_FORMAT_RGBA8888:
644         case TBM_FORMAT_BGRA8888:
645         case TBM_FORMAT_XRGB2101010:
646         case TBM_FORMAT_XBGR2101010:
647         case TBM_FORMAT_RGBX1010102:
648         case TBM_FORMAT_BGRX1010102:
649         case TBM_FORMAT_ARGB2101010:
650         case TBM_FORMAT_ABGR2101010:
651         case TBM_FORMAT_RGBA1010102:
652         case TBM_FORMAT_BGRA1010102:
653         case TBM_FORMAT_YUYV:
654         case TBM_FORMAT_YVYU:
655         case TBM_FORMAT_UYVY:
656         case TBM_FORMAT_VYUY:
657         case TBM_FORMAT_AYUV:
658                 bpp = 32;
659                 break;
660         case TBM_FORMAT_NV12:
661         case TBM_FORMAT_NV12MT:
662         case TBM_FORMAT_NV21:
663                 bpp = 12;
664                 break;
665         case TBM_FORMAT_NV16:
666         case TBM_FORMAT_NV61:
667                 bpp = 16;
668                 break;
669         case TBM_FORMAT_YUV410:
670         case TBM_FORMAT_YVU410:
671                 bpp = 9;
672                 break;
673         case TBM_FORMAT_YUV411:
674         case TBM_FORMAT_YVU411:
675         case TBM_FORMAT_YUV420:
676         case TBM_FORMAT_YVU420:
677                 bpp = 12;
678                 break;
679         case TBM_FORMAT_YUV422:
680         case TBM_FORMAT_YVU422:
681                 bpp = 16;
682                 break;
683         case TBM_FORMAT_YUV444:
684         case TBM_FORMAT_YVU444:
685                 bpp = 24;
686                 break;
687         default:
688                 break;
689         }
690
691         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
692
693         return bpp;
694 }
695
696 tbm_surface_h
697 tbm_surface_internal_create_with_flags(int width, int height,
698                                        int format, int flags)
699 {
700         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
701         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
702
703         struct _tbm_bufmgr *bufmgr;
704         struct _tbm_surface *surf = NULL;
705         uint32_t size = 0;
706         uint32_t offset = 0;
707         uint32_t stride = 0;
708         uint32_t bo_size = 0;
709         int bo_idx;
710         int i, j;
711         bool bufmgr_initialized = false;
712         tbm_bo bo = NULL;
713         void *bo_priv = NULL;
714         tbm_backend_bo_data *bo_data = NULL;
715         tbm_error_e error;
716
717         _tbm_surface_mutex_lock();
718
719         if (!g_surface_bufmgr) {
720                 _init_surface_bufmgr();
721                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
722                 bufmgr_initialized = true;
723         }
724
725         bufmgr = g_surface_bufmgr;
726         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
727                 TBM_ERR("The bufmgr is invalid\n");
728                 goto check_valid_fail;
729         }
730
731         surf = calloc(1, sizeof(struct _tbm_surface));
732         if (!surf) {
733                 /* LCOV_EXCL_START */
734                 TBM_ERR("fail to alloc surf\n");
735                 goto alloc_surf_fail;
736                 /* LCOV_EXCL_STOP */
737         }
738
739         surf->bufmgr = bufmgr;
740         surf->info.width = width;
741         surf->info.height = height;
742         surf->info.format = format;
743         surf->info.bpp = tbm_surface_internal_get_bpp(format);
744         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
745         if (!surf->info.num_planes) {
746                 TBM_ERR("fail to get num_planes. error(%s)\n", tbm_error_str(tbm_get_last_error()));
747                 goto num_planes_fail;
748         }
749         surf->refcnt = 1;
750
751         /* get size, stride and offset bo_idx */
752         for (i = 0; i < surf->info.num_planes; i++) {
753                 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
754                                                 &offset, &stride, &bo_idx)) {
755                         TBM_ERR("fail to query plane data\n");
756                         goto query_plane_data_fail;
757                 }
758
759                 surf->info.planes[i].size = size;
760                 surf->info.planes[i].offset = offset;
761                 surf->info.planes[i].stride = stride;
762                 surf->planes_bo_idx[i] = bo_idx;
763         }
764
765         surf->num_bos = 1;
766
767         for (i = 0; i < surf->info.num_planes; i++) {
768                 surf->info.size += surf->info.planes[i].size;
769
770                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
771                         surf->num_bos = surf->planes_bo_idx[i] + 1;
772         }
773
774         surf->flags = flags;
775
776         for (i = 0; i < surf->num_bos; i++) {
777                 bo_size = 0;
778                 for (j = 0; j < surf->info.num_planes; j++) {
779                         if (surf->planes_bo_idx[j] == i)
780                                 bo_size += surf->info.planes[j].size;
781                 }
782
783                 if (bufmgr->backend_module_data) {
784                         if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
785                                 /* LCOV_EXCL_START */
786                                 bo = calloc(1, sizeof(struct _tbm_bo));
787                                 if (!bo) {
788                                         TBM_ERR("fail to alloc bo struct\n");
789                                         goto alloc_bo_fail;
790                                 }
791
792                                 bo->bufmgr = surf->bufmgr;
793
794                                 pthread_mutex_lock(&surf->bufmgr->lock);
795
796                                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format(bufmgr->bufmgr_data, format, i,
797                                                                                                                                 width, height, flags, &error);
798                                 if (!bo_data) {
799                                         TBM_ERR("fail to alloc bo priv. error(%d)\n", error);
800                                         free(bo);
801                                         pthread_mutex_unlock(&surf->bufmgr->lock);
802                                         goto alloc_bo_fail;
803                                 }
804                                 bo->bo_data = bo_data;
805
806                                 bo->ref_cnt = 1;
807                                 bo->flags = flags;
808                                 LIST_INITHEAD(&bo->user_data_list);
809
810                                 LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
811
812                                 pthread_mutex_unlock(&surf->bufmgr->lock);
813
814                                 surf->bos[i] = bo;
815                                 /* LCOV_EXCL_STOP */
816                         } else {
817                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
818                                 if (!surf->bos[i]) {
819                                         TBM_ERR("fail to alloc bo idx:%d\n", i);
820                                         goto alloc_bo_fail;
821                                 }
822                         }
823                 } else {
824                         if (bufmgr->backend->surface_bo_alloc) {
825                                 /* LCOV_EXCL_START */
826                                 bo = calloc(1, sizeof(struct _tbm_bo));
827                                 if (!bo) {
828                                         TBM_ERR("fail to alloc bo struct\n");
829                                         goto alloc_bo_fail;
830                                 }
831
832                                 bo->bufmgr = surf->bufmgr;
833
834                                 pthread_mutex_lock(&surf->bufmgr->lock);
835
836                                 bo_priv = bufmgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
837                                 if (!bo_priv) {
838                                         TBM_ERR("fail to alloc bo priv\n");
839                                         free(bo);
840                                         pthread_mutex_unlock(&surf->bufmgr->lock);
841                                         goto alloc_bo_fail;
842                                 }
843                                 bo->priv = bo_priv;
844
845                                 bo->ref_cnt = 1;
846                                 bo->flags = flags;
847                                 LIST_INITHEAD(&bo->user_data_list);
848
849                                 LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
850
851                                 pthread_mutex_unlock(&surf->bufmgr->lock);
852
853                                 surf->bos[i] = bo;
854                                 /* LCOV_EXCL_STOP */
855                         } else {
856                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
857                                 if (!surf->bos[i]) {
858                                         TBM_ERR("fail to alloc bo idx:%d\n", i);
859                                         goto alloc_bo_fail;
860                                 }
861                         }
862                 }
863
864                 _tbm_bo_set_surface(surf->bos[i], surf);
865         }
866
867         TBM_TRACE_SURFACE_INTERNAL("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
868                         _tbm_surface_internal_format_to_str(format), flags, surf);
869
870         LIST_INITHEAD(&surf->user_data_list);
871         LIST_INITHEAD(&surf->debug_data_list);
872
873         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
874
875         _tbm_surface_mutex_unlock();
876
877         return surf;
878
879 /* LCOV_EXCL_START */
880 alloc_bo_fail:
881         for (j = 0; j < i; j++) {
882                 if (surf->bos[j])
883                         tbm_bo_unref(surf->bos[j]);
884         }
885 query_plane_data_fail:
886 num_planes_fail:
887         free(surf);
888 alloc_surf_fail:
889 check_valid_fail:
890         if (bufmgr_initialized && bufmgr) {
891                 LIST_DELINIT(&bufmgr->surf_list);
892                 _deinit_surface_bufmgr();
893         }
894         _tbm_surface_mutex_unlock();
895
896         TBM_ERR("error: width(%d) height(%d) format(%s) flags(%d)\n",
897                         width, height,
898                         _tbm_surface_internal_format_to_str(format), flags);
899 /* LCOV_EXCL_STOP */
900
901         return NULL;
902 }
903
904 tbm_surface_h
905 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
906                                      tbm_bo *bos, int num)
907 {
908         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
909         TBM_RETURN_VAL_IF_FAIL(info, NULL);
910         TBM_RETURN_VAL_IF_FAIL(info->num_planes > 0, NULL);
911         TBM_RETURN_VAL_IF_FAIL(num > 0, NULL);
912         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
913
914         struct _tbm_bufmgr *bufmgr;
915         struct _tbm_surface *surf = NULL;
916         int i;
917         bool bufmgr_initialized = false;
918
919         _tbm_surface_mutex_lock();
920
921         if (!g_surface_bufmgr) {
922                 _init_surface_bufmgr();
923                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
924                 bufmgr_initialized = true;
925         }
926
927         bufmgr = g_surface_bufmgr;
928         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
929                 TBM_ERR("fail to validate the Bufmgr.\n");
930                 goto check_valid_fail;
931         }
932
933         surf = calloc(1, sizeof(struct _tbm_surface));
934         if (!surf) {
935                 /* LCOV_EXCL_START */
936                 TBM_ERR("fail to allocate struct _tbm_surface.\n");
937                 goto alloc_surf_fail;
938                 /* LCOV_EXCL_STOP */
939         }
940
941         surf->bufmgr = bufmgr;
942         surf->info.width = info->width;
943         surf->info.height = info->height;
944         surf->info.format = info->format;
945         if (info->bpp > 0)
946                 surf->info.bpp = info->bpp;
947         else
948                 surf->info.bpp = tbm_surface_internal_get_bpp(info->format);
949         surf->info.num_planes = info->num_planes;
950         surf->refcnt = 1;
951
952         /* get size, stride and offset */
953         for (i = 0; i < info->num_planes; i++) {
954                 surf->info.planes[i].offset = info->planes[i].offset;
955                 surf->info.planes[i].stride = info->planes[i].stride;
956
957                 if (info->planes[i].size > 0)
958                         surf->info.planes[i].size = info->planes[i].size;
959                 else {
960                         uint32_t size = 0, offset = 0, stride = 0;
961                         int32_t bo_idx = 0;
962
963                         _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx);
964                         surf->info.planes[i].size = size;
965                 }
966
967                 if (num == 1)
968                         surf->planes_bo_idx[i] = 0;
969                 else
970                         surf->planes_bo_idx[i] = i;
971         }
972
973         if (info->size > 0) {
974                 surf->info.size = info->size;
975         } else {
976                 surf->info.size = 0;
977                 for (i = 0; i < info->num_planes; i++)
978                         surf->info.size += surf->info.planes[i].size;
979         }
980
981         surf->flags = TBM_BO_DEFAULT;
982
983         /* create only one bo */
984         surf->num_bos = num;
985         for (i = 0; i < num; i++) {
986                 if (bos[i] == NULL) {
987                         TBM_ERR("bos[%d] is null.\n", i);
988                         goto check_bo_fail;
989                 }
990
991                 surf->bos[i] = tbm_bo_ref(bos[i]);
992                 _tbm_bo_set_surface(bos[i], surf);
993         }
994
995         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
996                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
997
998         LIST_INITHEAD(&surf->user_data_list);
999         LIST_INITHEAD(&surf->debug_data_list);
1000
1001         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1002
1003         _tbm_surface_mutex_unlock();
1004
1005         return surf;
1006
1007 /* LCOV_EXCL_START */
1008 check_bo_fail:
1009         for (i = 0; i < num; i++) {
1010                 if (surf->bos[i])
1011                         tbm_bo_unref(surf->bos[i]);
1012         }
1013         free(surf);
1014 alloc_surf_fail:
1015 check_valid_fail:
1016         if (bufmgr_initialized && bufmgr) {
1017                 LIST_DELINIT(&bufmgr->surf_list);
1018                 _deinit_surface_bufmgr();
1019         }
1020         _tbm_surface_mutex_unlock();
1021
1022         TBM_ERR("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
1023                         info->width, info->height,
1024                         _tbm_surface_internal_format_to_str(info->format), num);
1025 /* LCOV_EXCL_STOP */
1026
1027         return NULL;
1028 }
1029
1030 void
1031 tbm_surface_internal_destroy(tbm_surface_h surface)
1032 {
1033         _tbm_surface_mutex_lock();
1034
1035         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1036
1037         surface->refcnt--;
1038
1039         if (surface->refcnt > 0) {
1040                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1041                 _tbm_surface_mutex_unlock();
1042                 return;
1043         }
1044
1045         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1046
1047         if (surface->refcnt == 0)
1048                 _tbm_surface_internal_destroy(surface);
1049
1050         _tbm_surface_mutex_unlock();
1051 }
1052
1053 void
1054 tbm_surface_internal_ref(tbm_surface_h surface)
1055 {
1056         _tbm_surface_mutex_lock();
1057
1058         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1059
1060         surface->refcnt++;
1061
1062         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1063
1064         _tbm_surface_mutex_unlock();
1065 }
1066
1067 void
1068 tbm_surface_internal_unref(tbm_surface_h surface)
1069 {
1070         _tbm_surface_mutex_lock();
1071
1072         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1073
1074         surface->refcnt--;
1075
1076         if (surface->refcnt > 0) {
1077                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1078                 _tbm_surface_mutex_unlock();
1079                 return;
1080         }
1081
1082         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1083
1084         if (surface->refcnt == 0)
1085                 _tbm_surface_internal_destroy(surface);
1086
1087         _tbm_surface_mutex_unlock();
1088 }
1089
1090 int
1091 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1092 {
1093         struct _tbm_surface *surf;
1094         int num;
1095
1096         _tbm_surface_mutex_lock();
1097
1098         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1099
1100         surf = (struct _tbm_surface *)surface;
1101         num = surf->num_bos;
1102
1103         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)\n", surface, num);
1104
1105         _tbm_surface_mutex_unlock();
1106
1107         return num;
1108 }
1109
1110 tbm_bo
1111 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1112 {
1113         struct _tbm_surface *surf;
1114         tbm_bo bo;
1115
1116         _tbm_surface_mutex_lock();
1117
1118         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1119         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1120
1121         surf = (struct _tbm_surface *)surface;
1122         bo = surf->bos[bo_idx];
1123
1124         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
1125
1126         _tbm_surface_mutex_unlock();
1127
1128         return bo;
1129 }
1130
1131 unsigned int
1132 tbm_surface_internal_get_size(tbm_surface_h surface)
1133 {
1134         struct _tbm_surface *surf;
1135         unsigned int size;
1136
1137         _tbm_surface_mutex_lock();
1138
1139         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1140
1141         surf = (struct _tbm_surface *)surface;
1142         size = surf->info.size;
1143
1144         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)\n", surface, size);
1145
1146         _tbm_surface_mutex_unlock();
1147
1148         return size;
1149 }
1150
1151 int
1152 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1153                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1154 {
1155         struct _tbm_surface *surf;
1156
1157         _tbm_surface_mutex_lock();
1158
1159         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1160         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1161
1162         surf = (struct _tbm_surface *)surface;
1163
1164         if (plane_idx >= surf->info.num_planes) {
1165                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1166                 _tbm_surface_mutex_unlock();
1167                 return 0;
1168         }
1169
1170         if (size)
1171                 *size = surf->info.planes[plane_idx].size;
1172
1173         if (offset)
1174                 *offset = surf->info.planes[plane_idx].offset;
1175
1176         if (pitch)
1177                 *pitch = surf->info.planes[plane_idx].stride;
1178
1179         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1180                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1181                                 surf->info.planes[plane_idx].stride);
1182
1183         _tbm_surface_mutex_unlock();
1184
1185         return 1;
1186 }
1187
1188 int
1189 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1190                               tbm_surface_info_s *info, int map)
1191 {
1192         struct _tbm_surface *surf;
1193         tbm_bo_handle bo_handles[4];
1194         int num_bos = 0;
1195         tbm_bo bos[4];
1196         int planes_bo_idx[TBM_SURF_PLANE_MAX];
1197         int i, j;
1198
1199         _tbm_surface_mutex_lock();
1200
1201         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1202
1203         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1204
1205         surf = (struct _tbm_surface *)surface;
1206
1207         memset(info, 0x00, sizeof(tbm_surface_info_s));
1208         info->width = surf->info.width;
1209         info->height = surf->info.height;
1210         info->format = surf->info.format;
1211         info->bpp = surf->info.bpp;
1212         info->size = surf->info.size;
1213         info->num_planes = surf->info.num_planes;
1214
1215         for (i = 0; i < surf->info.num_planes; i++) {
1216                 info->planes[i].size = surf->info.planes[i].size;
1217                 info->planes[i].offset = surf->info.planes[i].offset;
1218                 info->planes[i].stride = surf->info.planes[i].stride;
1219                 planes_bo_idx[i] = surf->planes_bo_idx[i];
1220         }
1221
1222         for (i = 0; i < surf->num_bos; i++)
1223                 bos[i] = surf->bos[i];
1224
1225         num_bos = surf->num_bos;
1226
1227         if (map == 1) {
1228                 _tbm_surface_mutex_unlock();
1229                 for (i = 0; i < num_bos; i++) {
1230                         bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1231                         if (bo_handles[i].ptr == NULL) {
1232                                 for (j = 0; j < i; j++)
1233                                         tbm_bo_unmap(bos[j]);
1234
1235                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1236                                 return 0;
1237                         }
1238                 }
1239                 _tbm_surface_mutex_lock();
1240         } else {
1241                 for (i = 0; i < num_bos; i++) {
1242                         bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1243                         if (bo_handles[i].ptr == NULL) {
1244                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1245                                 _tbm_surface_mutex_unlock();
1246                                 return 0;
1247                         }
1248                 }
1249         }
1250
1251         for (i = 0; i < info->num_planes; i++) {
1252                 if (bo_handles[planes_bo_idx[i]].ptr)
1253                         info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1254         }
1255
1256         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1257
1258         _tbm_surface_mutex_unlock();
1259
1260         return 1;
1261 }
1262
1263 void
1264 tbm_surface_internal_unmap(tbm_surface_h surface)
1265 {
1266         struct _tbm_surface *surf;
1267         int i;
1268
1269         _tbm_surface_mutex_lock();
1270
1271         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1272
1273         surf = (struct _tbm_surface *)surface;
1274
1275         for (i = 0; i < surf->num_bos; i++)
1276                 tbm_bo_unmap(surf->bos[i]);
1277
1278         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1279
1280         _tbm_surface_mutex_unlock();
1281 }
1282
1283 unsigned int
1284 tbm_surface_internal_get_width(tbm_surface_h surface)
1285 {
1286         struct _tbm_surface *surf;
1287         unsigned int width;
1288
1289         _tbm_surface_mutex_lock();
1290
1291         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1292
1293         surf = (struct _tbm_surface *)surface;
1294         width = surf->info.width;
1295
1296         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1297
1298         _tbm_surface_mutex_unlock();
1299
1300         return width;
1301 }
1302
1303 unsigned int
1304 tbm_surface_internal_get_height(tbm_surface_h surface)
1305 {
1306         struct _tbm_surface *surf;
1307         unsigned int height;
1308
1309         _tbm_surface_mutex_lock();
1310
1311         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1312
1313         surf = (struct _tbm_surface *)surface;
1314         height = surf->info.height;
1315
1316         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1317
1318         _tbm_surface_mutex_unlock();
1319
1320         return height;
1321
1322 }
1323
1324 tbm_format
1325 tbm_surface_internal_get_format(tbm_surface_h surface)
1326 {
1327         struct _tbm_surface *surf;
1328         tbm_format format;
1329
1330         _tbm_surface_mutex_lock();
1331
1332         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1333
1334         surf = (struct _tbm_surface *)surface;
1335         format = surf->info.format;
1336
1337         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1338
1339         _tbm_surface_mutex_unlock();
1340
1341         return format;
1342 }
1343
1344 int
1345 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1346 {
1347         struct _tbm_surface *surf;
1348         int bo_idx;
1349
1350         _tbm_surface_mutex_lock();
1351
1352         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1353         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1354
1355         surf = (struct _tbm_surface *)surface;
1356         bo_idx = surf->planes_bo_idx[plane_idx];
1357
1358         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1359
1360         _tbm_surface_mutex_unlock();
1361
1362         return bo_idx;
1363 }
1364
1365 int
1366 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1367                                    tbm_data_free data_free_func)
1368 {
1369         tbm_user_data *data;
1370
1371         _tbm_surface_mutex_lock();
1372
1373         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1374
1375         /* check if the data according to the key exist if so, return false. */
1376         data = user_data_lookup(&surface->user_data_list, key);
1377         if (data) {
1378                 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1379                 _tbm_surface_mutex_unlock();
1380                 return 0;
1381         }
1382
1383         data = user_data_create(key, data_free_func);
1384         if (!data) {
1385                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1386                 _tbm_surface_mutex_unlock();
1387                 return 0;
1388         }
1389
1390         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1391
1392         LIST_ADD(&data->item_link, &surface->user_data_list);
1393
1394         _tbm_surface_mutex_unlock();
1395
1396         return 1;
1397 }
1398
1399 int
1400 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1401                                    void *data)
1402 {
1403         tbm_user_data *old_data;
1404
1405         _tbm_surface_mutex_lock();
1406
1407         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1408
1409         old_data = user_data_lookup(&surface->user_data_list, key);
1410         if (!old_data) {
1411                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1412                 _tbm_surface_mutex_unlock();
1413                 return 0;
1414         }
1415
1416         if (old_data->data && old_data->free_func)
1417                 old_data->free_func(old_data->data);
1418
1419         old_data->data = data;
1420
1421         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1422
1423         _tbm_surface_mutex_unlock();
1424
1425         return 1;
1426 }
1427
1428 int
1429 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1430                                    void **data)
1431 {
1432         tbm_user_data *old_data;
1433
1434         _tbm_surface_mutex_lock();
1435
1436         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1437
1438         if (!data) {
1439                 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1440                 _tbm_surface_mutex_unlock();
1441                 return 0;
1442         }
1443         *data = NULL;
1444
1445         old_data = user_data_lookup(&surface->user_data_list, key);
1446         if (!old_data) {
1447                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1448                 _tbm_surface_mutex_unlock();
1449                 return 0;
1450         }
1451
1452         *data = old_data->data;
1453
1454         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1455
1456         _tbm_surface_mutex_unlock();
1457
1458         return 1;
1459 }
1460
1461 int
1462 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1463                                       unsigned long key)
1464 {
1465         tbm_user_data *old_data = (void *)0;
1466
1467         _tbm_surface_mutex_lock();
1468
1469         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1470
1471         old_data = user_data_lookup(&surface->user_data_list, key);
1472         if (!old_data) {
1473                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1474                 _tbm_surface_mutex_unlock();
1475                 return 0;
1476         }
1477
1478         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1479
1480         user_data_delete(old_data);
1481
1482         _tbm_surface_mutex_unlock();
1483
1484         return 1;
1485 }
1486
1487 /* LCOV_EXCL_START */
1488 unsigned int
1489 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1490 {
1491         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1492
1493         return surface->debug_pid;
1494 }
1495
1496 void
1497 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1498 {
1499         _tbm_surface_mutex_lock();
1500
1501         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1502
1503         surface->debug_pid = pid;
1504
1505         _tbm_surface_mutex_unlock();
1506 }
1507
1508 static tbm_surface_debug_data *
1509 _tbm_surface_internal_debug_data_create(char *key, char *value)
1510 {
1511         tbm_surface_debug_data *debug_data = NULL;
1512
1513         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1514         if (!debug_data)
1515                 return NULL;
1516
1517         if (key) debug_data->key = strdup(key);
1518         if (value) debug_data->value = strdup(value);
1519
1520         return debug_data;
1521 }
1522
1523 int
1524 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1525 {
1526         tbm_surface_debug_data *debug_data = NULL;
1527         tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1528         tbm_bufmgr bufmgr = NULL;
1529
1530         _tbm_surface_mutex_lock();
1531
1532         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1533         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1534
1535         bufmgr = surface->bufmgr;
1536
1537         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1538
1539         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1540                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1541                         if (old_data) {
1542                                 if (!strcmp(old_data->key, key)) {
1543                                         if (old_data->value && value && !strncmp(old_data->value, value, strlen(old_data->value))) {
1544                                                 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) Already exist key(%s) and value(%s)!\n", surface, key, value);
1545                                                 goto add_debug_key_list;
1546                                         }
1547
1548                                         if (old_data->value)
1549                                                 free(old_data->value);
1550
1551                                         if (value)
1552                                                 old_data->value = strdup(value);
1553                                         else
1554                                                 old_data->value = NULL;
1555
1556                                         goto add_debug_key_list;
1557                                 }
1558                         }
1559                 }
1560         }
1561
1562         debug_data = _tbm_surface_internal_debug_data_create(key, value);
1563         if (!debug_data) {
1564                 TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1565                 _tbm_surface_mutex_unlock();
1566                 return 0;
1567         }
1568
1569         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1570
1571         LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1572
1573 add_debug_key_list:
1574         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1575                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1576                         if (!strcmp(old_data->key, key)) {
1577                                 _tbm_surface_mutex_unlock();
1578                                 return 1;
1579                         }
1580                 }
1581         }
1582
1583         debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1584         LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1585
1586         _tbm_surface_mutex_unlock();
1587
1588         return 1;
1589 }
1590
1591 char *
1592 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1593 {
1594         tbm_surface_debug_data *old_data = NULL;
1595
1596         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1597
1598         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1599                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1600                         if (!strcmp(old_data->key, key))
1601                                 return old_data->value;
1602                 }
1603         }
1604
1605         return NULL;
1606 }
1607
1608 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1609 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1610
1611 struct _tbm_surface_dump_buf_info {
1612         int index;
1613         tbm_bo bo;
1614         int size;
1615         int dirty;
1616         int dirty_shm;
1617         int shm_stride;
1618         int shm_h;
1619         char name[1024];
1620
1621         tbm_surface_info_s info;
1622
1623         struct list_head link;
1624 };
1625
1626 struct _tbm_surface_dump_info {
1627         char *path;  // copy???
1628         int dump_max;
1629         int count;
1630         struct list_head *link;
1631         struct list_head surface_list; /* link of surface */
1632 };
1633
1634 static tbm_surface_dump_info *g_dump_info = NULL;
1635 static const char *dump_postfix[2] = {"png", "yuv"};
1636 static double scale_factor;
1637
1638 static void
1639 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1640                                 void *data2, int size2, void *data3, int size3)
1641 {
1642         FILE *fp;
1643         unsigned int *blocks;
1644
1645         if (_tbm_surface_check_file_is_symbolic_link(file))
1646                 TBM_ERR("%s is symbolic link\n", file);
1647
1648         fp = fopen(file, "w+");
1649         TBM_RETURN_IF_FAIL(fp != NULL);
1650
1651         blocks = (unsigned int *)data1;
1652         fwrite(blocks, 1, size1, fp);
1653
1654         if (size2 > 0) {
1655                 blocks = (unsigned int *)data2;
1656                 fwrite(blocks, 1, size2, fp);
1657         }
1658
1659         if (size3 > 0) {
1660                 blocks = (unsigned int *)data3;
1661                 fwrite(blocks, 1, size3, fp);
1662         }
1663
1664         fclose(fp);
1665 }
1666
1667 static void
1668 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int format)
1669 {
1670         unsigned int *blocks = (unsigned int *)data;
1671         FILE *fp;
1672         int pixel_size;
1673         png_bytep *row_pointers;
1674         int depth = 8, y;
1675
1676         if (_tbm_surface_check_file_is_symbolic_link(file))
1677                 TBM_ERR("%s is symbolic link\n", file);
1678
1679         fp = fopen(file, "wb");
1680         TBM_RETURN_IF_FAIL(fp != NULL);
1681
1682         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1683                                                         NULL, NULL, NULL);
1684         if (!pPngStruct) {
1685                 TBM_ERR("fail to create a png write structure.\n");
1686                 fclose(fp);
1687                 return;
1688         }
1689
1690         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1691         if (!pPngInfo) {
1692                 TBM_ERR("fail to create a png info structure.\n");
1693                 png_destroy_write_struct(&pPngStruct, NULL);
1694                 fclose(fp);
1695                 return;
1696         }
1697
1698         png_init_io(pPngStruct, fp);
1699         if (format == TBM_FORMAT_XRGB8888) {
1700                 pixel_size = 3;
1701                 png_set_IHDR(pPngStruct,
1702                                 pPngInfo,
1703                                 width,
1704                                 height,
1705                                 depth,
1706                                 PNG_COLOR_TYPE_RGB,
1707                                 PNG_INTERLACE_NONE,
1708                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1709         } else {
1710                 pixel_size = 4;
1711                 png_set_IHDR(pPngStruct,
1712                                 pPngInfo,
1713                                 width,
1714                                 height,
1715                                 depth,
1716                                 PNG_COLOR_TYPE_RGBA,
1717                                 PNG_INTERLACE_NONE,
1718                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1719         }
1720
1721         png_set_bgr(pPngStruct);
1722         png_write_info(pPngStruct, pPngInfo);
1723
1724         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1725         if (!row_pointers) {
1726                 TBM_ERR("fail to allocate the png row_pointers.\n");
1727                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1728                 fclose(fp);
1729                 return;
1730         }
1731
1732         for (y = 0; y < height; ++y) {
1733                 png_bytep row;
1734                 int x = 0;
1735
1736                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1737                 if (!row) {
1738                         TBM_ERR("fail to allocate the png row.\n");
1739                         for (x = 0; x < y; x++)
1740                                 png_free(pPngStruct, row_pointers[x]);
1741                         png_free(pPngStruct, row_pointers);
1742                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1743                         fclose(fp);
1744                         return;
1745                 }
1746                 row_pointers[y] = (png_bytep)row;
1747
1748                 for (x = 0; x < width; ++x) {
1749                         unsigned int curBlock = blocks[y * width + x];
1750
1751                         if (pixel_size == 3) { // XRGB8888
1752                                 row[x * pixel_size] = (curBlock & 0xFF);
1753                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1754                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1755                         } else { // ARGB8888
1756                                 row[x * pixel_size] = (curBlock & 0xFF);
1757                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1758                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1759                                 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1760                         }
1761                 }
1762         }
1763
1764         png_write_image(pPngStruct, row_pointers);
1765         png_write_end(pPngStruct, pPngInfo);
1766
1767         for (y = 0; y < height; y++)
1768                 png_free(pPngStruct, row_pointers[y]);
1769         png_free(pPngStruct, row_pointers);
1770
1771         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1772
1773         fclose(fp);
1774 }
1775
1776 void
1777 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1778 {
1779         TBM_RETURN_IF_FAIL(path != NULL);
1780         TBM_RETURN_IF_FAIL(w > 0);
1781         TBM_RETURN_IF_FAIL(h > 0);
1782         TBM_RETURN_IF_FAIL(count > 0);
1783
1784         tbm_surface_dump_buf_info *buf_info = NULL;
1785         tbm_surface_h tbm_surface;
1786         tbm_surface_info_s info;
1787         int buffer_size, i;
1788
1789         /* check running */
1790         if (g_dump_info) {
1791                 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
1792                 return;
1793         }
1794
1795         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1796         TBM_RETURN_IF_FAIL(g_dump_info);
1797
1798         LIST_INITHEAD(&g_dump_info->surface_list);
1799         g_dump_info->count = 0;
1800         g_dump_info->dump_max = count;
1801
1802         /* get buffer size */
1803         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1804         if (tbm_surface == NULL) {
1805                 TBM_ERR("tbm_surface_create fail\n");
1806                 free(g_dump_info);
1807                 g_dump_info = NULL;
1808                 return;
1809         }
1810
1811         if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
1812                 TBM_ERR("tbm_surface_get_info fail\n");
1813                 tbm_surface_destroy(tbm_surface);
1814                 free(g_dump_info);
1815                 g_dump_info = NULL;
1816                 return;
1817         }
1818         buffer_size = info.size;
1819         tbm_surface_destroy(tbm_surface);
1820
1821         /* create dump lists */
1822         for (i = 0; i < count; i++) {
1823                 tbm_bo bo = NULL;
1824
1825                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1826                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1827
1828                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1829                 if (bo == NULL) {
1830                         TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
1831                         free(buf_info);
1832                         goto fail;
1833                 }
1834
1835                 buf_info->index = i;
1836                 buf_info->bo = bo;
1837                 buf_info->size = buffer_size;
1838
1839                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1840         }
1841
1842         g_dump_info->path = path;
1843         g_dump_info->link = &g_dump_info->surface_list;
1844
1845         scale_factor = 0.0;
1846
1847         TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1848
1849         return;
1850
1851 fail:
1852         /* free resources */
1853         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1854                 tbm_surface_dump_buf_info *tmp;
1855
1856                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1857                         tbm_bo_unref(buf_info->bo);
1858                         LIST_DEL(&buf_info->link);
1859                         free(buf_info);
1860                 }
1861         }
1862
1863         TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
1864
1865         free(g_dump_info);
1866         g_dump_info = NULL;
1867
1868         return;
1869 }
1870
1871 void
1872 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
1873 {
1874         if (scale > 0.0) {
1875                 w *= scale;
1876                 h *= scale;
1877         }
1878
1879         tbm_surface_internal_dump_start(path, w, h, count);
1880         scale_factor = scale;
1881 }
1882
1883 void
1884 tbm_surface_internal_dump_end(void)
1885 {
1886         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1887         tbm_bo_handle bo_handle;
1888
1889         if (!g_dump_info)
1890                 return;
1891
1892         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1893                 free(g_dump_info);
1894                 g_dump_info = NULL;
1895                 return;
1896         }
1897
1898         /* make files */
1899         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1900                 char file[2048];
1901
1902                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1903                 if (bo_handle.ptr == NULL) {
1904                         tbm_bo_unref(buf_info->bo);
1905                         LIST_DEL(&buf_info->link);
1906                         free(buf_info);
1907                         continue;
1908                 }
1909
1910                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1911                 TBM_INFO("Dump File.. %s generated.\n", file);
1912
1913                 if (buf_info->dirty) {
1914                         void *ptr1 = NULL, *ptr2 = NULL;
1915
1916                         switch (buf_info->info.format) {
1917                         case TBM_FORMAT_ARGB8888:
1918                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1919                                                         buf_info->info.planes[0].stride >> 2,
1920                                                         buf_info->info.height, TBM_FORMAT_ARGB8888);
1921                                 break;
1922                         case TBM_FORMAT_XRGB8888:
1923                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1924                                                         buf_info->info.planes[0].stride >> 2,
1925                                                         buf_info->info.height, TBM_FORMAT_XRGB8888);
1926                                 break;
1927                         case TBM_FORMAT_YVU420:
1928                         case TBM_FORMAT_YUV420:
1929                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1930                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1931                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1932                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1933                                                         ptr1,
1934                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1935                                                         ptr2,
1936                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1937                                 break;
1938                         case TBM_FORMAT_NV12:
1939                         case TBM_FORMAT_NV21:
1940                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1941                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1942                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1943                                                         ptr1,
1944                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1945                                                         NULL, 0);
1946                                 break;
1947                         case TBM_FORMAT_YUYV:
1948                         case TBM_FORMAT_UYVY:
1949                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1950                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1951                                                         NULL, 0, NULL, 0);
1952                                 break;
1953                         default:
1954                                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1955                                 break;
1956                         }
1957                 } else if (buf_info->dirty_shm)
1958                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1959                                                         buf_info->shm_stride >> 2,
1960                                                         buf_info->shm_h, 0);
1961
1962                 tbm_bo_unmap(buf_info->bo);
1963                 tbm_bo_unref(buf_info->bo);
1964                 LIST_DEL(&buf_info->link);
1965                 free(buf_info);
1966         }
1967
1968         free(g_dump_info);
1969         g_dump_info = NULL;
1970
1971         TBM_INFO("Dump End..\n");
1972 }
1973
1974 static pixman_format_code_t
1975 _tbm_surface_internal_pixman_format_get(tbm_format format)
1976 {
1977         switch (format) {
1978         case TBM_FORMAT_ARGB8888:
1979                 return PIXMAN_a8r8g8b8;
1980         case TBM_FORMAT_XRGB8888:
1981                 return PIXMAN_x8r8g8b8;
1982         default:
1983                 return 0;
1984         }
1985
1986         return 0;
1987 }
1988
1989 /**
1990  * This function supports only if a buffer has below formats.
1991  * - TBM_FORMAT_ARGB8888
1992  * - TBM_FORMAT_XRGB8888
1993  */
1994 static tbm_surface_error_e
1995 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
1996                                                                    int format, int src_stride, int src_w, int src_h,
1997                                                                    int dst_stride, int dst_w, int dst_h)
1998 {
1999         pixman_image_t *src_img = NULL, *dst_img = NULL;
2000         pixman_format_code_t pixman_format;
2001         pixman_transform_t t;
2002         struct pixman_f_transform ft;
2003         double scale_x, scale_y;
2004
2005         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2006         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2007
2008         pixman_format = _tbm_surface_internal_pixman_format_get(format);
2009         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2010
2011         /* src */
2012         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2013                                                                            (uint32_t*)src_ptr, src_stride);
2014         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2015
2016         /* dst */
2017         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2018                                                                            (uint32_t*)dst_ptr, dst_stride);
2019         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2020
2021         pixman_f_transform_init_identity(&ft);
2022
2023         scale_x = (double)src_w / dst_w;
2024         scale_y = (double)src_h / dst_h;
2025
2026         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2027         pixman_f_transform_translate(&ft, NULL, 0, 0);
2028         pixman_transform_from_pixman_f_transform(&t, &ft);
2029         pixman_image_set_transform(src_img, &t);
2030
2031         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2032                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
2033
2034         pixman_image_unref(src_img);
2035         pixman_image_unref(dst_img);
2036
2037         return TBM_SURFACE_ERROR_NONE;
2038
2039 cant_convert:
2040         if (src_img)
2041                 pixman_image_unref(src_img);
2042
2043         return TBM_SURFACE_ERROR_INVALID_OPERATION;
2044 }
2045
2046 #define MAX_BOS         4       // This value is came from bos[4] in struct _tbm_surface
2047 #define KEY_LEN         5       // "_XXXX"
2048 #define KEYS_LEN        KEY_LEN * MAX_BOS
2049
2050 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2051 {
2052         char *keys, temp_key[KEY_LEN + 1];
2053         struct _tbm_surface *surf;
2054         int i, num_bos;
2055         tbm_bo bo;
2056
2057         _tbm_surface_mutex_lock();
2058
2059         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2060
2061         surf = (struct _tbm_surface *)surface;
2062
2063         num_bos = surf->num_bos;
2064         if (num_bos > MAX_BOS)
2065                 num_bos = MAX_BOS;
2066
2067         keys = calloc(KEYS_LEN + 1, sizeof(char));
2068         if (!keys) {
2069                 TBM_ERR("Failed to alloc memory");
2070                 _tbm_surface_mutex_unlock();
2071                 return NULL;
2072         }
2073
2074         for (i = 0; i < num_bos; i++) {
2075                 memset(temp_key, 0x00, KEY_LEN + 1);
2076                 bo = surf->bos[i];
2077                 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2078                 strncat(keys, temp_key, KEY_LEN);
2079         }
2080
2081         _tbm_surface_mutex_unlock();
2082
2083         return keys;
2084 }
2085
2086 static void _tbm_surface_internal_put_keys(char *keys)
2087 {
2088         if (keys)
2089                 free(keys);
2090 }
2091
2092 void
2093 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2094 {
2095         TBM_RETURN_IF_FAIL(surface != NULL);
2096         TBM_RETURN_IF_FAIL(type != NULL);
2097
2098         tbm_surface_dump_buf_info *buf_info;
2099         struct list_head *next_link;
2100         tbm_surface_info_s info;
2101         tbm_bo_handle bo_handle;
2102         const char *postfix;
2103         const char *format = NULL;
2104         char *keys;
2105         int ret;
2106
2107         if (!g_dump_info)
2108                 return;
2109
2110         next_link = g_dump_info->link->next;
2111         TBM_RETURN_IF_FAIL(next_link != NULL);
2112
2113         if (next_link == &g_dump_info->surface_list) {
2114                 next_link = next_link->next;
2115                 TBM_RETURN_IF_FAIL(next_link != NULL);
2116         }
2117
2118         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2119         TBM_RETURN_IF_FAIL(buf_info != NULL);
2120
2121         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2122         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2123
2124         if (scale_factor > 0.0) {
2125                 const int bpp = 4;
2126
2127                 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
2128                         TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2129                                           _tbm_surface_internal_format_to_str(info.format));
2130                         tbm_surface_unmap(surface);
2131                         return;
2132                 }
2133
2134                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2135
2136                 buf_info->info.width = info.width * scale_factor;
2137                 buf_info->info.height = info.height * scale_factor;
2138                 buf_info->info.format = info.format;
2139                 buf_info->info.bpp = tbm_surface_internal_get_bpp(buf_info->info.format);
2140                 buf_info->info.num_planes = 1;
2141                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2142                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2143
2144                 if (buf_info->info.size > buf_info->size) {
2145                         TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2146                                         buf_info->info.size, buf_info->size);
2147                         tbm_surface_unmap(surface);
2148                         return;
2149                 }
2150         } else {
2151                 if (info.size > buf_info->size) {
2152                         TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2153                                         info.size, buf_info->size);
2154                         tbm_surface_unmap(surface);
2155                         return;
2156                 }
2157
2158                 /* make the file information */
2159                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2160         }
2161
2162         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) {
2163                 postfix = dump_postfix[0];
2164                 format = _tbm_surface_internal_format_to_str(info.format);
2165         } else
2166                 postfix = dump_postfix[1];
2167
2168         keys = _tbm_surface_internal_get_keys(surface);
2169         if (!keys) {
2170                 TBM_ERR("fail to get keys");
2171                 tbm_surface_unmap(surface);
2172                 return;
2173         }
2174
2175         /* dump */
2176         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2177         if (!bo_handle.ptr) {
2178                 TBM_ERR("fail to map bo");
2179                 _tbm_surface_internal_put_keys(keys);
2180                 tbm_surface_unmap(surface);
2181                 return;
2182         }
2183         memset(bo_handle.ptr, 0x00, buf_info->size);
2184
2185         switch (info.format) {
2186         case TBM_FORMAT_ARGB8888:
2187         case TBM_FORMAT_XRGB8888:
2188                 snprintf(buf_info->name, sizeof(buf_info->name),
2189                                 "%10.3f_%03d%s_%p_%s-%s.%s",
2190                                  _tbm_surface_internal_get_time(),
2191                                  g_dump_info->count++, keys, surface, format, type, postfix);
2192
2193                 if (scale_factor > 0.0) {
2194                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2195                                                                                                          bo_handle.ptr,
2196                                                                                                          buf_info->info.format,
2197                                                                                                          info.planes[0].stride,
2198                                                                                                          info.width, info.height,
2199                                                                                                          buf_info->info.planes[0].stride,
2200                                                                                                          buf_info->info.width,
2201                                                                                                          buf_info->info.height);
2202                         if (ret != TBM_SURFACE_ERROR_NONE) {
2203                                 TBM_ERR("fail to scale buffer");
2204                                 tbm_bo_unmap(buf_info->bo);
2205                                 _tbm_surface_internal_put_keys(keys);
2206                                 tbm_surface_unmap(surface);
2207                                 return;
2208                         }
2209                 } else
2210                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2211                 break;
2212         case TBM_FORMAT_YVU420:
2213         case TBM_FORMAT_YUV420:
2214                 snprintf(buf_info->name, sizeof(buf_info->name),
2215                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2216                                  _tbm_surface_internal_get_time(),
2217                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2218                                 info.height, FOURCC_STR(info.format), postfix);
2219                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2220                 bo_handle.ptr += info.planes[0].stride * info.height;
2221                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2222                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2223                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2224                 break;
2225         case TBM_FORMAT_NV12:
2226         case TBM_FORMAT_NV21:
2227                 snprintf(buf_info->name, sizeof(buf_info->name),
2228                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2229                                  _tbm_surface_internal_get_time(),
2230                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2231                                 info.height, FOURCC_STR(info.format), postfix);
2232                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2233                 bo_handle.ptr += info.planes[0].stride * info.height;
2234                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2235                 break;
2236         case TBM_FORMAT_YUYV:
2237         case TBM_FORMAT_UYVY:
2238                 snprintf(buf_info->name, sizeof(buf_info->name),
2239                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2240                                  _tbm_surface_internal_get_time(),
2241                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2242                                 info.height, FOURCC_STR(info.format), postfix);
2243                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2244                 break;
2245         default:
2246                 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2247                 tbm_bo_unmap(buf_info->bo);
2248                 _tbm_surface_internal_put_keys(keys);
2249                 tbm_surface_unmap(surface);
2250                 return;
2251         }
2252
2253         tbm_bo_unmap(buf_info->bo);
2254
2255         _tbm_surface_internal_put_keys(keys);
2256
2257         tbm_surface_unmap(surface);
2258
2259         buf_info->dirty = 1;
2260         buf_info->dirty_shm = 0;
2261
2262         if (g_dump_info->count == 1000)
2263                 g_dump_info->count = 0;
2264
2265         g_dump_info->link = next_link;
2266
2267         TBM_INFO("Dump %s \n", buf_info->name);
2268 }
2269
2270 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2271                                                 const char *type)
2272 {
2273         TBM_RETURN_IF_FAIL(ptr != NULL);
2274         TBM_RETURN_IF_FAIL(w > 0);
2275         TBM_RETURN_IF_FAIL(h > 0);
2276         TBM_RETURN_IF_FAIL(stride > 0);
2277         TBM_RETURN_IF_FAIL(type != NULL);
2278
2279         tbm_surface_dump_buf_info *buf_info;
2280         struct list_head *next_link;
2281         tbm_bo_handle bo_handle;
2282         int ret, size, dw = 0, dh = 0, dstride = 0;
2283
2284         if (!g_dump_info)
2285                 return;
2286
2287         next_link = g_dump_info->link->next;
2288         TBM_RETURN_IF_FAIL(next_link != NULL);
2289
2290         if (next_link == &g_dump_info->surface_list) {
2291                 next_link = next_link->next;
2292                 TBM_RETURN_IF_FAIL(next_link != NULL);
2293         }
2294
2295         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2296         TBM_RETURN_IF_FAIL(buf_info != NULL);
2297
2298         if (scale_factor > 0.0) {
2299                 const int bpp = 4;
2300
2301                 dw = w * scale_factor;
2302                 dh = h * scale_factor;
2303                 dstride = dw * bpp;
2304                 size = dstride * dh;
2305         } else
2306                 size = stride * h;
2307
2308         if (size > buf_info->size) {
2309                 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2310                                 size, buf_info->size);
2311                 return;
2312         }
2313
2314         /* dump */
2315         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2316         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2317
2318         memset(bo_handle.ptr, 0x00, buf_info->size);
2319         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2320
2321         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2322                          _tbm_surface_internal_get_time(),
2323                          g_dump_info->count++, type, dump_postfix[0]);
2324         if (scale_factor > 0.0) {
2325                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2326                                                                                                  TBM_FORMAT_ARGB8888, stride,
2327                                                                                                  w, h, dstride, dw, dh);
2328                 if (ret != TBM_SURFACE_ERROR_NONE) {
2329                         TBM_ERR("fail to scale buffer");
2330                         tbm_bo_unmap(buf_info->bo);
2331                         return;
2332                 }
2333                 buf_info->shm_stride = dstride;
2334                 buf_info->shm_h = dh;
2335         } else {
2336                 memcpy(bo_handle.ptr, ptr, size);
2337                 buf_info->shm_stride = stride;
2338                 buf_info->shm_h = h;
2339         }
2340
2341         tbm_bo_unmap(buf_info->bo);
2342
2343         buf_info->dirty = 0;
2344         buf_info->dirty_shm = 1;
2345
2346         if (g_dump_info->count == 1000)
2347                 g_dump_info->count = 0;
2348
2349         g_dump_info->link = next_link;
2350
2351         TBM_INFO("Dump %s \n", buf_info->name);
2352 }
2353
2354 int
2355 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2356 {
2357         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2358         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2359         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2360
2361         tbm_surface_info_s info;
2362         const char *postfix;
2363         int ret;
2364         char file[1024];
2365
2366         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2367         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2368
2369         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2370                 postfix = dump_postfix[0];
2371         else
2372                 postfix = dump_postfix[1];
2373
2374         if (strcmp(postfix, type)) {
2375                 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2376                 tbm_surface_unmap(surface);
2377                 return 0;
2378         }
2379
2380         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2381
2382         if (!access(file, 0)) {
2383                 TBM_ERR("can't capture  buffer, exist file %s", file);
2384                 tbm_surface_unmap(surface);
2385                 return 0;
2386         }
2387
2388         switch (info.format) {
2389         case TBM_FORMAT_ARGB8888:
2390                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2391                                                         info.planes[0].stride >> 2,
2392                                                         info.height, TBM_FORMAT_ARGB8888);
2393                 break;
2394         case TBM_FORMAT_XRGB8888:
2395                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2396                                                         info.planes[0].stride >> 2,
2397                                                         info.height, TBM_FORMAT_XRGB8888);
2398                 break;
2399         case TBM_FORMAT_YVU420:
2400         case TBM_FORMAT_YUV420:
2401                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2402                                 info.planes[0].stride * info.height,
2403                                 info.planes[1].ptr,
2404                                 info.planes[1].stride * (info.height >> 1),
2405                                 info.planes[2].ptr,
2406                                 info.planes[2].stride * (info.height >> 1));
2407                 break;
2408         case TBM_FORMAT_NV12:
2409         case TBM_FORMAT_NV21:
2410                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2411                                         info.planes[0].stride * info.height,
2412                                         info.planes[1].ptr,
2413                                         info.planes[1].stride * (info.height >> 1),
2414                                         NULL, 0);
2415                 break;
2416         case TBM_FORMAT_YUYV:
2417         case TBM_FORMAT_UYVY:
2418                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2419                                         info.planes[0].stride * info.height,
2420                                         NULL, 0, NULL, 0);
2421                 break;
2422         default:
2423                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2424                 tbm_surface_unmap(surface);
2425                 return 0;
2426         }
2427
2428         tbm_surface_unmap(surface);
2429
2430         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2431
2432         return 1;
2433 }
2434
2435 int
2436 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2437                                                 const char *path, const char *name, const char *type)
2438 {
2439         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2440         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2441         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2442         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2443         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2444         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2445
2446         char file[1024];
2447
2448         if (strcmp(dump_postfix[0], type)) {
2449                 TBM_ERR("Not supported type:%s'", type);
2450                 return 0;
2451         }
2452
2453         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2454
2455         if (!access(file, 0)) {
2456                 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2457                 return 0;
2458         }
2459
2460         _tbm_surface_internal_dump_file_png(file, ptr, w, h, 0);
2461
2462         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2463
2464         return 1;
2465 }
2466 /*LCOV_EXCL_STOP*/