add size checking at dump
[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         char name[1024];
1157
1158         tbm_surface_info_s info;
1159
1160         struct list_head link;
1161 };
1162
1163 struct _tbm_surface_dump_info
1164 {
1165         char *path;  // copy???
1166         int dump_max;
1167         int count;
1168         struct list_head *link;
1169         struct list_head surface_list; /* link of surface */
1170 };
1171
1172 static tbm_surface_dump_info *g_dump_info = NULL;
1173 static const char *dump_postfix[2] = {"png", "yuv"};
1174
1175 static void
1176 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1, void *data2,
1177                      int size2, void *data3, int size3)
1178 {
1179         unsigned int *blocks;
1180         FILE *fp = fopen(file, "w+");
1181         TBM_RETURN_IF_FAIL(fp != NULL);
1182
1183         blocks = (unsigned int *)data1;
1184         fwrite(blocks, 1, size1, fp);
1185
1186         if (size2 > 0) {
1187                 blocks = (unsigned int *)data2;
1188                 fwrite(blocks, 1, size2, fp);
1189         }
1190
1191         if (size3 > 0) {
1192                 blocks = (unsigned int *)data3;
1193                 fwrite(blocks, 1, size3, fp);
1194         }
1195
1196         fclose(fp);
1197 }
1198
1199 static void
1200 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width,
1201                      int height)
1202 {
1203         FILE *fp = fopen(file, "wb");
1204         TBM_RETURN_IF_FAIL(fp != NULL);
1205         int depth = 8;
1206
1207         png_structp pPngStruct =
1208                 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1209         if (!pPngStruct) {
1210                 fclose(fp);
1211                 return;
1212         }
1213
1214         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1215         if (!pPngInfo) {
1216                 png_destroy_write_struct(&pPngStruct, NULL);
1217                 fclose(fp);
1218                 return;
1219         }
1220
1221         png_init_io(pPngStruct, fp);
1222         png_set_IHDR(pPngStruct,
1223                      pPngInfo,
1224                      width,
1225                      height,
1226                      depth,
1227                      PNG_COLOR_TYPE_RGBA,
1228                      PNG_INTERLACE_NONE,
1229                      PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1230
1231         png_set_bgr(pPngStruct);
1232         png_write_info(pPngStruct, pPngInfo);
1233
1234         const int pixel_size = 4;       // RGBA
1235         png_bytep *row_pointers =
1236                 png_malloc(pPngStruct, height * sizeof(png_byte *));
1237
1238         unsigned int *blocks = (unsigned int *)data;
1239         int y = 0;
1240         int x = 0;
1241
1242         for (; y < height; ++y) {
1243                 png_bytep row =
1244                         png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1245                 row_pointers[y] = (png_bytep)row;
1246                 for (x = 0; x < width; ++x) {
1247                         unsigned int curBlock = blocks[y * width + x];
1248                         row[x * pixel_size] = (curBlock & 0xFF);
1249                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1250                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1251                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1252                 }
1253         }
1254
1255         png_write_image(pPngStruct, row_pointers);
1256         png_write_end(pPngStruct, pPngInfo);
1257
1258         for (y = 0; y < height; y++)
1259                 png_free(pPngStruct, row_pointers[y]);
1260         png_free(pPngStruct, row_pointers);
1261
1262         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1263
1264         fclose(fp);
1265 }
1266
1267 void
1268 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1269 {
1270         TBM_RETURN_IF_FAIL(path != NULL);
1271         TBM_RETURN_IF_FAIL(w > 0);
1272         TBM_RETURN_IF_FAIL(h > 0);
1273         TBM_RETURN_IF_FAIL(count > 0);
1274
1275         tbm_surface_dump_buf_info *buf_info = NULL;
1276         tbm_surface_dump_buf_info *tmp;
1277         tbm_bo bo = NULL;
1278         int i;
1279         int buffer_size;
1280         tbm_surface_h tbm_surface;
1281         tbm_surface_info_s info;
1282         tbm_surface_error_e err;
1283
1284         /* check running */
1285         if (g_dump_info) {
1286                 TBM_LOG("[libtbm:%d] "
1287                         "waring: %s:%d already running the tbm_surface_internal_dump.\n",
1288                         getpid(), __func__, __LINE__);
1289                 return;
1290         }
1291
1292         g_dump_info = calloc(1, sizeof (struct _tbm_surface_dump_info));
1293         TBM_RETURN_IF_FAIL(g_dump_info);
1294
1295         LIST_INITHEAD(&g_dump_info->surface_list);
1296         g_dump_info->count = 0;
1297         g_dump_info->dump_max = count;
1298
1299         /* get buffer size */
1300         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1301         if (tbm_surface == NULL) {
1302                 TBM_LOG("tbm_surface_create fail\n");
1303                 free(g_dump_info);
1304                 g_dump_info = NULL;
1305                 return;
1306         }
1307         err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
1308         if (err != TBM_SURFACE_ERROR_NONE) {
1309                 TBM_LOG("tbm_surface_map fail\n");
1310                 tbm_surface_destroy(tbm_surface);
1311                 free(g_dump_info);
1312                 g_dump_info = NULL;
1313                 return;
1314         }
1315         buffer_size = info.planes[0].stride * h;
1316         tbm_surface_unmap(tbm_surface);
1317         tbm_surface_destroy(tbm_surface);
1318
1319         /* create dump lists */
1320         for (i = 0; i < count; i++)     {
1321                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1322                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1323                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1324                 if (bo == NULL) {
1325                         free(buf_info);
1326                         goto fail;
1327                 }
1328
1329                 buf_info->index = i;
1330                 buf_info->bo = bo;
1331                 buf_info->size = buffer_size;
1332
1333                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1334         }
1335
1336         g_dump_info->path = path;
1337         g_dump_info->link = &g_dump_info->surface_list;
1338
1339         TBM_LOG("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1340
1341         return;
1342 fail:
1343         /* free resources */
1344         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1345                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1346                         tbm_bo_unref(buf_info->bo);
1347                         free(buf_info);
1348                 }
1349         }
1350
1351         TBM_LOG("Dump Start fail.. path:%s\n", g_dump_info->path);
1352
1353         free(g_dump_info);
1354         g_dump_info = NULL;
1355
1356         return;
1357 }
1358
1359 void
1360 tbm_surface_internal_dump_end(void)
1361 {
1362         tbm_surface_dump_buf_info *buf_info, *tmp;
1363         tbm_bo_handle bo_handle;
1364
1365     if (!g_dump_info)
1366                 return;
1367
1368         /* make files */
1369         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1370                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1371                         if (buf_info->dirty) {
1372                                 char file[2048];
1373                                 void *ptr1 = NULL;
1374                                 void *ptr2 = NULL;
1375
1376                                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1377                                 if (bo_handle.ptr == NULL)
1378                                         continue;
1379
1380                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1381                                 TBM_LOG("Dump File.. %s generated.\n", file);
1382
1383                                 switch (buf_info->info.format) {
1384                                 case TBM_FORMAT_ARGB8888:
1385                                 case TBM_FORMAT_XRGB8888:
1386                                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1387                                                                                         buf_info->info.planes[0].stride >> 2, buf_info->info.height);
1388                                         break;
1389                                 case TBM_FORMAT_YVU420:
1390                                 case TBM_FORMAT_YUV420:
1391                                         ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1392                                         ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1393                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1394                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1395                                                                         ptr1,
1396                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1397                                                                         ptr2,
1398                                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1399                                         break;
1400                                 case TBM_FORMAT_NV12:
1401                                 case TBM_FORMAT_NV21:
1402                                         ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1403                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1404                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1405                                                                         ptr1,
1406                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1407                                                                         NULL, 0);
1408                                         break;
1409                                 case TBM_FORMAT_YUYV:
1410                                 case TBM_FORMAT_UYVY:
1411                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1412                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1413                                                                         NULL, 0, NULL, 0);
1414                                         break;
1415                                 default:
1416                                         TBM_LOG("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1417                                         tbm_bo_unmap(buf_info->bo);
1418                                         return;
1419                                 }
1420
1421                                 tbm_bo_unmap(buf_info->bo);
1422                         }
1423                 }
1424         }
1425
1426
1427         /* free resources */
1428         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1429                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1430                 tbm_bo_unref(buf_info->bo);
1431                         free(buf_info);
1432                 }
1433         }
1434
1435         free(g_dump_info);
1436         g_dump_info = NULL;
1437
1438         TBM_LOG("Dump End..\n");
1439 }
1440
1441 void
1442 tbm_internal_surface_dump_buffer(tbm_surface_h surface, const char *type)
1443 {
1444         TBM_RETURN_IF_FAIL(surface != NULL);
1445         TBM_RETURN_IF_FAIL(type != NULL);
1446
1447         tbm_surface_dump_buf_info *buf_info;
1448         tbm_surface_info_s info;
1449         struct list_head *next_link;
1450         tbm_bo_handle bo_handle;
1451         int ret;
1452         const char *postfix;
1453
1454     if (!g_dump_info)
1455                 return;
1456
1457         next_link = g_dump_info->link->next;
1458         TBM_RETURN_IF_FAIL(next_link != NULL);
1459
1460         if (next_link == &g_dump_info->surface_list) {
1461                 next_link = next_link->next;
1462                 TBM_RETURN_IF_FAIL(next_link != NULL);
1463         }
1464
1465         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1466         TBM_RETURN_IF_FAIL(buf_info != NULL);
1467
1468         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1469         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1470
1471         if (info.size > buf_info->size) {
1472                 TBM_LOG("Dump skip. surface over created buffer size(%d, %d)\n", info.size, buf_info->size);
1473                 tbm_surface_unmap(surface);
1474                 return;
1475         }
1476
1477         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1478                 postfix = dump_postfix[0];
1479         else
1480                 postfix = dump_postfix[1];
1481
1482         /* make the file information */
1483         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1484
1485         /* dump */
1486         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1487         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1488         memset(bo_handle.ptr, 0x00, buf_info->size);
1489
1490         switch (info.format) {
1491         case TBM_FORMAT_ARGB8888:
1492         case TBM_FORMAT_XRGB8888:
1493                 snprintf(buf_info->name, sizeof(buf_info->name), "%03d-%s.%s", g_dump_info->count++, type, postfix);
1494                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1495                 break;
1496         case TBM_FORMAT_YVU420:
1497         case TBM_FORMAT_YUV420:
1498                 snprintf(buf_info->name, sizeof(buf_info->name), "%03d-%s_%dx%d_%c%c%c%c.%s",
1499                                 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1500                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1501                 bo_handle.ptr += info.planes[0].stride * info.height;
1502                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1503                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1504                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1505                 break;
1506         case TBM_FORMAT_NV12:
1507         case TBM_FORMAT_NV21:
1508                 snprintf(buf_info->name, sizeof(buf_info->name), "%03d-%s_%dx%d_%c%c%c%c.%s",
1509                                 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1510                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1511                 bo_handle.ptr += info.planes[0].stride * info.height;
1512                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1513                 break;
1514         case TBM_FORMAT_YUYV:
1515         case TBM_FORMAT_UYVY:
1516                 snprintf(buf_info->name, sizeof(buf_info->name), "%03d-%s_%dx%d_%c%c%c%c.%s",
1517                                 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1518                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1519                 break;
1520         default:
1521                 TBM_LOG("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1522                 tbm_bo_unmap(buf_info->bo);
1523                 return;
1524         }
1525
1526         tbm_bo_unmap(buf_info->bo);
1527
1528         tbm_surface_unmap(surface);
1529
1530         buf_info->dirty = 1;
1531
1532         if (g_dump_info->count == 1000)
1533                 g_dump_info->count = 0;
1534
1535         g_dump_info->link = next_link;
1536
1537         TBM_LOG("Dump %s \n", buf_info->name);
1538 }
1539