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