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