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