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