fix tbm_surface_internal_set_debug_data()
[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         surf->info.bpp = info->bpp;
806         surf->info.num_planes = info->num_planes;
807         surf->refcnt = 1;
808
809         /* get size, stride and offset */
810         for (i = 0; i < info->num_planes; i++) {
811                 surf->info.planes[i].offset = info->planes[i].offset;
812                 surf->info.planes[i].stride = info->planes[i].stride;
813
814                 if (info->planes[i].size > 0)
815                         surf->info.planes[i].size = info->planes[i].size;
816                 else
817                         surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
818
819                 if (num == 1)
820                         surf->planes_bo_idx[i] = 0;
821                 else
822                         surf->planes_bo_idx[i] = i;
823         }
824
825         if (info->size > 0) {
826                 surf->info.size = info->size;
827         } else {
828                 surf->info.size = 0;
829                 for (i = 0; i < info->num_planes; i++)
830                         surf->info.size += surf->info.planes[i].size;
831         }
832
833         surf->flags = TBM_BO_DEFAULT;
834
835         /* create only one bo */
836         surf->num_bos = num;
837         for (i = 0; i < num; i++) {
838                 if (bos[i] == NULL) {
839                         TBM_LOG_E("bos[%d] is null.\n", i);
840                         goto check_bo_fail;
841                 }
842
843                 surf->bos[i] = tbm_bo_ref(bos[i]);
844                 _tbm_bo_set_surface(bos[i], surf);
845         }
846
847         TBM_TRACE("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
848                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
849
850         LIST_INITHEAD(&surf->user_data_list);
851         LIST_INITHEAD(&surf->debug_data_list);
852
853         LIST_ADD(&surf->item_link, &mgr->surf_list);
854
855         _tbm_surface_mutex_unlock();
856
857         return surf;
858
859 check_bo_fail:
860         for (i = 0; i < num; i++) {
861                 if (surf->bos[i])
862                         tbm_bo_unref(surf->bos[i]);
863         }
864         free(surf);
865 alloc_surf_fail:
866 check_valid_fail:
867         if (bufmgr_initialized && mgr) {
868                 LIST_DELINIT(&mgr->surf_list);
869                 _deinit_surface_bufmgr();
870         }
871         _tbm_surface_mutex_unlock();
872
873         TBM_LOG_E("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
874                         info->width, info->height,
875                         _tbm_surface_internal_format_to_str(info->format), num);
876
877         return NULL;
878 }
879
880 void
881 tbm_surface_internal_destroy(tbm_surface_h surface)
882 {
883         _tbm_surface_mutex_lock();
884
885         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
886
887         surface->refcnt--;
888
889         if (surface->refcnt > 0) {
890                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
891                 _tbm_surface_mutex_unlock();
892                 return;
893         }
894
895         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
896
897         if (surface->refcnt == 0)
898                 _tbm_surface_internal_destroy(surface);
899
900         _tbm_surface_mutex_unlock();
901 }
902
903 void
904 tbm_surface_internal_ref(tbm_surface_h surface)
905 {
906         _tbm_surface_mutex_lock();
907
908         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
909
910         surface->refcnt++;
911
912         TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
913
914         _tbm_surface_mutex_unlock();
915 }
916
917 void
918 tbm_surface_internal_unref(tbm_surface_h surface)
919 {
920         _tbm_surface_mutex_lock();
921
922         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
923
924         surface->refcnt--;
925
926         if (surface->refcnt > 0) {
927                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
928                 _tbm_surface_mutex_unlock();
929                 return;
930         }
931
932         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
933
934         if (surface->refcnt == 0)
935                 _tbm_surface_internal_destroy(surface);
936
937         _tbm_surface_mutex_unlock();
938 }
939
940 int
941 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
942 {
943         struct _tbm_surface *surf;
944         int num;
945
946         _tbm_surface_mutex_lock();
947
948         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
949
950         surf = (struct _tbm_surface *)surface;
951         num = surf->num_bos;
952
953         TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
954
955         _tbm_surface_mutex_unlock();
956
957         return num;
958 }
959
960 tbm_bo
961 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
962 {
963         struct _tbm_surface *surf;
964         tbm_bo bo;
965
966         _tbm_surface_mutex_lock();
967
968         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
969         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
970
971         surf = (struct _tbm_surface *)surface;
972         bo = surf->bos[bo_idx];
973
974         TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
975
976         _tbm_surface_mutex_unlock();
977
978         return bo;
979 }
980
981 unsigned int
982 tbm_surface_internal_get_size(tbm_surface_h surface)
983 {
984         struct _tbm_surface *surf;
985         unsigned int size;
986
987         _tbm_surface_mutex_lock();
988
989         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
990
991         surf = (struct _tbm_surface *)surface;
992         size = surf->info.size;
993
994         TBM_TRACE("tbm_surface(%p) size(%u)\n", surface, size);
995
996         _tbm_surface_mutex_unlock();
997
998         return size;
999 }
1000
1001 int
1002 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1003                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1004 {
1005         struct _tbm_surface *surf;
1006
1007         _tbm_surface_mutex_lock();
1008
1009         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1010         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1011
1012         surf = (struct _tbm_surface *)surface;
1013
1014         if (plane_idx >= surf->info.num_planes) {
1015                 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1016                 _tbm_surface_mutex_unlock();
1017                 return 0;
1018         }
1019
1020         if (size)
1021                 *size = surf->info.planes[plane_idx].size;
1022
1023         if (offset)
1024                 *offset = surf->info.planes[plane_idx].offset;
1025
1026         if (pitch)
1027                 *pitch = surf->info.planes[plane_idx].stride;
1028
1029         TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1030                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1031                                 surf->info.planes[plane_idx].stride);
1032
1033         _tbm_surface_mutex_unlock();
1034
1035         return 1;
1036 }
1037
1038 int
1039 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1040                               tbm_surface_info_s *info, int map)
1041 {
1042         struct _tbm_surface *surf;
1043         tbm_bo_handle bo_handles[4];
1044         int i, j;
1045
1046         _tbm_surface_mutex_lock();
1047
1048         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1049
1050         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1051
1052         surf = (struct _tbm_surface *)surface;
1053
1054         memset(info, 0x00, sizeof(tbm_surface_info_s));
1055         info->width = surf->info.width;
1056         info->height = surf->info.height;
1057         info->format = surf->info.format;
1058         info->bpp = surf->info.bpp;
1059         info->size = surf->info.size;
1060         info->num_planes = surf->info.num_planes;
1061
1062         if (map == 1) {
1063                 for (i = 0; i < surf->num_bos; i++) {
1064                         _tbm_surface_mutex_unlock();
1065                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1066                         _tbm_surface_mutex_lock();
1067                         if (bo_handles[i].ptr == NULL) {
1068                                 for (j = 0; j < i; j++)
1069                                         tbm_bo_unmap(surf->bos[j]);
1070
1071                                 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1072                                 _tbm_surface_mutex_unlock();
1073                                 return 0;
1074                         }
1075                 }
1076         } else {
1077                 for (i = 0; i < surf->num_bos; i++) {
1078                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1079                         if (bo_handles[i].ptr == NULL) {
1080                                 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1081                                 _tbm_surface_mutex_unlock();
1082                                 return 0;
1083                         }
1084                 }
1085         }
1086
1087         for (i = 0; i < surf->info.num_planes; i++) {
1088                 info->planes[i].size = surf->info.planes[i].size;
1089                 info->planes[i].offset = surf->info.planes[i].offset;
1090                 info->planes[i].stride = surf->info.planes[i].stride;
1091
1092                 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1093                         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1094                                               surf->info.planes[i].offset;
1095         }
1096
1097         TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1098
1099         _tbm_surface_mutex_unlock();
1100
1101         return 1;
1102 }
1103
1104 void
1105 tbm_surface_internal_unmap(tbm_surface_h surface)
1106 {
1107         struct _tbm_surface *surf;
1108         int i;
1109
1110         _tbm_surface_mutex_lock();
1111
1112         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1113
1114         surf = (struct _tbm_surface *)surface;
1115
1116         for (i = 0; i < surf->num_bos; i++)
1117                 tbm_bo_unmap(surf->bos[i]);
1118
1119         TBM_TRACE("tbm_surface(%p)\n", surface);
1120
1121         _tbm_surface_mutex_unlock();
1122 }
1123
1124 unsigned int
1125 tbm_surface_internal_get_width(tbm_surface_h surface)
1126 {
1127         struct _tbm_surface *surf;
1128         unsigned int width;
1129
1130         _tbm_surface_mutex_lock();
1131
1132         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1133
1134         surf = (struct _tbm_surface *)surface;
1135         width = surf->info.width;
1136
1137         TBM_TRACE("tbm_surface(%p) width(%u)\n", surface, width);
1138
1139         _tbm_surface_mutex_unlock();
1140
1141         return width;
1142 }
1143
1144 unsigned int
1145 tbm_surface_internal_get_height(tbm_surface_h surface)
1146 {
1147         struct _tbm_surface *surf;
1148         unsigned int height;
1149
1150         _tbm_surface_mutex_lock();
1151
1152         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1153
1154         surf = (struct _tbm_surface *)surface;
1155         height = surf->info.height;
1156
1157         TBM_TRACE("tbm_surface(%p) height(%u)\n", surface, height);
1158
1159         _tbm_surface_mutex_unlock();
1160
1161         return height;
1162
1163 }
1164
1165 tbm_format
1166 tbm_surface_internal_get_format(tbm_surface_h surface)
1167 {
1168         struct _tbm_surface *surf;
1169         tbm_format format;
1170
1171         _tbm_surface_mutex_lock();
1172
1173         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1174
1175         surf = (struct _tbm_surface *)surface;
1176         format = surf->info.format;
1177
1178         TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1179
1180         _tbm_surface_mutex_unlock();
1181
1182         return format;
1183 }
1184
1185 int
1186 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1187 {
1188         struct _tbm_surface *surf;
1189         int bo_idx;
1190
1191         _tbm_surface_mutex_lock();
1192
1193         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1194         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1195
1196         surf = (struct _tbm_surface *)surface;
1197         bo_idx = surf->planes_bo_idx[plane_idx];
1198
1199         TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1200
1201         _tbm_surface_mutex_unlock();
1202
1203         return bo_idx;
1204 }
1205
1206 int
1207 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1208                                    tbm_data_free data_free_func)
1209 {
1210         tbm_user_data *data;
1211
1212         _tbm_surface_mutex_lock();
1213
1214         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1215
1216         /* check if the data according to the key exist if so, return false. */
1217         data = user_data_lookup(&surface->user_data_list, key);
1218         if (data) {
1219                 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1220                 _tbm_surface_mutex_unlock();
1221                 return 0;
1222         }
1223
1224         data = user_data_create(key, data_free_func);
1225         if (!data) {
1226                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1227                 _tbm_surface_mutex_unlock();
1228                 return 0;
1229         }
1230
1231         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1232
1233         LIST_ADD(&data->item_link, &surface->user_data_list);
1234
1235         _tbm_surface_mutex_unlock();
1236
1237         return 1;
1238 }
1239
1240 int
1241 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1242                                    void *data)
1243 {
1244         tbm_user_data *old_data;
1245
1246         _tbm_surface_mutex_lock();
1247
1248         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1249
1250         old_data = user_data_lookup(&surface->user_data_list, key);
1251         if (!old_data) {
1252                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1253                 _tbm_surface_mutex_unlock();
1254                 return 0;
1255         }
1256
1257         if (old_data->data && old_data->free_func)
1258                 old_data->free_func(old_data->data);
1259
1260         old_data->data = data;
1261
1262         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1263
1264         _tbm_surface_mutex_unlock();
1265
1266         return 1;
1267 }
1268
1269 int
1270 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1271                                    void **data)
1272 {
1273         tbm_user_data *old_data;
1274
1275         _tbm_surface_mutex_lock();
1276
1277         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1278
1279         if (!data) {
1280                 TBM_LOG_E("error: tbm_surface(%p) key(%lu)\n", surface, key);
1281                 _tbm_surface_mutex_unlock();
1282                 return 0;
1283         }
1284         *data = NULL;
1285
1286         old_data = user_data_lookup(&surface->user_data_list, key);
1287         if (!old_data) {
1288                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1289                 _tbm_surface_mutex_unlock();
1290                 return 0;
1291         }
1292
1293         *data = old_data->data;
1294
1295         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1296
1297         _tbm_surface_mutex_unlock();
1298
1299         return 1;
1300 }
1301
1302 int
1303 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1304                                       unsigned long key)
1305 {
1306         tbm_user_data *old_data = (void *)0;
1307
1308         _tbm_surface_mutex_lock();
1309
1310         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1311
1312         old_data = user_data_lookup(&surface->user_data_list, key);
1313         if (!old_data) {
1314                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1315                 _tbm_surface_mutex_unlock();
1316                 return 0;
1317         }
1318
1319         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1320
1321         user_data_delete(old_data);
1322
1323         _tbm_surface_mutex_unlock();
1324
1325         return 1;
1326 }
1327
1328 /* LCOV_EXCL_START */
1329 unsigned int
1330 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1331 {
1332         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1333
1334         return surface->debug_pid;
1335 }
1336
1337 void
1338 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1339 {
1340         _tbm_surface_mutex_lock();
1341
1342         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1343
1344         surface->debug_pid = pid;
1345
1346         _tbm_surface_mutex_unlock();
1347 }
1348
1349 static tbm_surface_debug_data *
1350 _tbm_surface_internal_debug_data_create(char *key, char *value)
1351 {
1352         tbm_surface_debug_data *debug_data = NULL;
1353
1354         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1355         if (!debug_data)
1356                 return NULL;
1357
1358         if (key) debug_data->key = strdup(key);
1359         if (value) debug_data->value = strdup(value);
1360
1361         return debug_data;
1362 }
1363
1364 int
1365 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1366 {
1367         tbm_surface_debug_data *debug_data = NULL;
1368         tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1369         tbm_bufmgr bufmgr = NULL;
1370
1371         _tbm_surface_mutex_lock();
1372
1373         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1374         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1375
1376         bufmgr = surface->bufmgr;
1377
1378         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1379
1380         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1381                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1382                         if (old_data) {
1383                                 if (!strcmp(old_data->key, key)) {
1384                                         if (old_data->value && value && !strncmp(old_data->value, value, strlen(old_data->value))) {
1385                                                 TBM_TRACE("tbm_surface(%p) Already exist key(%s) and value(%s)!\n", surface, key, value);
1386                                                 goto add_debug_key_list;
1387                                         }
1388
1389                                         if (old_data->value)
1390                                                 free(old_data->value);
1391
1392                                         if (value)
1393                                                 old_data->value = strdup(value);
1394                                         else
1395                                                 old_data->value = NULL;
1396
1397                                         goto add_debug_key_list;
1398                                 }
1399                         }
1400                 }
1401         }
1402
1403         debug_data = _tbm_surface_internal_debug_data_create(key, value);
1404         if (!debug_data) {
1405                 TBM_LOG_E("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1406                 _tbm_surface_mutex_unlock();
1407                 return 0;
1408         }
1409
1410         TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1411
1412         LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1413
1414 add_debug_key_list:
1415         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1416                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1417                         if (!strcmp(old_data->key, key)) {
1418                                 _tbm_surface_mutex_unlock();
1419                                 return 1;
1420                         }
1421                 }
1422         }
1423
1424         debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1425         LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1426
1427         _tbm_surface_mutex_unlock();
1428
1429         return 1;
1430 }
1431
1432 char *
1433 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1434 {
1435         tbm_surface_debug_data *old_data = NULL;
1436
1437         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1438
1439         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1440                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1441                         if (!strcmp(old_data->key, key))
1442                                 return old_data->value;
1443                 }
1444         }
1445
1446         return NULL;
1447 }
1448
1449 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1450 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1451
1452 struct _tbm_surface_dump_buf_info {
1453         int index;
1454         tbm_bo bo;
1455         int size;
1456         int dirty;
1457         int dirty_shm;
1458         int shm_stride;
1459         int shm_h;
1460         char name[1024];
1461
1462         tbm_surface_info_s info;
1463
1464         struct list_head link;
1465 };
1466
1467 struct _tbm_surface_dump_info {
1468         char *path;  // copy???
1469         int dump_max;
1470         int count;
1471         struct list_head *link;
1472         struct list_head surface_list; /* link of surface */
1473 };
1474
1475 static tbm_surface_dump_info *g_dump_info = NULL;
1476 static const char *dump_postfix[2] = {"png", "yuv"};
1477
1478 static void
1479 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1480                                 void *data2, int size2, void *data3, int size3)
1481 {
1482         FILE *fp = fopen(file, "w+");
1483         TBM_RETURN_IF_FAIL(fp != NULL);
1484         unsigned int *blocks;
1485
1486         blocks = (unsigned int *)data1;
1487         fwrite(blocks, 1, size1, fp);
1488
1489         if (size2 > 0) {
1490                 blocks = (unsigned int *)data2;
1491                 fwrite(blocks, 1, size2, fp);
1492         }
1493
1494         if (size3 > 0) {
1495                 blocks = (unsigned int *)data3;
1496                 fwrite(blocks, 1, size3, fp);
1497         }
1498
1499         fclose(fp);
1500 }
1501
1502 static void
1503 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height)
1504 {
1505         unsigned int *blocks = (unsigned int *)data;
1506         FILE *fp = fopen(file, "wb");
1507         TBM_RETURN_IF_FAIL(fp != NULL);
1508         const int pixel_size = 4;       // RGBA
1509         png_bytep *row_pointers;
1510         int depth = 8, y;
1511
1512         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1513                                                         NULL, NULL, NULL);
1514         if (!pPngStruct) {
1515                 TBM_LOG_E("fail to create a png write structure.\n");
1516                 fclose(fp);
1517                 return;
1518         }
1519
1520         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1521         if (!pPngInfo) {
1522                 TBM_LOG_E("fail to create a png info structure.\n");
1523                 png_destroy_write_struct(&pPngStruct, NULL);
1524                 fclose(fp);
1525                 return;
1526         }
1527
1528         png_init_io(pPngStruct, fp);
1529         png_set_IHDR(pPngStruct,
1530                         pPngInfo,
1531                         width,
1532                         height,
1533                         depth,
1534                         PNG_COLOR_TYPE_RGBA,
1535                         PNG_INTERLACE_NONE,
1536                         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1537
1538         png_set_bgr(pPngStruct);
1539         png_write_info(pPngStruct, pPngInfo);
1540
1541         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1542         if (!row_pointers) {
1543                 TBM_LOG_E("fail to allocate the png row_pointers.\n");
1544                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1545                 fclose(fp);
1546                 return;
1547         }
1548
1549         for (y = 0; y < height; ++y) {
1550                 png_bytep row;
1551                 int x = 0;
1552
1553                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1554                 if (!row) {
1555                         TBM_LOG_E("fail to allocate the png row.\n");
1556                         for (x = 0; x < y; x++)
1557                                 png_free(pPngStruct, row_pointers[x]);
1558                         png_free(pPngStruct, row_pointers);
1559                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1560                         fclose(fp);
1561                         return;
1562                 }
1563                 row_pointers[y] = (png_bytep)row;
1564
1565                 for (x = 0; x < width; ++x) {
1566                         unsigned int curBlock = blocks[y * width + x];
1567
1568                         row[x * pixel_size] = (curBlock & 0xFF);
1569                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1570                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1571                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1572                 }
1573         }
1574
1575         png_write_image(pPngStruct, row_pointers);
1576         png_write_end(pPngStruct, pPngInfo);
1577
1578         for (y = 0; y < height; y++)
1579                 png_free(pPngStruct, row_pointers[y]);
1580         png_free(pPngStruct, row_pointers);
1581
1582         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1583
1584         fclose(fp);
1585 }
1586
1587 void
1588 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1589 {
1590         TBM_RETURN_IF_FAIL(path != NULL);
1591         TBM_RETURN_IF_FAIL(w > 0);
1592         TBM_RETURN_IF_FAIL(h > 0);
1593         TBM_RETURN_IF_FAIL(count > 0);
1594
1595         tbm_surface_dump_buf_info *buf_info = NULL;
1596         tbm_surface_h tbm_surface;
1597         tbm_surface_info_s info;
1598         int buffer_size, i;
1599
1600         /* check running */
1601         if (g_dump_info) {
1602                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1603                 return;
1604         }
1605
1606         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1607         TBM_RETURN_IF_FAIL(g_dump_info);
1608
1609         LIST_INITHEAD(&g_dump_info->surface_list);
1610         g_dump_info->count = 0;
1611         g_dump_info->dump_max = count;
1612
1613         /* get buffer size */
1614         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1615         if (tbm_surface == NULL) {
1616                 TBM_LOG_E("tbm_surface_create fail\n");
1617                 free(g_dump_info);
1618                 g_dump_info = NULL;
1619                 return;
1620         }
1621
1622         if (TBM_SURFACE_ERROR_NONE != tbm_surface_map(tbm_surface,
1623                                                 TBM_SURF_OPTION_READ, &info)) {
1624                 TBM_LOG_E("tbm_surface_map fail\n");
1625                 tbm_surface_destroy(tbm_surface);
1626                 free(g_dump_info);
1627                 g_dump_info = NULL;
1628                 return;
1629         }
1630         buffer_size = info.planes[0].stride * h;
1631
1632         tbm_surface_unmap(tbm_surface);
1633         tbm_surface_destroy(tbm_surface);
1634
1635         /* create dump lists */
1636         for (i = 0; i < count; i++) {
1637                 tbm_bo bo = NULL;
1638
1639                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1640                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1641
1642                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1643                 if (bo == NULL) {
1644                         TBM_LOG_E("fail to allocate the tbm_bo[%d]\n", i);
1645                         free(buf_info);
1646                         goto fail;
1647                 }
1648
1649                 buf_info->index = i;
1650                 buf_info->bo = bo;
1651                 buf_info->size = buffer_size;
1652
1653                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1654         }
1655
1656         g_dump_info->path = path;
1657         g_dump_info->link = &g_dump_info->surface_list;
1658
1659         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1660
1661         return;
1662
1663 fail:
1664         /* free resources */
1665         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1666                 tbm_surface_dump_buf_info *tmp;
1667
1668                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1669                         tbm_bo_unref(buf_info->bo);
1670                         LIST_DEL(&buf_info->link);
1671                         free(buf_info);
1672                 }
1673         }
1674
1675         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1676
1677         free(g_dump_info);
1678         g_dump_info = NULL;
1679
1680         return;
1681 }
1682
1683 void
1684 tbm_surface_internal_dump_end(void)
1685 {
1686         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1687         tbm_bo_handle bo_handle;
1688
1689         if (!g_dump_info)
1690                 return;
1691
1692         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1693                 free(g_dump_info);
1694                 g_dump_info = NULL;
1695                 return;
1696         }
1697
1698         /* make files */
1699         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1700                 char file[2048];
1701
1702                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1703                 if (bo_handle.ptr == NULL) {
1704                         tbm_bo_unref(buf_info->bo);
1705                         LIST_DEL(&buf_info->link);
1706                         free(buf_info);
1707                         continue;
1708                 }
1709
1710                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1711                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1712
1713                 if (buf_info->dirty) {
1714                         void *ptr1 = NULL, *ptr2 = NULL;
1715
1716                         switch (buf_info->info.format) {
1717                         case TBM_FORMAT_ARGB8888:
1718                         case TBM_FORMAT_XRGB8888:
1719                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1720                                                         buf_info->info.planes[0].stride >> 2,
1721                                                         buf_info->info.height);
1722                                 break;
1723                         case TBM_FORMAT_YVU420:
1724                         case TBM_FORMAT_YUV420:
1725                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1726                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1727                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1728                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1729                                                         ptr1,
1730                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1731                                                         ptr2,
1732                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1733                                 break;
1734                         case TBM_FORMAT_NV12:
1735                         case TBM_FORMAT_NV21:
1736                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1737                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1738                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1739                                                         ptr1,
1740                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1741                                                         NULL, 0);
1742                                 break;
1743                         case TBM_FORMAT_YUYV:
1744                         case TBM_FORMAT_UYVY:
1745                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1746                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1747                                                         NULL, 0, NULL, 0);
1748                                 break;
1749                         default:
1750                                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1751                                 break;
1752                         }
1753                 } else if (buf_info->dirty_shm)
1754                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1755                                                         buf_info->shm_stride >> 2,
1756                                                         buf_info->shm_h);
1757
1758                 tbm_bo_unmap(buf_info->bo);
1759                 tbm_bo_unref(buf_info->bo);
1760                 LIST_DEL(&buf_info->link);
1761                 free(buf_info);
1762         }
1763
1764         free(g_dump_info);
1765         g_dump_info = NULL;
1766
1767         TBM_LOG_I("Dump End..\n");
1768 }
1769
1770 void
1771 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1772 {
1773         TBM_RETURN_IF_FAIL(surface != NULL);
1774         TBM_RETURN_IF_FAIL(type != NULL);
1775
1776         tbm_surface_dump_buf_info *buf_info;
1777         struct list_head *next_link;
1778         tbm_surface_info_s info;
1779         tbm_bo_handle bo_handle;
1780         const char *postfix;
1781         int ret;
1782
1783         if (!g_dump_info)
1784                 return;
1785
1786         next_link = g_dump_info->link->next;
1787         TBM_RETURN_IF_FAIL(next_link != NULL);
1788
1789         if (next_link == &g_dump_info->surface_list) {
1790                 next_link = next_link->next;
1791                 TBM_RETURN_IF_FAIL(next_link != NULL);
1792         }
1793
1794         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1795         TBM_RETURN_IF_FAIL(buf_info != NULL);
1796
1797         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1798         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1799
1800         if (info.size > buf_info->size) {
1801                 TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1802                                 info.size, buf_info->size);
1803                 tbm_surface_unmap(surface);
1804                 return;
1805         }
1806
1807         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1808                 postfix = dump_postfix[0];
1809         else
1810                 postfix = dump_postfix[1];
1811
1812         /* make the file information */
1813         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1814
1815         /* dump */
1816         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1817         if (!bo_handle.ptr) {
1818                 TBM_LOG_E("fail to map bo");
1819                 tbm_surface_unmap(surface);
1820                 return;
1821         }
1822         memset(bo_handle.ptr, 0x00, buf_info->size);
1823
1824         switch (info.format) {
1825         case TBM_FORMAT_ARGB8888:
1826         case TBM_FORMAT_XRGB8888:
1827                 snprintf(buf_info->name, sizeof(buf_info->name),
1828                                 "%10.3f_%03d_%p-%s.%s",
1829                                  _tbm_surface_internal_get_time(),
1830                                  g_dump_info->count++, surface, type, postfix);
1831                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1832                 break;
1833         case TBM_FORMAT_YVU420:
1834         case TBM_FORMAT_YUV420:
1835                 snprintf(buf_info->name, sizeof(buf_info->name),
1836                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1837                                  _tbm_surface_internal_get_time(),
1838                                  g_dump_info->count++, type, info.planes[0].stride,
1839                                 info.height, FOURCC_STR(info.format), postfix);
1840                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1841                 bo_handle.ptr += info.planes[0].stride * info.height;
1842                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1843                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1844                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1845                 break;
1846         case TBM_FORMAT_NV12:
1847         case TBM_FORMAT_NV21:
1848                 snprintf(buf_info->name, sizeof(buf_info->name),
1849                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1850                                  _tbm_surface_internal_get_time(),
1851                                  g_dump_info->count++, type, info.planes[0].stride,
1852                                 info.height, FOURCC_STR(info.format), postfix);
1853                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1854                 bo_handle.ptr += info.planes[0].stride * info.height;
1855                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1856                 break;
1857         case TBM_FORMAT_YUYV:
1858         case TBM_FORMAT_UYVY:
1859                 snprintf(buf_info->name, sizeof(buf_info->name),
1860                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1861                                  _tbm_surface_internal_get_time(),
1862                                  g_dump_info->count++, type, info.planes[0].stride,
1863                                 info.height, FOURCC_STR(info.format), postfix);
1864                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1865                 break;
1866         default:
1867                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1868                 tbm_bo_unmap(buf_info->bo);
1869                 tbm_surface_unmap(surface);
1870                 return;
1871         }
1872
1873         tbm_bo_unmap(buf_info->bo);
1874
1875         tbm_surface_unmap(surface);
1876
1877         buf_info->dirty = 1;
1878         buf_info->dirty_shm = 0;
1879
1880         if (g_dump_info->count == 1000)
1881                 g_dump_info->count = 0;
1882
1883         g_dump_info->link = next_link;
1884
1885         TBM_LOG_I("Dump %s \n", buf_info->name);
1886 }
1887
1888 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
1889                                                 const char *type)
1890 {
1891         TBM_RETURN_IF_FAIL(ptr != NULL);
1892         TBM_RETURN_IF_FAIL(w > 0);
1893         TBM_RETURN_IF_FAIL(h > 0);
1894         TBM_RETURN_IF_FAIL(stride > 0);
1895         TBM_RETURN_IF_FAIL(type != NULL);
1896
1897         tbm_surface_dump_buf_info *buf_info;
1898         struct list_head *next_link;
1899         tbm_bo_handle bo_handle;
1900         int size;
1901
1902         if (!g_dump_info)
1903                 return;
1904
1905         next_link = g_dump_info->link->next;
1906         TBM_RETURN_IF_FAIL(next_link != NULL);
1907
1908         if (next_link == &g_dump_info->surface_list) {
1909                 next_link = next_link->next;
1910                 TBM_RETURN_IF_FAIL(next_link != NULL);
1911         }
1912
1913         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1914         TBM_RETURN_IF_FAIL(buf_info != NULL);
1915
1916         size = stride * h;
1917         if (size > buf_info->size) {
1918                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
1919                                 size, buf_info->size);
1920                 return;
1921         }
1922
1923         /* dump */
1924         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1925         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1926
1927         memset(bo_handle.ptr, 0x00, buf_info->size);
1928         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1929
1930         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1931                          _tbm_surface_internal_get_time(),
1932                          g_dump_info->count++, type, dump_postfix[0]);
1933         memcpy(bo_handle.ptr, ptr, size);
1934
1935         tbm_bo_unmap(buf_info->bo);
1936
1937         buf_info->dirty = 0;
1938         buf_info->dirty_shm = 1;
1939         buf_info->shm_stride = stride;
1940         buf_info->shm_h = h;
1941
1942         if (g_dump_info->count == 1000)
1943                 g_dump_info->count = 0;
1944
1945         g_dump_info->link = next_link;
1946
1947         TBM_LOG_I("Dump %s \n", buf_info->name);
1948 }
1949
1950 int
1951 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
1952 {
1953         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
1954         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1955         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
1956
1957         tbm_surface_info_s info;
1958         const char *postfix;
1959         int ret;
1960         char file[1024];
1961
1962         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1963         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
1964
1965         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1966                 postfix = dump_postfix[0];
1967         else
1968                 postfix = dump_postfix[1];
1969
1970         if (strcmp(postfix, type)) {
1971                 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
1972                 tbm_surface_unmap(surface);
1973                 return 0;
1974         }
1975
1976         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
1977
1978         if (!access(file, 0)) {
1979                 TBM_LOG_E("can't capture  buffer, exist file %s", file);
1980                 tbm_surface_unmap(surface);
1981                 return 0;
1982         }
1983
1984         switch (info.format) {
1985         case TBM_FORMAT_ARGB8888:
1986         case TBM_FORMAT_XRGB8888:
1987                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
1988                                                         info.planes[0].stride >> 2,
1989                                                         info.height);
1990                 break;
1991         case TBM_FORMAT_YVU420:
1992         case TBM_FORMAT_YUV420:
1993                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
1994                                 info.planes[0].stride * info.height,
1995                                 info.planes[1].ptr,
1996                                 info.planes[1].stride * (info.height >> 1),
1997                                 info.planes[2].ptr,
1998                                 info.planes[2].stride * (info.height >> 1));
1999                 break;
2000         case TBM_FORMAT_NV12:
2001         case TBM_FORMAT_NV21:
2002                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2003                                         info.planes[0].stride * info.height,
2004                                         info.planes[1].ptr,
2005                                         info.planes[1].stride * (info.height >> 1),
2006                                         NULL, 0);
2007                 break;
2008         case TBM_FORMAT_YUYV:
2009         case TBM_FORMAT_UYVY:
2010                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2011                                         info.planes[0].stride * info.height,
2012                                         NULL, 0, NULL, 0);
2013                 break;
2014         default:
2015                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2016                 tbm_surface_unmap(surface);
2017                 return 0;
2018         }
2019
2020         tbm_surface_unmap(surface);
2021
2022         TBM_LOG_I("Capture %s \n", file);
2023
2024         return 1;
2025 }
2026
2027 int
2028 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2029                                                 const char *path, const char *name, const char *type)
2030 {
2031         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2032         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2033         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2034         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2035         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2036         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2037
2038         char file[1024];
2039
2040         if (strcmp(dump_postfix[0], type)) {
2041                 TBM_LOG_E("Not supported type:%s'", type);
2042                 return 0;
2043         }
2044
2045         if (!access(file, 0)) {
2046                 TBM_LOG_E("can't capture buffer, exist file %s", file);
2047                 return 0;
2048         }
2049
2050         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2051
2052         _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2053
2054         TBM_LOG_I("Capture %s \n", file);
2055
2056         return 1;
2057 }
2058 /*LCOV_EXCL_STOP*/