correct surface information
[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
34 #include <stdio.h>
35 #include <time.h>
36 #include <sys/time.h>
37 #include "tbm_bufmgr.h"
38 #include "tbm_bufmgr_int.h"
39 #include "tbm_surface_internal.h"
40 #include "list.h"
41 #include <png.h>
42
43 static tbm_bufmgr g_surface_bufmgr;
44 static pthread_mutex_t tbm_surface_lock;
45 void _tbm_surface_mutex_unlock(void);
46
47 #define C(b, m)              (((b) >> (m)) & 0xFF)
48 #define B(c, s)              ((((unsigned int)(c)) & 0xff) << (s))
49 #define FOURCC(a, b, c, d)     (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
50 #define FOURCC_STR(id)      C(id, 0), C(id, 8), C(id, 16), C(id, 24)
51 #define FOURCC_ID(str)      FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3])
52
53 /* check condition */
54 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
55         if (!(cond)) {\
56                 TBM_LOG_E("'%s' failed.\n", #cond);\
57                 _tbm_surface_mutex_unlock();\
58                 return;\
59         } \
60 }
61
62 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
63         if (!(cond)) {\
64                 TBM_LOG_E("'%s' failed.\n", #cond);\
65                 _tbm_surface_mutex_unlock();\
66                 return val;\
67         } \
68 }
69
70 /* LCOV_EXCL_START */
71
72 static double
73 _tbm_surface_internal_get_time(void)
74 {
75         struct timespec tp;
76         unsigned int time;
77
78         clock_gettime(CLOCK_MONOTONIC, &tp);
79         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
80
81         return time / 1000.0;
82 }
83
84 static void
85 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
86 {
87         LIST_DEL(&debug_data->item_link);
88
89         if (debug_data->key) free(debug_data->key);
90         if (debug_data->value) free(debug_data->value);
91         free(debug_data);
92 }
93
94 char *
95 _tbm_surface_internal_format_to_str(tbm_format format)
96 {
97         switch (format) {
98         case TBM_FORMAT_C8:
99                 return "TBM_FORMAT_C8";
100         case TBM_FORMAT_RGB332:
101                 return "TBM_FORMAT_RGB332";
102         case TBM_FORMAT_BGR233:
103                 return "TBM_FORMAT_BGR233";
104         case TBM_FORMAT_XRGB4444:
105                 return "TBM_FORMAT_XRGB4444";
106         case TBM_FORMAT_XBGR4444:
107                 return "TBM_FORMAT_XBGR4444";
108         case TBM_FORMAT_RGBX4444:
109                 return "TBM_FORMAT_RGBX4444";
110         case TBM_FORMAT_BGRX4444:
111                 return "TBM_FORMAT_BGRX4444";
112         case TBM_FORMAT_ARGB4444:
113                 return "TBM_FORMAT_ARGB4444";
114         case TBM_FORMAT_ABGR4444:
115                 return "TBM_FORMAT_ABGR4444";
116         case TBM_FORMAT_RGBA4444:
117                 return "TBM_FORMAT_RGBA4444";
118         case TBM_FORMAT_BGRA4444:
119                 return "TBM_FORMAT_BGRA4444";
120         case TBM_FORMAT_XRGB1555:
121                 return "TBM_FORMAT_XRGB1555";
122         case TBM_FORMAT_XBGR1555:
123                 return "TBM_FORMAT_XBGR1555";
124         case TBM_FORMAT_RGBX5551:
125                 return "TBM_FORMAT_RGBX5551";
126         case TBM_FORMAT_BGRX5551:
127                 return "TBM_FORMAT_BGRX5551";
128         case TBM_FORMAT_ARGB1555:
129                 return "TBM_FORMAT_ARGB1555";
130         case TBM_FORMAT_ABGR1555:
131                 return "TBM_FORMAT_ABGR1555";
132         case TBM_FORMAT_RGBA5551:
133                 return "TBM_FORMAT_RGBA5551";
134         case TBM_FORMAT_BGRA5551:
135                 return "TBM_FORMAT_BGRA5551";
136         case TBM_FORMAT_RGB565:
137                 return "TBM_FORMAT_RGB565";
138         case TBM_FORMAT_BGR565:
139                 return "TBM_FORMAT_BGR565";
140         case TBM_FORMAT_RGB888:
141                 return "TBM_FORMAT_RGB888";
142         case TBM_FORMAT_BGR888:
143                 return "TBM_FORMAT_BGR888";
144         case TBM_FORMAT_XRGB8888:
145                 return "TBM_FORMAT_XRGB8888";
146         case TBM_FORMAT_XBGR8888:
147                 return "TBM_FORMAT_XBGR8888";
148         case TBM_FORMAT_RGBX8888:
149                 return "TBM_FORMAT_RGBX8888";
150         case TBM_FORMAT_BGRX8888:
151                 return "TBM_FORMAT_BGRX8888";
152         case TBM_FORMAT_ARGB8888:
153                 return "TBM_FORMAT_ARGB8888";
154         case TBM_FORMAT_ABGR8888:
155                 return "TBM_FORMAT_ABGR8888";
156         case TBM_FORMAT_RGBA8888:
157                 return "TBM_FORMAT_RGBA8888";
158         case TBM_FORMAT_BGRA8888:
159                 return "TBM_FORMAT_BGRA8888";
160         case TBM_FORMAT_XRGB2101010:
161                 return "TBM_FORMAT_XRGB2101010";
162         case TBM_FORMAT_XBGR2101010:
163                 return "TBM_FORMAT_XBGR2101010";
164         case TBM_FORMAT_RGBX1010102:
165                 return "TBM_FORMAT_RGBX1010102";
166         case TBM_FORMAT_BGRX1010102:
167                 return "TBM_FORMAT_BGRX1010102";
168         case TBM_FORMAT_ARGB2101010:
169                 return "TBM_FORMAT_ARGB2101010";
170         case TBM_FORMAT_ABGR2101010:
171                 return "TBM_FORMAT_ABGR2101010";
172         case TBM_FORMAT_RGBA1010102:
173                 return "TBM_FORMAT_RGBA1010102";
174         case TBM_FORMAT_BGRA1010102:
175                 return "TBM_FORMAT_BGRA1010102";
176         case TBM_FORMAT_YUYV:
177                 return "TBM_FORMAT_YUYV";
178         case TBM_FORMAT_YVYU:
179                 return "TBM_FORMAT_YVYU";
180         case TBM_FORMAT_UYVY:
181                 return "TBM_FORMAT_UYVY";
182         case TBM_FORMAT_VYUY:
183                 return "TBM_FORMAT_VYUY";
184         case TBM_FORMAT_AYUV:
185                 return "TBM_FORMAT_AYUV";
186         case TBM_FORMAT_NV12:
187                 return "TBM_FORMAT_NV12";
188         case TBM_FORMAT_NV21:
189                 return "TBM_FORMAT_NV21";
190         case TBM_FORMAT_NV16:
191                 return "TBM_FORMAT_NV16";
192         case TBM_FORMAT_NV61:
193                 return "TBM_FORMAT_NV61";
194         case TBM_FORMAT_YUV410:
195                 return "TBM_FORMAT_YUV410";
196         case TBM_FORMAT_YVU410:
197                 return "TBM_FORMAT_YVU410";
198         case TBM_FORMAT_YUV411:
199                 return "TBM_FORMAT_YUV411";
200         case TBM_FORMAT_YVU411:
201                 return "TBM_FORMAT_YVU411";
202         case TBM_FORMAT_YUV420:
203                 return "TBM_FORMAT_YUV420";
204         case TBM_FORMAT_YVU420:
205                 return "TBM_FORMAT_YVU420";
206         case TBM_FORMAT_YUV422:
207                 return "TBM_FORMAT_YUV422";
208         case TBM_FORMAT_YVU422:
209                 return "TBM_FORMAT_YVU422";
210         case TBM_FORMAT_YUV444:
211                 return "TBM_FORMAT_YUV444";
212         case TBM_FORMAT_YVU444:
213                 return "TBM_FORMAT_YVU444";
214         case TBM_FORMAT_NV12MT:
215                 return "TBM_FORMAT_NV12MT";
216         default:
217                 return "unknwon";
218         }
219 }
220 /* LCOV_EXCL_STOP */
221
222 static bool
223 _tbm_surface_mutex_init(void)
224 {
225         static bool tbm_surface_mutex_init = false;
226
227         if (tbm_surface_mutex_init)
228                 return true;
229
230         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
231                 TBM_LOG_E("fail: pthread_mutex_init for tbm_surface_lock.\n");
232                 return false;
233         }
234
235         tbm_surface_mutex_init = true;
236
237         return true;
238 }
239
240 void
241 _tbm_surface_mutex_lock(void)
242 {
243         if (!_tbm_surface_mutex_init()) {
244                 TBM_LOG_E("fail: _tbm_surface_mutex_init.\n");
245                 return;
246         }
247
248         pthread_mutex_lock(&tbm_surface_lock);
249 }
250
251 void
252 _tbm_surface_mutex_unlock(void)
253 {
254         pthread_mutex_unlock(&tbm_surface_lock);
255 }
256
257 static void
258 _init_surface_bufmgr(void)
259 {
260         g_surface_bufmgr = tbm_bufmgr_init(-1);
261 }
262
263 static void
264 _deinit_surface_bufmgr(void)
265 {
266         if (!g_surface_bufmgr)
267                 return;
268
269         tbm_bufmgr_deinit(g_surface_bufmgr);
270         g_surface_bufmgr = NULL;
271 }
272
273 static int
274 _tbm_surface_internal_is_valid(tbm_surface_h surface)
275 {
276         tbm_surface_h old_data = NULL;
277
278         TBM_RETURN_VAL_IF_FAIL(g_surface_bufmgr, 0);
279         TBM_RETURN_VAL_IF_FAIL(surface, 0);
280
281         if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
282                 LIST_FOR_EACH_ENTRY(old_data, &g_surface_bufmgr->surf_list, item_link) {
283                         if (old_data == surface) {
284                                 TBM_TRACE("tbm_surface(%p)\n", surface);
285                                 return 1;
286                         }
287                 }
288         }
289
290         TBM_LOG_E("error: No valid tbm_surface(%p)\n", surface);
291
292         return 0;
293 }
294
295 static int
296 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
297                                        int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
298 {
299         TBM_RETURN_VAL_IF_FAIL(surface, 0);
300         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
301
302         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
303         struct _tbm_bufmgr *mgr = surf->bufmgr;
304         int ret = 0;
305
306         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
307         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
308         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
309         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
310
311         if (!mgr->backend->surface_get_plane_data)
312                 return 0;
313
314         ret = mgr->backend->surface_get_plane_data(surf->info.width,
315                         surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
316         if (!ret) {
317                 TBM_LOG_E("Fail to surface_get_plane_data. surface(%p)\n", surface);
318                 return 0;
319         }
320
321         return 1;
322 }
323
324 static void
325 _tbm_surface_internal_destroy(tbm_surface_h surface)
326 {
327         int i;
328         tbm_bufmgr bufmgr = surface->bufmgr;
329         tbm_user_data *old_data = NULL, *tmp = NULL;
330         tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
331
332         /* destory the user_data_list */
333         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
334                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
335                         TBM_DBG("free user_data\n");
336                         user_data_delete(old_data);
337                 }
338         }
339
340         for (i = 0; i < surface->num_bos; i++) {
341                 surface->bos[i]->surface = NULL;
342
343                 tbm_bo_unref(surface->bos[i]);
344                 surface->bos[i] = NULL;
345         }
346
347         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
348                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
349                         _tbm_surface_internal_debug_data_delete(debug_old_data);
350         }
351
352         LIST_DEL(&surface->item_link);
353
354         free(surface);
355         surface = NULL;
356
357         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
358                 LIST_DELINIT(&bufmgr->surf_list);
359
360                 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
361                         LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
362                                 _tbm_surface_internal_debug_data_delete(debug_old_data);
363                         }
364                 }
365
366                 _deinit_surface_bufmgr();
367         }
368 }
369
370 int
371 tbm_surface_internal_is_valid(tbm_surface_h surface)
372 {
373         int ret = 0;
374
375         _tbm_surface_mutex_lock();
376
377         /* Return silently if surface is null. */
378         if (!surface) {
379                 _tbm_surface_mutex_unlock();
380                 return 0;
381         }
382
383         ret = _tbm_surface_internal_is_valid(surface);
384
385         _tbm_surface_mutex_unlock();
386
387         return ret;
388 }
389
390 int
391 tbm_surface_internal_query_supported_formats(uint32_t **formats,
392                 uint32_t *num)
393 {
394         struct _tbm_bufmgr *mgr;
395         int ret = 0;
396         bool bufmgr_initialized = false;
397
398         _tbm_surface_mutex_lock();
399
400         if (!g_surface_bufmgr) {
401                 _init_surface_bufmgr();
402                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
403                 bufmgr_initialized = true;
404         }
405
406         mgr = g_surface_bufmgr;
407
408         if (!mgr->backend->surface_supported_format)
409                 goto fail;
410
411         ret = mgr->backend->surface_supported_format(formats, num);
412         if (!ret)  {
413                 TBM_LOG_E("Fail to surface_supported_format.\n");
414                 goto fail;
415         }
416
417         TBM_TRACE("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
418
419         _tbm_surface_mutex_unlock();
420
421         return ret;
422
423 fail:
424         if (bufmgr_initialized) {
425                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
426                 _deinit_surface_bufmgr();
427         }
428         _tbm_surface_mutex_unlock();
429
430         TBM_LOG_E("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
431
432         return 0;
433 }
434
435 int
436 tbm_surface_internal_get_num_planes(tbm_format format)
437 {
438         int num_planes = 0;
439
440         switch (format) {
441         case TBM_FORMAT_C8:
442         case TBM_FORMAT_RGB332:
443         case TBM_FORMAT_BGR233:
444         case TBM_FORMAT_XRGB4444:
445         case TBM_FORMAT_XBGR4444:
446         case TBM_FORMAT_RGBX4444:
447         case TBM_FORMAT_BGRX4444:
448         case TBM_FORMAT_ARGB4444:
449         case TBM_FORMAT_ABGR4444:
450         case TBM_FORMAT_RGBA4444:
451         case TBM_FORMAT_BGRA4444:
452         case TBM_FORMAT_XRGB1555:
453         case TBM_FORMAT_XBGR1555:
454         case TBM_FORMAT_RGBX5551:
455         case TBM_FORMAT_BGRX5551:
456         case TBM_FORMAT_ARGB1555:
457         case TBM_FORMAT_ABGR1555:
458         case TBM_FORMAT_RGBA5551:
459         case TBM_FORMAT_BGRA5551:
460         case TBM_FORMAT_RGB565:
461         case TBM_FORMAT_BGR565:
462         case TBM_FORMAT_RGB888:
463         case TBM_FORMAT_BGR888:
464         case TBM_FORMAT_XRGB8888:
465         case TBM_FORMAT_XBGR8888:
466         case TBM_FORMAT_RGBX8888:
467         case TBM_FORMAT_BGRX8888:
468         case TBM_FORMAT_ARGB8888:
469         case TBM_FORMAT_ABGR8888:
470         case TBM_FORMAT_RGBA8888:
471         case TBM_FORMAT_BGRA8888:
472         case TBM_FORMAT_XRGB2101010:
473         case TBM_FORMAT_XBGR2101010:
474         case TBM_FORMAT_RGBX1010102:
475         case TBM_FORMAT_BGRX1010102:
476         case TBM_FORMAT_ARGB2101010:
477         case TBM_FORMAT_ABGR2101010:
478         case TBM_FORMAT_RGBA1010102:
479         case TBM_FORMAT_BGRA1010102:
480         case TBM_FORMAT_YUYV:
481         case TBM_FORMAT_YVYU:
482         case TBM_FORMAT_UYVY:
483         case TBM_FORMAT_VYUY:
484         case TBM_FORMAT_AYUV:
485                 num_planes = 1;
486                 break;
487         case TBM_FORMAT_NV12:
488         case TBM_FORMAT_NV12MT:
489         case TBM_FORMAT_NV21:
490         case TBM_FORMAT_NV16:
491         case TBM_FORMAT_NV61:
492                 num_planes = 2;
493                 break;
494         case TBM_FORMAT_YUV410:
495         case TBM_FORMAT_YVU410:
496         case TBM_FORMAT_YUV411:
497         case TBM_FORMAT_YVU411:
498         case TBM_FORMAT_YUV420:
499         case TBM_FORMAT_YVU420:
500         case TBM_FORMAT_YUV422:
501         case TBM_FORMAT_YVU422:
502         case TBM_FORMAT_YUV444:
503         case TBM_FORMAT_YVU444:
504                 num_planes = 3;
505                 break;
506
507         default:
508                 break;
509         }
510
511         TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
512
513         return num_planes;
514 }
515
516 int
517 tbm_surface_internal_get_bpp(tbm_format format)
518 {
519
520         int bpp = 0;
521
522         switch (format) {
523         case TBM_FORMAT_C8:
524         case TBM_FORMAT_RGB332:
525         case TBM_FORMAT_BGR233:
526                 bpp = 8;
527                 break;
528         case TBM_FORMAT_XRGB4444:
529         case TBM_FORMAT_XBGR4444:
530         case TBM_FORMAT_RGBX4444:
531         case TBM_FORMAT_BGRX4444:
532         case TBM_FORMAT_ARGB4444:
533         case TBM_FORMAT_ABGR4444:
534         case TBM_FORMAT_RGBA4444:
535         case TBM_FORMAT_BGRA4444:
536         case TBM_FORMAT_XRGB1555:
537         case TBM_FORMAT_XBGR1555:
538         case TBM_FORMAT_RGBX5551:
539         case TBM_FORMAT_BGRX5551:
540         case TBM_FORMAT_ARGB1555:
541         case TBM_FORMAT_ABGR1555:
542         case TBM_FORMAT_RGBA5551:
543         case TBM_FORMAT_BGRA5551:
544         case TBM_FORMAT_RGB565:
545         case TBM_FORMAT_BGR565:
546                 bpp = 16;
547                 break;
548         case TBM_FORMAT_RGB888:
549         case TBM_FORMAT_BGR888:
550                 bpp = 24;
551                 break;
552         case TBM_FORMAT_XRGB8888:
553         case TBM_FORMAT_XBGR8888:
554         case TBM_FORMAT_RGBX8888:
555         case TBM_FORMAT_BGRX8888:
556         case TBM_FORMAT_ARGB8888:
557         case TBM_FORMAT_ABGR8888:
558         case TBM_FORMAT_RGBA8888:
559         case TBM_FORMAT_BGRA8888:
560         case TBM_FORMAT_XRGB2101010:
561         case TBM_FORMAT_XBGR2101010:
562         case TBM_FORMAT_RGBX1010102:
563         case TBM_FORMAT_BGRX1010102:
564         case TBM_FORMAT_ARGB2101010:
565         case TBM_FORMAT_ABGR2101010:
566         case TBM_FORMAT_RGBA1010102:
567         case TBM_FORMAT_BGRA1010102:
568         case TBM_FORMAT_YUYV:
569         case TBM_FORMAT_YVYU:
570         case TBM_FORMAT_UYVY:
571         case TBM_FORMAT_VYUY:
572         case TBM_FORMAT_AYUV:
573                 bpp = 32;
574                 break;
575         case TBM_FORMAT_NV12:
576         case TBM_FORMAT_NV12MT:
577         case TBM_FORMAT_NV21:
578                 bpp = 12;
579                 break;
580         case TBM_FORMAT_NV16:
581         case TBM_FORMAT_NV61:
582                 bpp = 16;
583                 break;
584         case TBM_FORMAT_YUV410:
585         case TBM_FORMAT_YVU410:
586                 bpp = 9;
587                 break;
588         case TBM_FORMAT_YUV411:
589         case TBM_FORMAT_YVU411:
590         case TBM_FORMAT_YUV420:
591         case TBM_FORMAT_YVU420:
592                 bpp = 12;
593                 break;
594         case TBM_FORMAT_YUV422:
595         case TBM_FORMAT_YVU422:
596                 bpp = 16;
597                 break;
598         case TBM_FORMAT_YUV444:
599         case TBM_FORMAT_YVU444:
600                 bpp = 24;
601                 break;
602         default:
603                 break;
604         }
605
606         TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
607
608         return bpp;
609 }
610
611 tbm_surface_h
612 tbm_surface_internal_create_with_flags(int width, int height,
613                                        int format, int flags)
614 {
615         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
616         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
617
618         struct _tbm_bufmgr *mgr;
619         struct _tbm_surface *surf = NULL;
620         uint32_t size = 0;
621         uint32_t offset = 0;
622         uint32_t stride = 0;
623         uint32_t bo_size = 0;
624         int bo_idx;
625         int i, j;
626         bool bufmgr_initialized = false;
627
628         _tbm_surface_mutex_lock();
629
630         if (!g_surface_bufmgr) {
631                 _init_surface_bufmgr();
632                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
633                 bufmgr_initialized = true;
634         }
635
636         mgr = g_surface_bufmgr;
637         if (!TBM_BUFMGR_IS_VALID(mgr)) {
638                 TBM_LOG_E("The bufmgr is invalid\n");
639                 goto check_valid_fail;
640         }
641
642         surf = calloc(1, sizeof(struct _tbm_surface));
643         if (!surf) {
644                 TBM_LOG_E("fail to alloc surf\n");
645                 goto alloc_surf_fail;
646         }
647
648         surf->bufmgr = mgr;
649         surf->info.width = width;
650         surf->info.height = height;
651         surf->info.format = format;
652         surf->info.bpp = tbm_surface_internal_get_bpp(format);
653         surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
654         surf->refcnt = 1;
655
656         /* get size, stride and offset bo_idx */
657         for (i = 0; i < surf->info.num_planes; i++) {
658                 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
659                                                 &offset, &stride, &bo_idx)) {
660                         TBM_LOG_E("fail to query plane data\n");
661                         goto query_plane_data_fail;
662                 }
663
664                 surf->info.planes[i].size = size;
665                 surf->info.planes[i].offset = offset;
666                 surf->info.planes[i].stride = stride;
667                 surf->planes_bo_idx[i] = bo_idx;
668         }
669
670         surf->num_bos = 1;
671
672         for (i = 0; i < surf->info.num_planes; i++) {
673                 surf->info.size += surf->info.planes[i].size;
674
675                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
676                         surf->num_bos = surf->planes_bo_idx[i] + 1;
677         }
678
679         surf->flags = flags;
680
681         for (i = 0; i < surf->num_bos; i++) {
682                 bo_size = 0;
683                 for (j = 0; j < surf->info.num_planes; j++) {
684                         if (surf->planes_bo_idx[j] == i)
685                                 bo_size += surf->info.planes[j].size;
686                 }
687
688                 if (mgr->backend->surface_bo_alloc) {
689                         /* LCOV_EXCL_START */
690                         tbm_bo bo = NULL;
691                         void *bo_priv = NULL;
692
693                         bo = calloc(1, sizeof(struct _tbm_bo));
694                         if (!bo) {
695                                 TBM_LOG_E("fail to alloc bo struct\n");
696                                 goto alloc_bo_fail;
697                         }
698
699                         bo->bufmgr = surf->bufmgr;
700
701                         pthread_mutex_lock(&surf->bufmgr->lock);
702
703                         bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
704                         if (!bo_priv) {
705                                 TBM_LOG_E("fail to alloc bo priv\n");
706                                 free(bo);
707                                 pthread_mutex_unlock(&surf->bufmgr->lock);
708                                 goto alloc_bo_fail;
709                         }
710
711                         bo->ref_cnt = 1;
712                         bo->flags = flags;
713                         bo->priv = bo_priv;
714
715                         LIST_INITHEAD(&bo->user_data_list);
716
717                         LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
718
719                         pthread_mutex_unlock(&surf->bufmgr->lock);
720
721                         surf->bos[i] = bo;
722                         /* LCOV_EXCL_STOP */
723                 } else {
724                         surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
725                         if (!surf->bos[i]) {
726                                 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
727                                 goto alloc_bo_fail;
728                         }
729                 }
730
731                 _tbm_bo_set_surface(surf->bos[i], surf);
732         }
733
734         TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
735                         _tbm_surface_internal_format_to_str(format), flags, surf);
736
737         LIST_INITHEAD(&surf->user_data_list);
738         LIST_INITHEAD(&surf->debug_data_list);
739
740         LIST_ADD(&surf->item_link, &mgr->surf_list);
741
742         _tbm_surface_mutex_unlock();
743
744         return surf;
745
746 alloc_bo_fail:
747         for (j = 0; j < i; j++) {
748                 if (surf->bos[j])
749                         tbm_bo_unref(surf->bos[j]);
750         }
751 query_plane_data_fail:
752         free(surf);
753 alloc_surf_fail:
754 check_valid_fail:
755         if (bufmgr_initialized && mgr) {
756                 LIST_DELINIT(&mgr->surf_list);
757                 _deinit_surface_bufmgr();
758         }
759         _tbm_surface_mutex_unlock();
760
761         TBM_LOG_E("error: width(%d) height(%d) format(%s) flags(%d)\n",
762                         width, height,
763                         _tbm_surface_internal_format_to_str(format), flags);
764
765         return NULL;
766 }
767
768 tbm_surface_h
769 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
770                                      tbm_bo *bos, int num)
771 {
772         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
773         TBM_RETURN_VAL_IF_FAIL(info, NULL);
774         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
775
776         struct _tbm_bufmgr *mgr;
777         struct _tbm_surface *surf = NULL;
778         int i;
779         bool bufmgr_initialized = false;
780
781         _tbm_surface_mutex_lock();
782
783         if (!g_surface_bufmgr) {
784                 _init_surface_bufmgr();
785                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
786                 bufmgr_initialized = true;
787         }
788
789         mgr = g_surface_bufmgr;
790         if (!TBM_BUFMGR_IS_VALID(mgr)) {
791                 TBM_LOG_E("fail to validate the Bufmgr.\n");
792                 goto check_valid_fail;
793         }
794
795         surf = calloc(1, sizeof(struct _tbm_surface));
796         if (!surf) {
797                 TBM_LOG_E("fail to allocate struct _tbm_surface.\n");
798                 goto alloc_surf_fail;
799         }
800
801         surf->bufmgr = mgr;
802         surf->info.width = info->width;
803         surf->info.height = info->height;
804         surf->info.format = info->format;
805         if (info->bpp > 0)
806                 surf->info.bpp = info->bpp;
807         else
808                 surf->info.bpp = tbm_surface_internal_get_bpp(info->format);
809         surf->info.num_planes = info->num_planes;
810         surf->refcnt = 1;
811
812         /* get size, stride and offset */
813         for (i = 0; i < info->num_planes; i++) {
814                 surf->info.planes[i].offset = info->planes[i].offset;
815                 surf->info.planes[i].stride = info->planes[i].stride;
816
817                 if (info->planes[i].size > 0)
818                         surf->info.planes[i].size = info->planes[i].size;
819                 else {
820                         uint32_t size = 0, offset = 0, stride = 0;
821                         int32_t bo_idx = 0;
822
823                         _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx);
824                         surf->info.planes[i].size = size;
825                 }
826
827                 if (num == 1)
828                         surf->planes_bo_idx[i] = 0;
829                 else
830                         surf->planes_bo_idx[i] = i;
831         }
832
833         if (info->size > 0) {
834                 surf->info.size = info->size;
835         } else {
836                 surf->info.size = 0;
837                 for (i = 0; i < info->num_planes; i++)
838                         surf->info.size += surf->info.planes[i].size;
839         }
840
841         surf->flags = TBM_BO_DEFAULT;
842
843         /* create only one bo */
844         surf->num_bos = num;
845         for (i = 0; i < num; i++) {
846                 if (bos[i] == NULL) {
847                         TBM_LOG_E("bos[%d] is null.\n", i);
848                         goto check_bo_fail;
849                 }
850
851                 surf->bos[i] = tbm_bo_ref(bos[i]);
852                 _tbm_bo_set_surface(bos[i], surf);
853         }
854
855         TBM_TRACE("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
856                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
857
858         LIST_INITHEAD(&surf->user_data_list);
859         LIST_INITHEAD(&surf->debug_data_list);
860
861         LIST_ADD(&surf->item_link, &mgr->surf_list);
862
863         _tbm_surface_mutex_unlock();
864
865         return surf;
866
867 check_bo_fail:
868         for (i = 0; i < num; i++) {
869                 if (surf->bos[i])
870                         tbm_bo_unref(surf->bos[i]);
871         }
872         free(surf);
873 alloc_surf_fail:
874 check_valid_fail:
875         if (bufmgr_initialized && mgr) {
876                 LIST_DELINIT(&mgr->surf_list);
877                 _deinit_surface_bufmgr();
878         }
879         _tbm_surface_mutex_unlock();
880
881         TBM_LOG_E("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
882                         info->width, info->height,
883                         _tbm_surface_internal_format_to_str(info->format), num);
884
885         return NULL;
886 }
887
888 void
889 tbm_surface_internal_destroy(tbm_surface_h surface)
890 {
891         _tbm_surface_mutex_lock();
892
893         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
894
895         surface->refcnt--;
896
897         if (surface->refcnt > 0) {
898                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
899                 _tbm_surface_mutex_unlock();
900                 return;
901         }
902
903         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
904
905         if (surface->refcnt == 0)
906                 _tbm_surface_internal_destroy(surface);
907
908         _tbm_surface_mutex_unlock();
909 }
910
911 void
912 tbm_surface_internal_ref(tbm_surface_h surface)
913 {
914         _tbm_surface_mutex_lock();
915
916         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
917
918         surface->refcnt++;
919
920         TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
921
922         _tbm_surface_mutex_unlock();
923 }
924
925 void
926 tbm_surface_internal_unref(tbm_surface_h surface)
927 {
928         _tbm_surface_mutex_lock();
929
930         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
931
932         surface->refcnt--;
933
934         if (surface->refcnt > 0) {
935                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
936                 _tbm_surface_mutex_unlock();
937                 return;
938         }
939
940         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
941
942         if (surface->refcnt == 0)
943                 _tbm_surface_internal_destroy(surface);
944
945         _tbm_surface_mutex_unlock();
946 }
947
948 int
949 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
950 {
951         struct _tbm_surface *surf;
952         int num;
953
954         _tbm_surface_mutex_lock();
955
956         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
957
958         surf = (struct _tbm_surface *)surface;
959         num = surf->num_bos;
960
961         TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
962
963         _tbm_surface_mutex_unlock();
964
965         return num;
966 }
967
968 tbm_bo
969 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
970 {
971         struct _tbm_surface *surf;
972         tbm_bo bo;
973
974         _tbm_surface_mutex_lock();
975
976         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
977         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
978
979         surf = (struct _tbm_surface *)surface;
980         bo = surf->bos[bo_idx];
981
982         TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
983
984         _tbm_surface_mutex_unlock();
985
986         return bo;
987 }
988
989 unsigned int
990 tbm_surface_internal_get_size(tbm_surface_h surface)
991 {
992         struct _tbm_surface *surf;
993         unsigned int size;
994
995         _tbm_surface_mutex_lock();
996
997         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
998
999         surf = (struct _tbm_surface *)surface;
1000         size = surf->info.size;
1001
1002         TBM_TRACE("tbm_surface(%p) size(%u)\n", surface, size);
1003
1004         _tbm_surface_mutex_unlock();
1005
1006         return size;
1007 }
1008
1009 int
1010 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1011                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1012 {
1013         struct _tbm_surface *surf;
1014
1015         _tbm_surface_mutex_lock();
1016
1017         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1018         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1019
1020         surf = (struct _tbm_surface *)surface;
1021
1022         if (plane_idx >= surf->info.num_planes) {
1023                 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1024                 _tbm_surface_mutex_unlock();
1025                 return 0;
1026         }
1027
1028         if (size)
1029                 *size = surf->info.planes[plane_idx].size;
1030
1031         if (offset)
1032                 *offset = surf->info.planes[plane_idx].offset;
1033
1034         if (pitch)
1035                 *pitch = surf->info.planes[plane_idx].stride;
1036
1037         TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1038                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1039                                 surf->info.planes[plane_idx].stride);
1040
1041         _tbm_surface_mutex_unlock();
1042
1043         return 1;
1044 }
1045
1046 int
1047 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1048                               tbm_surface_info_s *info, int map)
1049 {
1050         struct _tbm_surface *surf;
1051         tbm_bo_handle bo_handles[4];
1052         int i, j;
1053
1054         _tbm_surface_mutex_lock();
1055
1056         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1057
1058         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1059
1060         surf = (struct _tbm_surface *)surface;
1061
1062         memset(info, 0x00, sizeof(tbm_surface_info_s));
1063         info->width = surf->info.width;
1064         info->height = surf->info.height;
1065         info->format = surf->info.format;
1066         info->bpp = surf->info.bpp;
1067         info->size = surf->info.size;
1068         info->num_planes = surf->info.num_planes;
1069
1070         if (map == 1) {
1071                 for (i = 0; i < surf->num_bos; i++) {
1072                         _tbm_surface_mutex_unlock();
1073                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1074                         _tbm_surface_mutex_lock();
1075                         if (bo_handles[i].ptr == NULL) {
1076                                 for (j = 0; j < i; j++)
1077                                         tbm_bo_unmap(surf->bos[j]);
1078
1079                                 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1080                                 _tbm_surface_mutex_unlock();
1081                                 return 0;
1082                         }
1083                 }
1084         } else {
1085                 for (i = 0; i < surf->num_bos; i++) {
1086                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1087                         if (bo_handles[i].ptr == NULL) {
1088                                 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1089                                 _tbm_surface_mutex_unlock();
1090                                 return 0;
1091                         }
1092                 }
1093         }
1094
1095         for (i = 0; i < surf->info.num_planes; i++) {
1096                 info->planes[i].size = surf->info.planes[i].size;
1097                 info->planes[i].offset = surf->info.planes[i].offset;
1098                 info->planes[i].stride = surf->info.planes[i].stride;
1099
1100                 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1101                         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1102                                               surf->info.planes[i].offset;
1103         }
1104
1105         TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1106
1107         _tbm_surface_mutex_unlock();
1108
1109         return 1;
1110 }
1111
1112 void
1113 tbm_surface_internal_unmap(tbm_surface_h surface)
1114 {
1115         struct _tbm_surface *surf;
1116         int i;
1117
1118         _tbm_surface_mutex_lock();
1119
1120         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1121
1122         surf = (struct _tbm_surface *)surface;
1123
1124         for (i = 0; i < surf->num_bos; i++)
1125                 tbm_bo_unmap(surf->bos[i]);
1126
1127         TBM_TRACE("tbm_surface(%p)\n", surface);
1128
1129         _tbm_surface_mutex_unlock();
1130 }
1131
1132 unsigned int
1133 tbm_surface_internal_get_width(tbm_surface_h surface)
1134 {
1135         struct _tbm_surface *surf;
1136         unsigned int width;
1137
1138         _tbm_surface_mutex_lock();
1139
1140         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1141
1142         surf = (struct _tbm_surface *)surface;
1143         width = surf->info.width;
1144
1145         TBM_TRACE("tbm_surface(%p) width(%u)\n", surface, width);
1146
1147         _tbm_surface_mutex_unlock();
1148
1149         return width;
1150 }
1151
1152 unsigned int
1153 tbm_surface_internal_get_height(tbm_surface_h surface)
1154 {
1155         struct _tbm_surface *surf;
1156         unsigned int height;
1157
1158         _tbm_surface_mutex_lock();
1159
1160         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1161
1162         surf = (struct _tbm_surface *)surface;
1163         height = surf->info.height;
1164
1165         TBM_TRACE("tbm_surface(%p) height(%u)\n", surface, height);
1166
1167         _tbm_surface_mutex_unlock();
1168
1169         return height;
1170
1171 }
1172
1173 tbm_format
1174 tbm_surface_internal_get_format(tbm_surface_h surface)
1175 {
1176         struct _tbm_surface *surf;
1177         tbm_format format;
1178
1179         _tbm_surface_mutex_lock();
1180
1181         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1182
1183         surf = (struct _tbm_surface *)surface;
1184         format = surf->info.format;
1185
1186         TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1187
1188         _tbm_surface_mutex_unlock();
1189
1190         return format;
1191 }
1192
1193 int
1194 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1195 {
1196         struct _tbm_surface *surf;
1197         int bo_idx;
1198
1199         _tbm_surface_mutex_lock();
1200
1201         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1202         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1203
1204         surf = (struct _tbm_surface *)surface;
1205         bo_idx = surf->planes_bo_idx[plane_idx];
1206
1207         TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1208
1209         _tbm_surface_mutex_unlock();
1210
1211         return bo_idx;
1212 }
1213
1214 int
1215 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1216                                    tbm_data_free data_free_func)
1217 {
1218         tbm_user_data *data;
1219
1220         _tbm_surface_mutex_lock();
1221
1222         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1223
1224         /* check if the data according to the key exist if so, return false. */
1225         data = user_data_lookup(&surface->user_data_list, key);
1226         if (data) {
1227                 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1228                 _tbm_surface_mutex_unlock();
1229                 return 0;
1230         }
1231
1232         data = user_data_create(key, data_free_func);
1233         if (!data) {
1234                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1235                 _tbm_surface_mutex_unlock();
1236                 return 0;
1237         }
1238
1239         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1240
1241         LIST_ADD(&data->item_link, &surface->user_data_list);
1242
1243         _tbm_surface_mutex_unlock();
1244
1245         return 1;
1246 }
1247
1248 int
1249 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1250                                    void *data)
1251 {
1252         tbm_user_data *old_data;
1253
1254         _tbm_surface_mutex_lock();
1255
1256         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1257
1258         old_data = user_data_lookup(&surface->user_data_list, key);
1259         if (!old_data) {
1260                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1261                 _tbm_surface_mutex_unlock();
1262                 return 0;
1263         }
1264
1265         if (old_data->data && old_data->free_func)
1266                 old_data->free_func(old_data->data);
1267
1268         old_data->data = data;
1269
1270         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1271
1272         _tbm_surface_mutex_unlock();
1273
1274         return 1;
1275 }
1276
1277 int
1278 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1279                                    void **data)
1280 {
1281         tbm_user_data *old_data;
1282
1283         _tbm_surface_mutex_lock();
1284
1285         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1286
1287         if (!data) {
1288                 TBM_LOG_E("error: tbm_surface(%p) key(%lu)\n", surface, key);
1289                 _tbm_surface_mutex_unlock();
1290                 return 0;
1291         }
1292         *data = NULL;
1293
1294         old_data = user_data_lookup(&surface->user_data_list, key);
1295         if (!old_data) {
1296                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1297                 _tbm_surface_mutex_unlock();
1298                 return 0;
1299         }
1300
1301         *data = old_data->data;
1302
1303         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1304
1305         _tbm_surface_mutex_unlock();
1306
1307         return 1;
1308 }
1309
1310 int
1311 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1312                                       unsigned long key)
1313 {
1314         tbm_user_data *old_data = (void *)0;
1315
1316         _tbm_surface_mutex_lock();
1317
1318         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1319
1320         old_data = user_data_lookup(&surface->user_data_list, key);
1321         if (!old_data) {
1322                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1323                 _tbm_surface_mutex_unlock();
1324                 return 0;
1325         }
1326
1327         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1328
1329         user_data_delete(old_data);
1330
1331         _tbm_surface_mutex_unlock();
1332
1333         return 1;
1334 }
1335
1336 /* LCOV_EXCL_START */
1337 unsigned int
1338 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1339 {
1340         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1341
1342         return surface->debug_pid;
1343 }
1344
1345 void
1346 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1347 {
1348         _tbm_surface_mutex_lock();
1349
1350         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1351
1352         surface->debug_pid = pid;
1353
1354         _tbm_surface_mutex_unlock();
1355 }
1356
1357 static tbm_surface_debug_data *
1358 _tbm_surface_internal_debug_data_create(char *key, char *value)
1359 {
1360         tbm_surface_debug_data *debug_data = NULL;
1361
1362         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1363         if (!debug_data)
1364                 return NULL;
1365
1366         if (key) debug_data->key = strdup(key);
1367         if (value) debug_data->value = strdup(value);
1368
1369         return debug_data;
1370 }
1371
1372 int
1373 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1374 {
1375         tbm_surface_debug_data *debug_data = NULL;
1376         tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1377         tbm_bufmgr bufmgr = NULL;
1378
1379         _tbm_surface_mutex_lock();
1380
1381         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1382         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1383
1384         bufmgr = surface->bufmgr;
1385
1386         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1387
1388         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1389                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1390                         if (old_data) {
1391                                 if (!strcmp(old_data->key, key)) {
1392                                         if (old_data->value && value && !strncmp(old_data->value, value, strlen(old_data->value))) {
1393                                                 TBM_TRACE("tbm_surface(%p) Already exist key(%s) and value(%s)!\n", surface, key, value);
1394                                                 goto add_debug_key_list;
1395                                         }
1396
1397                                         if (old_data->value)
1398                                                 free(old_data->value);
1399
1400                                         if (value)
1401                                                 old_data->value = strdup(value);
1402                                         else
1403                                                 old_data->value = NULL;
1404
1405                                         goto add_debug_key_list;
1406                                 }
1407                         }
1408                 }
1409         }
1410
1411         debug_data = _tbm_surface_internal_debug_data_create(key, value);
1412         if (!debug_data) {
1413                 TBM_LOG_E("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1414                 _tbm_surface_mutex_unlock();
1415                 return 0;
1416         }
1417
1418         TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1419
1420         LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1421
1422 add_debug_key_list:
1423         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1424                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1425                         if (!strcmp(old_data->key, key)) {
1426                                 _tbm_surface_mutex_unlock();
1427                                 return 1;
1428                         }
1429                 }
1430         }
1431
1432         debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1433         LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1434
1435         _tbm_surface_mutex_unlock();
1436
1437         return 1;
1438 }
1439
1440 char *
1441 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1442 {
1443         tbm_surface_debug_data *old_data = NULL;
1444
1445         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1446
1447         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1448                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1449                         if (!strcmp(old_data->key, key))
1450                                 return old_data->value;
1451                 }
1452         }
1453
1454         return NULL;
1455 }
1456
1457 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1458 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1459
1460 struct _tbm_surface_dump_buf_info {
1461         int index;
1462         tbm_bo bo;
1463         int size;
1464         int dirty;
1465         int dirty_shm;
1466         int shm_stride;
1467         int shm_h;
1468         char name[1024];
1469
1470         tbm_surface_info_s info;
1471
1472         struct list_head link;
1473 };
1474
1475 struct _tbm_surface_dump_info {
1476         char *path;  // copy???
1477         int dump_max;
1478         int count;
1479         struct list_head *link;
1480         struct list_head surface_list; /* link of surface */
1481 };
1482
1483 static tbm_surface_dump_info *g_dump_info = NULL;
1484 static const char *dump_postfix[2] = {"png", "yuv"};
1485
1486 static void
1487 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1488                                 void *data2, int size2, void *data3, int size3)
1489 {
1490         FILE *fp = fopen(file, "w+");
1491         TBM_RETURN_IF_FAIL(fp != NULL);
1492         unsigned int *blocks;
1493
1494         blocks = (unsigned int *)data1;
1495         fwrite(blocks, 1, size1, fp);
1496
1497         if (size2 > 0) {
1498                 blocks = (unsigned int *)data2;
1499                 fwrite(blocks, 1, size2, fp);
1500         }
1501
1502         if (size3 > 0) {
1503                 blocks = (unsigned int *)data3;
1504                 fwrite(blocks, 1, size3, fp);
1505         }
1506
1507         fclose(fp);
1508 }
1509
1510 static void
1511 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height)
1512 {
1513         unsigned int *blocks = (unsigned int *)data;
1514         FILE *fp = fopen(file, "wb");
1515         TBM_RETURN_IF_FAIL(fp != NULL);
1516         const int pixel_size = 4;       // RGBA
1517         png_bytep *row_pointers;
1518         int depth = 8, y;
1519
1520         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1521                                                         NULL, NULL, NULL);
1522         if (!pPngStruct) {
1523                 TBM_LOG_E("fail to create a png write structure.\n");
1524                 fclose(fp);
1525                 return;
1526         }
1527
1528         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1529         if (!pPngInfo) {
1530                 TBM_LOG_E("fail to create a png info structure.\n");
1531                 png_destroy_write_struct(&pPngStruct, NULL);
1532                 fclose(fp);
1533                 return;
1534         }
1535
1536         png_init_io(pPngStruct, fp);
1537         png_set_IHDR(pPngStruct,
1538                         pPngInfo,
1539                         width,
1540                         height,
1541                         depth,
1542                         PNG_COLOR_TYPE_RGBA,
1543                         PNG_INTERLACE_NONE,
1544                         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1545
1546         png_set_bgr(pPngStruct);
1547         png_write_info(pPngStruct, pPngInfo);
1548
1549         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1550         if (!row_pointers) {
1551                 TBM_LOG_E("fail to allocate the png row_pointers.\n");
1552                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1553                 fclose(fp);
1554                 return;
1555         }
1556
1557         for (y = 0; y < height; ++y) {
1558                 png_bytep row;
1559                 int x = 0;
1560
1561                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1562                 if (!row) {
1563                         TBM_LOG_E("fail to allocate the png row.\n");
1564                         for (x = 0; x < y; x++)
1565                                 png_free(pPngStruct, row_pointers[x]);
1566                         png_free(pPngStruct, row_pointers);
1567                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1568                         fclose(fp);
1569                         return;
1570                 }
1571                 row_pointers[y] = (png_bytep)row;
1572
1573                 for (x = 0; x < width; ++x) {
1574                         unsigned int curBlock = blocks[y * width + x];
1575
1576                         row[x * pixel_size] = (curBlock & 0xFF);
1577                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1578                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1579                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1580                 }
1581         }
1582
1583         png_write_image(pPngStruct, row_pointers);
1584         png_write_end(pPngStruct, pPngInfo);
1585
1586         for (y = 0; y < height; y++)
1587                 png_free(pPngStruct, row_pointers[y]);
1588         png_free(pPngStruct, row_pointers);
1589
1590         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1591
1592         fclose(fp);
1593 }
1594
1595 void
1596 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1597 {
1598         TBM_RETURN_IF_FAIL(path != NULL);
1599         TBM_RETURN_IF_FAIL(w > 0);
1600         TBM_RETURN_IF_FAIL(h > 0);
1601         TBM_RETURN_IF_FAIL(count > 0);
1602
1603         tbm_surface_dump_buf_info *buf_info = NULL;
1604         tbm_surface_h tbm_surface;
1605         tbm_surface_info_s info;
1606         int buffer_size, i;
1607
1608         /* check running */
1609         if (g_dump_info) {
1610                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1611                 return;
1612         }
1613
1614         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1615         TBM_RETURN_IF_FAIL(g_dump_info);
1616
1617         LIST_INITHEAD(&g_dump_info->surface_list);
1618         g_dump_info->count = 0;
1619         g_dump_info->dump_max = count;
1620
1621         /* get buffer size */
1622         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1623         if (tbm_surface == NULL) {
1624                 TBM_LOG_E("tbm_surface_create fail\n");
1625                 free(g_dump_info);
1626                 g_dump_info = NULL;
1627                 return;
1628         }
1629
1630         if (TBM_SURFACE_ERROR_NONE != tbm_surface_map(tbm_surface,
1631                                                 TBM_SURF_OPTION_READ, &info)) {
1632                 TBM_LOG_E("tbm_surface_map fail\n");
1633                 tbm_surface_destroy(tbm_surface);
1634                 free(g_dump_info);
1635                 g_dump_info = NULL;
1636                 return;
1637         }
1638         buffer_size = info.planes[0].stride * h;
1639
1640         tbm_surface_unmap(tbm_surface);
1641         tbm_surface_destroy(tbm_surface);
1642
1643         /* create dump lists */
1644         for (i = 0; i < count; i++) {
1645                 tbm_bo bo = NULL;
1646
1647                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1648                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1649
1650                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1651                 if (bo == NULL) {
1652                         TBM_LOG_E("fail to allocate the tbm_bo[%d]\n", i);
1653                         free(buf_info);
1654                         goto fail;
1655                 }
1656
1657                 buf_info->index = i;
1658                 buf_info->bo = bo;
1659                 buf_info->size = buffer_size;
1660
1661                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1662         }
1663
1664         g_dump_info->path = path;
1665         g_dump_info->link = &g_dump_info->surface_list;
1666
1667         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1668
1669         return;
1670
1671 fail:
1672         /* free resources */
1673         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1674                 tbm_surface_dump_buf_info *tmp;
1675
1676                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1677                         tbm_bo_unref(buf_info->bo);
1678                         LIST_DEL(&buf_info->link);
1679                         free(buf_info);
1680                 }
1681         }
1682
1683         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1684
1685         free(g_dump_info);
1686         g_dump_info = NULL;
1687
1688         return;
1689 }
1690
1691 void
1692 tbm_surface_internal_dump_end(void)
1693 {
1694         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1695         tbm_bo_handle bo_handle;
1696
1697         if (!g_dump_info)
1698                 return;
1699
1700         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1701                 free(g_dump_info);
1702                 g_dump_info = NULL;
1703                 return;
1704         }
1705
1706         /* make files */
1707         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1708                 char file[2048];
1709
1710                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1711                 if (bo_handle.ptr == NULL) {
1712                         tbm_bo_unref(buf_info->bo);
1713                         LIST_DEL(&buf_info->link);
1714                         free(buf_info);
1715                         continue;
1716                 }
1717
1718                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1719                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1720
1721                 if (buf_info->dirty) {
1722                         void *ptr1 = NULL, *ptr2 = NULL;
1723
1724                         switch (buf_info->info.format) {
1725                         case TBM_FORMAT_ARGB8888:
1726                         case TBM_FORMAT_XRGB8888:
1727                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1728                                                         buf_info->info.planes[0].stride >> 2,
1729                                                         buf_info->info.height);
1730                                 break;
1731                         case TBM_FORMAT_YVU420:
1732                         case TBM_FORMAT_YUV420:
1733                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1734                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1735                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1736                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1737                                                         ptr1,
1738                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1739                                                         ptr2,
1740                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1741                                 break;
1742                         case TBM_FORMAT_NV12:
1743                         case TBM_FORMAT_NV21:
1744                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1745                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1746                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1747                                                         ptr1,
1748                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1749                                                         NULL, 0);
1750                                 break;
1751                         case TBM_FORMAT_YUYV:
1752                         case TBM_FORMAT_UYVY:
1753                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1754                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1755                                                         NULL, 0, NULL, 0);
1756                                 break;
1757                         default:
1758                                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1759                                 break;
1760                         }
1761                 } else if (buf_info->dirty_shm)
1762                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1763                                                         buf_info->shm_stride >> 2,
1764                                                         buf_info->shm_h);
1765
1766                 tbm_bo_unmap(buf_info->bo);
1767                 tbm_bo_unref(buf_info->bo);
1768                 LIST_DEL(&buf_info->link);
1769                 free(buf_info);
1770         }
1771
1772         free(g_dump_info);
1773         g_dump_info = NULL;
1774
1775         TBM_LOG_I("Dump End..\n");
1776 }
1777
1778 void
1779 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1780 {
1781         TBM_RETURN_IF_FAIL(surface != NULL);
1782         TBM_RETURN_IF_FAIL(type != NULL);
1783
1784         tbm_surface_dump_buf_info *buf_info;
1785         struct list_head *next_link;
1786         tbm_surface_info_s info;
1787         tbm_bo_handle bo_handle;
1788         const char *postfix;
1789         int ret;
1790
1791         if (!g_dump_info)
1792                 return;
1793
1794         next_link = g_dump_info->link->next;
1795         TBM_RETURN_IF_FAIL(next_link != NULL);
1796
1797         if (next_link == &g_dump_info->surface_list) {
1798                 next_link = next_link->next;
1799                 TBM_RETURN_IF_FAIL(next_link != NULL);
1800         }
1801
1802         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1803         TBM_RETURN_IF_FAIL(buf_info != NULL);
1804
1805         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1806         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1807
1808         if (info.size > buf_info->size) {
1809                 TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1810                                 info.size, buf_info->size);
1811                 tbm_surface_unmap(surface);
1812                 return;
1813         }
1814
1815         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1816                 postfix = dump_postfix[0];
1817         else
1818                 postfix = dump_postfix[1];
1819
1820         /* make the file information */
1821         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1822
1823         /* dump */
1824         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1825         if (!bo_handle.ptr) {
1826                 TBM_LOG_E("fail to map bo");
1827                 tbm_surface_unmap(surface);
1828                 return;
1829         }
1830         memset(bo_handle.ptr, 0x00, buf_info->size);
1831
1832         switch (info.format) {
1833         case TBM_FORMAT_ARGB8888:
1834         case TBM_FORMAT_XRGB8888:
1835                 snprintf(buf_info->name, sizeof(buf_info->name),
1836                                 "%10.3f_%03d_%p-%s.%s",
1837                                  _tbm_surface_internal_get_time(),
1838                                  g_dump_info->count++, surface, type, postfix);
1839                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1840                 break;
1841         case TBM_FORMAT_YVU420:
1842         case TBM_FORMAT_YUV420:
1843                 snprintf(buf_info->name, sizeof(buf_info->name),
1844                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1845                                  _tbm_surface_internal_get_time(),
1846                                  g_dump_info->count++, type, info.planes[0].stride,
1847                                 info.height, FOURCC_STR(info.format), postfix);
1848                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1849                 bo_handle.ptr += info.planes[0].stride * info.height;
1850                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1851                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1852                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1853                 break;
1854         case TBM_FORMAT_NV12:
1855         case TBM_FORMAT_NV21:
1856                 snprintf(buf_info->name, sizeof(buf_info->name),
1857                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1858                                  _tbm_surface_internal_get_time(),
1859                                  g_dump_info->count++, type, info.planes[0].stride,
1860                                 info.height, FOURCC_STR(info.format), postfix);
1861                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1862                 bo_handle.ptr += info.planes[0].stride * info.height;
1863                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1864                 break;
1865         case TBM_FORMAT_YUYV:
1866         case TBM_FORMAT_UYVY:
1867                 snprintf(buf_info->name, sizeof(buf_info->name),
1868                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1869                                  _tbm_surface_internal_get_time(),
1870                                  g_dump_info->count++, type, info.planes[0].stride,
1871                                 info.height, FOURCC_STR(info.format), postfix);
1872                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1873                 break;
1874         default:
1875                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1876                 tbm_bo_unmap(buf_info->bo);
1877                 tbm_surface_unmap(surface);
1878                 return;
1879         }
1880
1881         tbm_bo_unmap(buf_info->bo);
1882
1883         tbm_surface_unmap(surface);
1884
1885         buf_info->dirty = 1;
1886         buf_info->dirty_shm = 0;
1887
1888         if (g_dump_info->count == 1000)
1889                 g_dump_info->count = 0;
1890
1891         g_dump_info->link = next_link;
1892
1893         TBM_LOG_I("Dump %s \n", buf_info->name);
1894 }
1895
1896 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
1897                                                 const char *type)
1898 {
1899         TBM_RETURN_IF_FAIL(ptr != NULL);
1900         TBM_RETURN_IF_FAIL(w > 0);
1901         TBM_RETURN_IF_FAIL(h > 0);
1902         TBM_RETURN_IF_FAIL(stride > 0);
1903         TBM_RETURN_IF_FAIL(type != NULL);
1904
1905         tbm_surface_dump_buf_info *buf_info;
1906         struct list_head *next_link;
1907         tbm_bo_handle bo_handle;
1908         int size;
1909
1910         if (!g_dump_info)
1911                 return;
1912
1913         next_link = g_dump_info->link->next;
1914         TBM_RETURN_IF_FAIL(next_link != NULL);
1915
1916         if (next_link == &g_dump_info->surface_list) {
1917                 next_link = next_link->next;
1918                 TBM_RETURN_IF_FAIL(next_link != NULL);
1919         }
1920
1921         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1922         TBM_RETURN_IF_FAIL(buf_info != NULL);
1923
1924         size = stride * h;
1925         if (size > buf_info->size) {
1926                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
1927                                 size, buf_info->size);
1928                 return;
1929         }
1930
1931         /* dump */
1932         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1933         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1934
1935         memset(bo_handle.ptr, 0x00, buf_info->size);
1936         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1937
1938         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1939                          _tbm_surface_internal_get_time(),
1940                          g_dump_info->count++, type, dump_postfix[0]);
1941         memcpy(bo_handle.ptr, ptr, size);
1942
1943         tbm_bo_unmap(buf_info->bo);
1944
1945         buf_info->dirty = 0;
1946         buf_info->dirty_shm = 1;
1947         buf_info->shm_stride = stride;
1948         buf_info->shm_h = h;
1949
1950         if (g_dump_info->count == 1000)
1951                 g_dump_info->count = 0;
1952
1953         g_dump_info->link = next_link;
1954
1955         TBM_LOG_I("Dump %s \n", buf_info->name);
1956 }
1957
1958 int
1959 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
1960 {
1961         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
1962         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1963         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
1964
1965         tbm_surface_info_s info;
1966         const char *postfix;
1967         int ret;
1968         char file[1024];
1969
1970         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1971         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
1972
1973         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1974                 postfix = dump_postfix[0];
1975         else
1976                 postfix = dump_postfix[1];
1977
1978         if (strcmp(postfix, type)) {
1979                 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
1980                 tbm_surface_unmap(surface);
1981                 return 0;
1982         }
1983
1984         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
1985
1986         if (!access(file, 0)) {
1987                 TBM_LOG_E("can't capture  buffer, exist file %s", file);
1988                 tbm_surface_unmap(surface);
1989                 return 0;
1990         }
1991
1992         switch (info.format) {
1993         case TBM_FORMAT_ARGB8888:
1994         case TBM_FORMAT_XRGB8888:
1995                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
1996                                                         info.planes[0].stride >> 2,
1997                                                         info.height);
1998                 break;
1999         case TBM_FORMAT_YVU420:
2000         case TBM_FORMAT_YUV420:
2001                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2002                                 info.planes[0].stride * info.height,
2003                                 info.planes[1].ptr,
2004                                 info.planes[1].stride * (info.height >> 1),
2005                                 info.planes[2].ptr,
2006                                 info.planes[2].stride * (info.height >> 1));
2007                 break;
2008         case TBM_FORMAT_NV12:
2009         case TBM_FORMAT_NV21:
2010                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2011                                         info.planes[0].stride * info.height,
2012                                         info.planes[1].ptr,
2013                                         info.planes[1].stride * (info.height >> 1),
2014                                         NULL, 0);
2015                 break;
2016         case TBM_FORMAT_YUYV:
2017         case TBM_FORMAT_UYVY:
2018                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2019                                         info.planes[0].stride * info.height,
2020                                         NULL, 0, NULL, 0);
2021                 break;
2022         default:
2023                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2024                 tbm_surface_unmap(surface);
2025                 return 0;
2026         }
2027
2028         tbm_surface_unmap(surface);
2029
2030         TBM_LOG_I("Capture %s \n", file);
2031
2032         return 1;
2033 }
2034
2035 int
2036 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2037                                                 const char *path, const char *name, const char *type)
2038 {
2039         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2040         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2041         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2042         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2043         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2044         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2045
2046         char file[1024];
2047
2048         if (strcmp(dump_postfix[0], type)) {
2049                 TBM_LOG_E("Not supported type:%s'", type);
2050                 return 0;
2051         }
2052
2053         if (!access(file, 0)) {
2054                 TBM_LOG_E("can't capture buffer, exist file %s", file);
2055                 return 0;
2056         }
2057
2058         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2059
2060         _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2061
2062         TBM_LOG_I("Capture %s \n", file);
2063
2064         return 1;
2065 }
2066 /*LCOV_EXCL_STOP*/