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