Fixed implicit declaration of TBM_LOG
[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_E("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                         DBG("free user_data\n");
269                         user_data_delete(old_data);
270                 }
271         }
272
273         LIST_DEL(&surface->item_link);
274
275         free(surface);
276         surface = NULL;
277
278         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
279                 LIST_DELINIT(&bufmgr->surf_list);
280                 _deinit_surface_bufmgr();
281         }
282 }
283
284 int
285 tbm_surface_internal_is_valid(tbm_surface_h surface)
286 {
287         tbm_surface_h old_data = NULL, tmp = NULL;
288
289         if (surface == NULL || g_surface_bufmgr == NULL)
290                 return 0;
291
292         if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
293                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &g_surface_bufmgr->surf_list, item_link) {
294                         if (old_data == surface)
295                                 return 1;
296                 }
297         }
298         return 0;
299 }
300
301 int
302 tbm_surface_internal_query_supported_formats(uint32_t **formats,
303                 uint32_t *num)
304 {
305         struct _tbm_bufmgr *mgr;
306         int ret = 0;
307
308         _tbm_surface_mutex_lock();
309
310         if (!g_surface_bufmgr) {
311                 _init_surface_bufmgr();
312                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
313         }
314
315         mgr = g_surface_bufmgr;
316
317         if (!mgr->backend->surface_supported_format) {
318                 _tbm_surface_mutex_unlock();
319                 return 0;
320         }
321
322         ret = mgr->backend->surface_supported_format(formats, num);
323
324         _tbm_surface_mutex_unlock();
325
326         return ret;
327 }
328
329 int
330 tbm_surface_internal_get_num_planes(tbm_format format)
331 {
332         int num_planes = 0;
333
334         switch (format) {
335         case TBM_FORMAT_C8:
336         case TBM_FORMAT_RGB332:
337         case TBM_FORMAT_BGR233:
338         case TBM_FORMAT_XRGB4444:
339         case TBM_FORMAT_XBGR4444:
340         case TBM_FORMAT_RGBX4444:
341         case TBM_FORMAT_BGRX4444:
342         case TBM_FORMAT_ARGB4444:
343         case TBM_FORMAT_ABGR4444:
344         case TBM_FORMAT_RGBA4444:
345         case TBM_FORMAT_BGRA4444:
346         case TBM_FORMAT_XRGB1555:
347         case TBM_FORMAT_XBGR1555:
348         case TBM_FORMAT_RGBX5551:
349         case TBM_FORMAT_BGRX5551:
350         case TBM_FORMAT_ARGB1555:
351         case TBM_FORMAT_ABGR1555:
352         case TBM_FORMAT_RGBA5551:
353         case TBM_FORMAT_BGRA5551:
354         case TBM_FORMAT_RGB565:
355         case TBM_FORMAT_BGR565:
356         case TBM_FORMAT_RGB888:
357         case TBM_FORMAT_BGR888:
358         case TBM_FORMAT_XRGB8888:
359         case TBM_FORMAT_XBGR8888:
360         case TBM_FORMAT_RGBX8888:
361         case TBM_FORMAT_BGRX8888:
362         case TBM_FORMAT_ARGB8888:
363         case TBM_FORMAT_ABGR8888:
364         case TBM_FORMAT_RGBA8888:
365         case TBM_FORMAT_BGRA8888:
366         case TBM_FORMAT_XRGB2101010:
367         case TBM_FORMAT_XBGR2101010:
368         case TBM_FORMAT_RGBX1010102:
369         case TBM_FORMAT_BGRX1010102:
370         case TBM_FORMAT_ARGB2101010:
371         case TBM_FORMAT_ABGR2101010:
372         case TBM_FORMAT_RGBA1010102:
373         case TBM_FORMAT_BGRA1010102:
374         case TBM_FORMAT_YUYV:
375         case TBM_FORMAT_YVYU:
376         case TBM_FORMAT_UYVY:
377         case TBM_FORMAT_VYUY:
378         case TBM_FORMAT_AYUV:
379                 num_planes = 1;
380                 break;
381         case TBM_FORMAT_NV12:
382         case TBM_FORMAT_NV12MT:
383         case TBM_FORMAT_NV21:
384         case TBM_FORMAT_NV16:
385         case TBM_FORMAT_NV61:
386                 num_planes = 2;
387                 break;
388         case TBM_FORMAT_YUV410:
389         case TBM_FORMAT_YVU410:
390         case TBM_FORMAT_YUV411:
391         case TBM_FORMAT_YVU411:
392         case TBM_FORMAT_YUV420:
393         case TBM_FORMAT_YVU420:
394         case TBM_FORMAT_YUV422:
395         case TBM_FORMAT_YVU422:
396         case TBM_FORMAT_YUV444:
397         case TBM_FORMAT_YVU444:
398                 num_planes = 3;
399                 break;
400
401         default:
402                 break;
403         }
404
405         return num_planes;
406 }
407
408 int
409 tbm_surface_internal_get_bpp(tbm_format format)
410 {
411         int bpp = 0;
412
413         switch (format) {
414         case TBM_FORMAT_C8:
415         case TBM_FORMAT_RGB332:
416         case TBM_FORMAT_BGR233:
417                 bpp = 8;
418                 break;
419         case TBM_FORMAT_XRGB4444:
420         case TBM_FORMAT_XBGR4444:
421         case TBM_FORMAT_RGBX4444:
422         case TBM_FORMAT_BGRX4444:
423         case TBM_FORMAT_ARGB4444:
424         case TBM_FORMAT_ABGR4444:
425         case TBM_FORMAT_RGBA4444:
426         case TBM_FORMAT_BGRA4444:
427         case TBM_FORMAT_XRGB1555:
428         case TBM_FORMAT_XBGR1555:
429         case TBM_FORMAT_RGBX5551:
430         case TBM_FORMAT_BGRX5551:
431         case TBM_FORMAT_ARGB1555:
432         case TBM_FORMAT_ABGR1555:
433         case TBM_FORMAT_RGBA5551:
434         case TBM_FORMAT_BGRA5551:
435         case TBM_FORMAT_RGB565:
436         case TBM_FORMAT_BGR565:
437                 bpp = 16;
438                 break;
439         case TBM_FORMAT_RGB888:
440         case TBM_FORMAT_BGR888:
441                 bpp = 24;
442                 break;
443         case TBM_FORMAT_XRGB8888:
444         case TBM_FORMAT_XBGR8888:
445         case TBM_FORMAT_RGBX8888:
446         case TBM_FORMAT_BGRX8888:
447         case TBM_FORMAT_ARGB8888:
448         case TBM_FORMAT_ABGR8888:
449         case TBM_FORMAT_RGBA8888:
450         case TBM_FORMAT_BGRA8888:
451         case TBM_FORMAT_XRGB2101010:
452         case TBM_FORMAT_XBGR2101010:
453         case TBM_FORMAT_RGBX1010102:
454         case TBM_FORMAT_BGRX1010102:
455         case TBM_FORMAT_ARGB2101010:
456         case TBM_FORMAT_ABGR2101010:
457         case TBM_FORMAT_RGBA1010102:
458         case TBM_FORMAT_BGRA1010102:
459         case TBM_FORMAT_YUYV:
460         case TBM_FORMAT_YVYU:
461         case TBM_FORMAT_UYVY:
462         case TBM_FORMAT_VYUY:
463         case TBM_FORMAT_AYUV:
464                 bpp = 32;
465                 break;
466         case TBM_FORMAT_NV12:
467         case TBM_FORMAT_NV12MT:
468         case TBM_FORMAT_NV21:
469                 bpp = 12;
470                 break;
471         case TBM_FORMAT_NV16:
472         case TBM_FORMAT_NV61:
473                 bpp = 16;
474                 break;
475         case TBM_FORMAT_YUV410:
476         case TBM_FORMAT_YVU410:
477                 bpp = 9;
478                 break;
479         case TBM_FORMAT_YUV411:
480         case TBM_FORMAT_YVU411:
481         case TBM_FORMAT_YUV420:
482         case TBM_FORMAT_YVU420:
483                 bpp = 12;
484                 break;
485         case TBM_FORMAT_YUV422:
486         case TBM_FORMAT_YVU422:
487                 bpp = 16;
488                 break;
489         case TBM_FORMAT_YUV444:
490         case TBM_FORMAT_YVU444:
491                 bpp = 24;
492                 break;
493         default:
494                 break;
495         }
496
497         return bpp;
498 }
499
500 tbm_surface_h
501 tbm_surface_internal_create_with_flags(int width, int height,
502                                        int format, int flags)
503 {
504         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
505         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
506
507         struct _tbm_bufmgr *mgr;
508         struct _tbm_surface *surf = NULL;
509         uint32_t size = 0;
510         uint32_t offset = 0;
511         uint32_t stride = 0;
512         uint32_t bo_size = 0;
513         int bo_idx;
514         int i, j;
515
516         _tbm_surface_mutex_lock();
517
518         if (!g_surface_bufmgr) {
519                 _init_surface_bufmgr();
520                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
521         }
522
523         mgr = g_surface_bufmgr;
524         if (!TBM_BUFMGR_IS_VALID(mgr)) {
525                 _tbm_surface_mutex_unlock();
526                 return NULL;
527         }
528         surf = calloc(1, sizeof(struct _tbm_surface));
529         if (!surf) {
530                 _tbm_surface_mutex_unlock();
531                 return NULL;
532         }
533
534         surf->bufmgr = mgr;
535         surf->info.width = width;
536         surf->info.height = height;
537         surf->info.format = format;
538         surf->info.bpp = tbm_surface_internal_get_bpp(format);
539         surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
540         surf->refcnt = 1;
541
542         /* get size, stride and offset bo_idx */
543         for (i = 0; i < surf->info.num_planes; i++) {
544                 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride,
545                                                        &bo_idx);
546                 surf->info.planes[i].size = size;
547                 surf->info.planes[i].offset = offset;
548                 surf->info.planes[i].stride = stride;
549                 surf->planes_bo_idx[i] = bo_idx;
550         }
551
552         surf->num_bos = 1;
553
554         for (i = 0; i < surf->info.num_planes; i++) {
555                 surf->info.size += surf->info.planes[i].size;
556
557                 if (surf->num_bos -1 > surf->planes_bo_idx[i])
558                         surf->num_bos = surf->planes_bo_idx[i]++;
559         }
560
561         surf->flags = flags;
562
563         for (i = 0; i < surf->num_bos; i++) {
564                 bo_size = 0;
565                 for (j = 0; j < surf->info.num_planes; j++) {
566                         if (surf->planes_bo_idx[j] == i)
567                                 bo_size += surf->info.planes[j].size;
568                 }
569
570                 if (mgr->backend->surface_bo_alloc) {
571
572                         tbm_bo bo = NULL;
573                         void *bo_priv = NULL;
574
575                         bo = calloc(1, sizeof(struct _tbm_bo));
576                         if (!bo) {
577                                 TBM_LOG_E("fail to alloc bo struct\n");
578                                 goto alloc_fail;
579                         }
580
581                         bo->bufmgr = surf->bufmgr;
582
583                         pthread_mutex_lock(&surf->bufmgr->lock);
584
585                         bo_priv = mgr->backend->surface_bo_alloc (bo, width, height, format, flags, i);
586                         if (!bo_priv) {
587                                 TBM_LOG_E("fail to alloc bo priv\n");
588                                 free(bo);
589                                 pthread_mutex_unlock(&surf->bufmgr->lock);
590                                 goto alloc_fail;
591                         }
592
593                         bo->ref_cnt = 1;
594                         bo->flags = flags;
595                         bo->priv = bo_priv;
596
597                         LIST_INITHEAD(&bo->user_data_list);
598
599                         LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
600
601                         pthread_mutex_unlock(&surf->bufmgr->lock);
602
603                         surf->bos[i] = bo;
604
605                 } else {
606                         surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
607                 }
608
609                 if (!surf->bos[i]) {
610                         TBM_LOG_E("fail to alloc bo idx:%d\n", i);
611                         goto alloc_fail;
612                 }
613
614                 _tbm_bo_set_surface(surf->bos[i], surf);
615
616         }
617
618         LIST_INITHEAD(&surf->user_data_list);
619
620         LIST_ADD(&surf->item_link, &mgr->surf_list);
621
622         _tbm_surface_mutex_unlock();
623
624         return surf;
625
626 alloc_fail:
627         for (j = 0; j < i; j++) {
628                 if (surf->bos[j])
629                         tbm_bo_unref(surf->bos[j]);
630         }
631
632         free(surf);
633         surf = NULL;
634
635         if (LIST_IS_EMPTY(&mgr->surf_list)) {
636                 LIST_DELINIT(&mgr->surf_list);
637                 _deinit_surface_bufmgr();
638         }
639
640         _tbm_surface_mutex_unlock();
641         return NULL;
642 }
643
644 tbm_surface_h
645 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
646                                      tbm_bo *bos, int num)
647 {
648         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
649         TBM_RETURN_VAL_IF_FAIL(info, NULL);
650         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
651
652         struct _tbm_bufmgr *mgr;
653         struct _tbm_surface *surf = NULL;
654         int i;
655
656         _tbm_surface_mutex_lock();
657
658         if (!g_surface_bufmgr) {
659                 _init_surface_bufmgr();
660                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
661         }
662
663         mgr = g_surface_bufmgr;
664         if (!TBM_BUFMGR_IS_VALID(mgr)) {
665                 _tbm_surface_mutex_unlock();
666                 return NULL;
667         }
668
669         surf = calloc(1, sizeof(struct _tbm_surface));
670         if (!surf) {
671                 _tbm_surface_mutex_unlock();
672                 return NULL;
673         }
674
675         surf->bufmgr = mgr;
676         surf->info.width = info->width;
677         surf->info.height = info->height;
678         surf->info.format = info->format;
679         surf->info.bpp = info->bpp;
680         surf->info.num_planes = info->num_planes;
681         surf->refcnt = 1;
682
683         /* get size, stride and offset */
684         for (i = 0; i < info->num_planes; i++) {
685                 surf->info.planes[i].offset = info->planes[i].offset;
686                 surf->info.planes[i].stride = info->planes[i].stride;
687
688                 if (info->planes[i].size > 0)
689                         surf->info.planes[i].size = info->planes[i].size;
690                 else
691                         surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
692
693                 if (num == 1)
694                         surf->planes_bo_idx[i] = 0;
695                 else
696                         surf->planes_bo_idx[i] = i;
697         }
698
699         if (info->size > 0) {
700                 surf->info.size = info->size;
701         } else {
702                 surf->info.size = 0;
703                 for (i = 0; i < info->num_planes; i++)
704                         surf->info.size += surf->info.planes[i].size;
705         }
706
707         surf->flags = TBM_BO_DEFAULT;
708
709         /* create only one bo */
710         surf->num_bos = num;
711         for (i = 0; i < num; i++) {
712                 if (bos[i] == NULL)
713                         goto bail1;
714
715                 surf->bos[i] = tbm_bo_ref(bos[i]);
716                 _tbm_bo_set_surface(bos[i], surf);
717         }
718
719         LIST_INITHEAD(&surf->user_data_list);
720
721         LIST_ADD(&surf->item_link, &mgr->surf_list);
722
723         _tbm_surface_mutex_unlock();
724
725         return surf;
726 bail1:
727         for (i = 0; i < num; i++) {
728                 if (surf->bos[i]) {
729                         tbm_bo_unref(surf->bos[i]);
730                         surf->bos[i] = NULL;
731                 }
732         }
733
734         free(surf);
735         surf = NULL;
736
737         if (LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
738                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
739                 _deinit_surface_bufmgr();
740         }
741
742         _tbm_surface_mutex_unlock();
743
744         return NULL;
745 }
746
747 void
748 tbm_surface_internal_destroy(tbm_surface_h surface)
749 {
750         if (!tbm_surface_internal_is_valid(surface))
751                 return;
752
753         _tbm_surface_mutex_lock();
754
755         surface->refcnt--;
756
757         if (surface->refcnt > 0) {
758                 _tbm_surface_mutex_unlock();
759                 return;
760         }
761
762         if (surface->refcnt == 0)
763                 _tbm_surface_internal_destroy(surface);
764
765         _tbm_surface_mutex_unlock();
766 }
767
768 void
769 tbm_surface_internal_ref(tbm_surface_h surface)
770 {
771         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
772
773         _tbm_surface_mutex_lock();
774
775         surface->refcnt++;
776
777         _tbm_surface_mutex_unlock();
778 }
779
780 void
781 tbm_surface_internal_unref(tbm_surface_h surface)
782 {
783         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
784
785         _tbm_surface_mutex_lock();
786
787         surface->refcnt--;
788
789         if (surface->refcnt > 0) {
790                 _tbm_surface_mutex_unlock();
791                 return;
792         }
793
794         if (surface->refcnt == 0)
795                 _tbm_surface_internal_destroy(surface);
796
797         _tbm_surface_mutex_unlock();
798 }
799
800 int
801 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
802 {
803         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
804
805         struct _tbm_surface *surf;
806         int num;
807
808         _tbm_surface_mutex_lock();
809
810         surf = (struct _tbm_surface *)surface;
811         num = surf->num_bos;
812
813         _tbm_surface_mutex_unlock();
814
815         return num;
816 }
817
818 tbm_bo
819 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
820 {
821         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), NULL);
822         TBM_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
823
824         struct _tbm_surface *surf;
825         tbm_bo bo;
826
827         _tbm_surface_mutex_lock();
828
829         surf = (struct _tbm_surface *)surface;
830         bo = surf->bos[bo_idx];
831
832         _tbm_surface_mutex_unlock();
833
834         return bo;
835 }
836
837 int
838 tbm_surface_internal_get_size(tbm_surface_h surface)
839 {
840         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
841
842         struct _tbm_surface *surf;
843         unsigned int size;
844
845         _tbm_surface_mutex_lock();
846
847         surf = (struct _tbm_surface *)surface;
848         size = surf->info.size;
849
850         _tbm_surface_mutex_unlock();
851
852         return size;
853 }
854
855 int
856 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
857                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
858 {
859         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
860         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
861
862         struct _tbm_surface *surf;
863
864         _tbm_surface_mutex_lock();
865
866         surf = (struct _tbm_surface *)surface;
867
868         if (plane_idx >= surf->info.num_planes) {
869                 _tbm_surface_mutex_unlock();
870                 return 0;
871         }
872
873         if (size)
874                 *size = surf->info.planes[plane_idx].size;
875
876         if (offset)
877                 *offset = surf->info.planes[plane_idx].offset;
878
879         if (pitch)
880                 *pitch = surf->info.planes[plane_idx].stride;
881
882         _tbm_surface_mutex_unlock();
883
884         return 1;
885 }
886
887 int
888 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
889                               tbm_surface_info_s *info, int map)
890 {
891         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
892
893         struct _tbm_surface *surf;
894         tbm_bo_handle bo_handles[4];
895         int i, j;
896
897         _tbm_surface_mutex_lock();
898
899         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
900
901         surf = (struct _tbm_surface *)surface;
902
903         memset(info, 0x00, sizeof(tbm_surface_info_s));
904         info->width = surf->info.width;
905         info->height = surf->info.height;
906         info->format = surf->info.format;
907         info->bpp = surf->info.bpp;
908         info->size = surf->info.size;
909         info->num_planes = surf->info.num_planes;
910
911         if (map == 1) {
912                 for (i = 0; i < surf->num_bos; i++) {
913                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
914                         if (bo_handles[i].ptr == NULL) {
915                                 for (j = 0; j < i; j++)
916                                         tbm_bo_unmap(surf->bos[j]);
917
918                                 _tbm_surface_mutex_unlock();
919                                 return 0;
920                         }
921                 }
922         } else {
923                 for (i = 0; i < surf->num_bos; i++)
924                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
925         }
926
927         for (i = 0; i < surf->info.num_planes; i++) {
928                 info->planes[i].size = surf->info.planes[i].size;
929                 info->planes[i].offset = surf->info.planes[i].offset;
930                 info->planes[i].stride = surf->info.planes[i].stride;
931
932                 if (bo_handles[surf->planes_bo_idx[i]].ptr)
933                         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
934                                               surf->info.planes[i].offset;
935         }
936
937         _tbm_surface_mutex_unlock();
938
939         return 1;
940 }
941
942 void
943 tbm_surface_internal_unmap(tbm_surface_h surface)
944 {
945         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
946
947         struct _tbm_surface *surf;
948         int i;
949
950         _tbm_surface_mutex_lock();
951
952         surf = (struct _tbm_surface *)surface;
953
954         for (i = 0; i < surf->num_bos; i++)
955                 tbm_bo_unmap(surf->bos[i]);
956
957         _tbm_surface_mutex_unlock();
958 }
959
960 unsigned int
961 tbm_surface_internal_get_width(tbm_surface_h surface)
962 {
963         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
964
965         struct _tbm_surface *surf;
966         unsigned int width;
967
968         _tbm_surface_mutex_lock();
969
970         surf = (struct _tbm_surface *)surface;
971         width = surf->info.width;
972
973         _tbm_surface_mutex_unlock();
974
975         return width;
976 }
977
978 unsigned int
979 tbm_surface_internal_get_height(tbm_surface_h surface)
980 {
981         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
982
983         struct _tbm_surface *surf;
984         unsigned int height;
985
986         _tbm_surface_mutex_lock();
987
988         surf = (struct _tbm_surface *)surface;
989         height = surf->info.height;
990
991         _tbm_surface_mutex_unlock();
992
993         return height;
994
995 }
996
997 tbm_format
998 tbm_surface_internal_get_format(tbm_surface_h surface)
999 {
1000         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1001
1002         struct _tbm_surface *surf;
1003         tbm_format format;
1004
1005         _tbm_surface_mutex_lock();
1006
1007         surf = (struct _tbm_surface *)surface;
1008         format = surf->info.format;
1009
1010         _tbm_surface_mutex_unlock();
1011
1012         return format;
1013 }
1014
1015 int
1016 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1017 {
1018         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1019         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1020         struct _tbm_surface *surf;
1021         int bo_idx;
1022
1023         _tbm_surface_mutex_lock();
1024
1025         surf = (struct _tbm_surface *)surface;
1026         bo_idx = surf->planes_bo_idx[plane_idx];
1027
1028         _tbm_surface_mutex_unlock();
1029
1030         return bo_idx;
1031 }
1032
1033 unsigned int
1034 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1035 {
1036         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1037
1038         return surface->debug_pid;
1039 }
1040
1041 void
1042 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1043 {
1044         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1045
1046         surface->debug_pid = pid;
1047 }
1048
1049 int
1050 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1051                                    tbm_data_free data_free_func)
1052 {
1053         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1054
1055         tbm_user_data *data;
1056
1057         /* check if the data according to the key exist if so, return false. */
1058         data = user_data_lookup(&surface->user_data_list, key);
1059         if (data) {
1060                 TBM_LOG_W("waring user data already exist. key:%ld\n", key);
1061                 return 0;
1062         }
1063
1064         data = user_data_create(key, data_free_func);
1065         if (!data)
1066                 return 0;
1067
1068         LIST_ADD(&data->item_link, &surface->user_data_list);
1069
1070         return 1;
1071 }
1072
1073 int
1074 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1075                                    void *data)
1076 {
1077         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1078
1079         tbm_user_data *old_data;
1080
1081         if (LIST_IS_EMPTY(&surface->user_data_list))
1082                 return 0;
1083
1084         old_data = user_data_lookup(&surface->user_data_list, key);
1085         if (!old_data)
1086                 return 0;
1087
1088         if (old_data->data && old_data->free_func)
1089                 old_data->free_func(old_data->data);
1090
1091         old_data->data = data;
1092
1093         return 1;
1094 }
1095
1096 int
1097 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1098                                    void **data)
1099 {
1100         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1101
1102         tbm_user_data *old_data;
1103
1104         if (!data || LIST_IS_EMPTY(&surface->user_data_list))
1105                 return 0;
1106
1107         old_data = user_data_lookup(&surface->user_data_list, key);
1108         if (!old_data) {
1109                 *data = NULL;
1110                 return 0;
1111         }
1112
1113         *data = old_data->data;
1114
1115         return 1;
1116 }
1117
1118 int
1119 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1120                                       unsigned long key)
1121 {
1122         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1123
1124         tbm_user_data *old_data = (void *)0;
1125
1126         if (LIST_IS_EMPTY(&surface->user_data_list))
1127                 return 0;
1128
1129         old_data = user_data_lookup(&surface->user_data_list, key);
1130         if (!old_data)
1131                 return 0;
1132
1133         user_data_delete(old_data);
1134
1135         return 1;
1136 }
1137
1138 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1139 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1140
1141 struct _tbm_surface_dump_buf_info
1142 {
1143         int index;
1144         tbm_bo bo;
1145         int size;
1146         int dirty;
1147         int dirty_shm;
1148         int shm_stride;
1149         int shm_h;
1150         char name[1024];
1151
1152         tbm_surface_info_s info;
1153
1154         struct list_head link;
1155 };
1156
1157 struct _tbm_surface_dump_info
1158 {
1159         char *path;  // copy???
1160         int dump_max;
1161         int count;
1162         struct list_head *link;
1163         struct list_head surface_list; /* link of surface */
1164 };
1165
1166 static tbm_surface_dump_info *g_dump_info = NULL;
1167 static const char *dump_postfix[2] = {"png", "yuv"};
1168
1169 static void
1170 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1, void *data2,
1171                      int size2, void *data3, int size3)
1172 {
1173         unsigned int *blocks;
1174         FILE *fp = fopen(file, "w+");
1175         TBM_RETURN_IF_FAIL(fp != NULL);
1176
1177         blocks = (unsigned int *)data1;
1178         fwrite(blocks, 1, size1, fp);
1179
1180         if (size2 > 0) {
1181                 blocks = (unsigned int *)data2;
1182                 fwrite(blocks, 1, size2, fp);
1183         }
1184
1185         if (size3 > 0) {
1186                 blocks = (unsigned int *)data3;
1187                 fwrite(blocks, 1, size3, fp);
1188         }
1189
1190         fclose(fp);
1191 }
1192
1193 static void
1194 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width,
1195                      int height)
1196 {
1197         FILE *fp = fopen(file, "wb");
1198         TBM_RETURN_IF_FAIL(fp != NULL);
1199         int depth = 8;
1200
1201         png_structp pPngStruct =
1202                 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1203         if (!pPngStruct) {
1204                 fclose(fp);
1205                 return;
1206         }
1207
1208         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1209         if (!pPngInfo) {
1210                 png_destroy_write_struct(&pPngStruct, NULL);
1211                 fclose(fp);
1212                 return;
1213         }
1214
1215         png_init_io(pPngStruct, fp);
1216         png_set_IHDR(pPngStruct,
1217                      pPngInfo,
1218                      width,
1219                      height,
1220                      depth,
1221                      PNG_COLOR_TYPE_RGBA,
1222                      PNG_INTERLACE_NONE,
1223                      PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1224
1225         png_set_bgr(pPngStruct);
1226         png_write_info(pPngStruct, pPngInfo);
1227
1228         const int pixel_size = 4;       // RGBA
1229         png_bytep *row_pointers =
1230                         png_malloc(pPngStruct, height * sizeof(png_byte *));
1231
1232         unsigned int *blocks = (unsigned int *)data;
1233         int y = 0;
1234         int x = 0;
1235
1236         for (; y < height; ++y) {
1237                 png_bytep row =
1238                         png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1239                 row_pointers[y] = (png_bytep)row;
1240                 for (x = 0; x < width; ++x) {
1241                         unsigned int curBlock = blocks[y * width + x];
1242                         row[x * pixel_size] = (curBlock & 0xFF);
1243                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1244                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1245                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1246                 }
1247         }
1248
1249         png_write_image(pPngStruct, row_pointers);
1250         png_write_end(pPngStruct, pPngInfo);
1251
1252         for (y = 0; y < height; y++)
1253                 png_free(pPngStruct, row_pointers[y]);
1254         png_free(pPngStruct, row_pointers);
1255
1256         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1257
1258         fclose(fp);
1259 }
1260
1261 void
1262 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1263 {
1264         TBM_RETURN_IF_FAIL(path != NULL);
1265         TBM_RETURN_IF_FAIL(w > 0);
1266         TBM_RETURN_IF_FAIL(h > 0);
1267         TBM_RETURN_IF_FAIL(count > 0);
1268
1269         tbm_surface_dump_buf_info *buf_info = NULL;
1270         tbm_surface_dump_buf_info *tmp;
1271         tbm_bo bo = NULL;
1272         int i;
1273         int buffer_size;
1274         tbm_surface_h tbm_surface;
1275         tbm_surface_info_s info;
1276         tbm_surface_error_e err;
1277
1278         /* check running */
1279         if (g_dump_info) {
1280                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1281                 return;
1282         }
1283
1284         g_dump_info = calloc(1, sizeof (struct _tbm_surface_dump_info));
1285         TBM_RETURN_IF_FAIL(g_dump_info);
1286
1287         LIST_INITHEAD(&g_dump_info->surface_list);
1288         g_dump_info->count = 0;
1289         g_dump_info->dump_max = count;
1290
1291         /* get buffer size */
1292         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1293         if (tbm_surface == NULL) {
1294                 TBM_LOG_E("tbm_surface_create fail\n");
1295                 free(g_dump_info);
1296                 g_dump_info = NULL;
1297                 return;
1298         }
1299         err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
1300         if (err != TBM_SURFACE_ERROR_NONE) {
1301                 TBM_LOG_E("tbm_surface_map fail\n");
1302                 tbm_surface_destroy(tbm_surface);
1303                 free(g_dump_info);
1304                 g_dump_info = NULL;
1305                 return;
1306         }
1307         buffer_size = info.planes[0].stride * h;
1308         tbm_surface_unmap(tbm_surface);
1309         tbm_surface_destroy(tbm_surface);
1310
1311         /* create dump lists */
1312         for (i = 0; i < count; i++)     {
1313                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1314                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1315                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1316                 if (bo == NULL) {
1317                         free(buf_info);
1318                         goto fail;
1319                 }
1320
1321                 buf_info->index = i;
1322                 buf_info->bo = bo;
1323                 buf_info->size = buffer_size;
1324
1325                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1326         }
1327
1328         g_dump_info->path = path;
1329         g_dump_info->link = &g_dump_info->surface_list;
1330
1331         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1332
1333         return;
1334 fail:
1335         /* free resources */
1336         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1337                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1338                         tbm_bo_unref(buf_info->bo);
1339                         free(buf_info);
1340                 }
1341         }
1342
1343         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1344
1345         free(g_dump_info);
1346         g_dump_info = NULL;
1347
1348         return;
1349 }
1350
1351 void
1352 tbm_surface_internal_dump_end(void)
1353 {
1354         tbm_surface_dump_buf_info *buf_info, *tmp;
1355         tbm_bo_handle bo_handle;
1356
1357         if (!g_dump_info)
1358                 return;
1359
1360         /* make files */
1361         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1362                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1363                         char file[2048];
1364
1365                         if (buf_info->dirty) {
1366                                 void *ptr1 = NULL;
1367                                 void *ptr2 = NULL;
1368
1369                                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1370                                 if (bo_handle.ptr == NULL)
1371                                         continue;
1372
1373                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1374                                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1375
1376                                 switch (buf_info->info.format) {
1377                                 case TBM_FORMAT_ARGB8888:
1378                                 case TBM_FORMAT_XRGB8888:
1379                                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1380                                                                         buf_info->info.planes[0].stride >> 2, buf_info->info.height);
1381                                         break;
1382                                 case TBM_FORMAT_YVU420:
1383                                 case TBM_FORMAT_YUV420:
1384                                         ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1385                                         ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1386                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1387                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1388                                                                         ptr1,
1389                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1390                                                                         ptr2,
1391                                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1392                                         break;
1393                                 case TBM_FORMAT_NV12:
1394                                 case TBM_FORMAT_NV21:
1395                                         ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1396                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1397                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1398                                                                         ptr1,
1399                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1400                                                                         NULL, 0);
1401                                         break;
1402                                 case TBM_FORMAT_YUYV:
1403                                 case TBM_FORMAT_UYVY:
1404                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1405                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1406                                                                         NULL, 0, NULL, 0);
1407                                         break;
1408                                 default:
1409                                         TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1410                                         tbm_bo_unmap(buf_info->bo);
1411                                         return;
1412                                 }
1413
1414                                 tbm_bo_unmap(buf_info->bo);
1415                         } else if (buf_info->dirty_shm) {
1416                                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1417                                 if (bo_handle.ptr == NULL)
1418                                         continue;
1419
1420                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1421                                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1422
1423                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1424                                                                 buf_info->shm_stride >> 2, buf_info->shm_h);
1425
1426                                 tbm_bo_unmap(buf_info->bo);
1427                         }
1428                 }
1429         }
1430
1431
1432         /* free resources */
1433         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1434                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1435                         tbm_bo_unref(buf_info->bo);
1436                         free(buf_info);
1437                 }
1438         }
1439
1440         free(g_dump_info);
1441         g_dump_info = NULL;
1442
1443         TBM_LOG_I("Dump End..\n");
1444 }
1445
1446 void
1447 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1448 {
1449         TBM_RETURN_IF_FAIL(surface != NULL);
1450         TBM_RETURN_IF_FAIL(type != NULL);
1451
1452         tbm_surface_dump_buf_info *buf_info;
1453         tbm_surface_info_s info;
1454         struct list_head *next_link;
1455         tbm_bo_handle bo_handle;
1456         int ret;
1457         const char *postfix;
1458
1459         if (!g_dump_info)
1460                 return;
1461
1462         next_link = g_dump_info->link->next;
1463         TBM_RETURN_IF_FAIL(next_link != NULL);
1464
1465         if (next_link == &g_dump_info->surface_list) {
1466                 next_link = next_link->next;
1467                 TBM_RETURN_IF_FAIL(next_link != NULL);
1468         }
1469
1470         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1471         TBM_RETURN_IF_FAIL(buf_info != NULL);
1472
1473         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1474         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1475
1476         if (info.size > buf_info->size) {
1477                 TBM_LOG_W("Dump skip. surface over created buffer size(%d, %d)\n", info.size, buf_info->size);
1478                 tbm_surface_unmap(surface);
1479                 return;
1480         }
1481
1482         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1483                 postfix = dump_postfix[0];
1484         else
1485                 postfix = dump_postfix[1];
1486
1487         /* make the file information */
1488         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1489
1490         /* dump */
1491         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1492         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1493         memset(bo_handle.ptr, 0x00, buf_info->size);
1494
1495         switch (info.format) {
1496         case TBM_FORMAT_ARGB8888:
1497         case TBM_FORMAT_XRGB8888:
1498                 snprintf(buf_info->name, sizeof(buf_info->name), "%03d-%s.%s", g_dump_info->count++, type, postfix);
1499                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1500                 break;
1501         case TBM_FORMAT_YVU420:
1502         case TBM_FORMAT_YUV420:
1503                 snprintf(buf_info->name, sizeof(buf_info->name), "%03d-%s_%dx%d_%c%c%c%c.%s",
1504                                 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1505                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1506                 bo_handle.ptr += info.planes[0].stride * info.height;
1507                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1508                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1509                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1510                 break;
1511         case TBM_FORMAT_NV12:
1512         case TBM_FORMAT_NV21:
1513                 snprintf(buf_info->name, sizeof(buf_info->name), "%03d-%s_%dx%d_%c%c%c%c.%s",
1514                                 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1515                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1516                 bo_handle.ptr += info.planes[0].stride * info.height;
1517                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1518                 break;
1519         case TBM_FORMAT_YUYV:
1520         case TBM_FORMAT_UYVY:
1521                 snprintf(buf_info->name, sizeof(buf_info->name), "%03d-%s_%dx%d_%c%c%c%c.%s",
1522                                 g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1523                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1524                 break;
1525         default:
1526                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1527                 tbm_bo_unmap(buf_info->bo);
1528                 return;
1529         }
1530
1531         tbm_bo_unmap(buf_info->bo);
1532
1533         tbm_surface_unmap(surface);
1534
1535         buf_info->dirty = 1;
1536         buf_info->dirty_shm = 0;
1537
1538         if (g_dump_info->count == 1000)
1539                 g_dump_info->count = 0;
1540
1541         g_dump_info->link = next_link;
1542
1543         TBM_LOG_I("Dump %s \n", buf_info->name);
1544 }
1545
1546 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int  stride, const char *type)
1547 {
1548         TBM_RETURN_IF_FAIL(ptr != NULL);
1549         TBM_RETURN_IF_FAIL(w > 0);
1550         TBM_RETURN_IF_FAIL(h > 0);
1551         TBM_RETURN_IF_FAIL(stride > 0);
1552         TBM_RETURN_IF_FAIL(type != NULL);
1553
1554         tbm_surface_dump_buf_info *buf_info;
1555         struct list_head *next_link;
1556         tbm_bo_handle bo_handle;
1557
1558         if (!g_dump_info)
1559                 return;
1560
1561         next_link = g_dump_info->link->next;
1562         TBM_RETURN_IF_FAIL(next_link != NULL);
1563
1564         if (next_link == &g_dump_info->surface_list) {
1565                 next_link = next_link->next;
1566                 TBM_RETURN_IF_FAIL(next_link != NULL);
1567         }
1568
1569         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1570         TBM_RETURN_IF_FAIL(buf_info != NULL);
1571
1572         if (stride * h > buf_info->size) {
1573                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n", stride * h, buf_info->size);
1574                 return;
1575         }
1576
1577         /* dump */
1578         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1579         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1580         memset(bo_handle.ptr, 0x00, buf_info->size);
1581         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1582
1583
1584         snprintf(buf_info->name, sizeof(buf_info->name), "%03d-%s.%s", g_dump_info->count++, type, dump_postfix[0]);
1585         memcpy(bo_handle.ptr, ptr, stride * h);
1586
1587         tbm_bo_unmap(buf_info->bo);
1588
1589         buf_info->dirty = 0;
1590         buf_info->dirty_shm = 1;
1591         buf_info->shm_stride = stride;
1592         buf_info->shm_h = h;
1593
1594         if (g_dump_info->count == 1000)
1595                 g_dump_info->count = 0;
1596
1597         g_dump_info->link = next_link;
1598
1599         TBM_LOG_I("Dump %s \n", buf_info->name);
1600 }
1601