use TBM_LOG_E at error case in tbm_surface_internal.c
[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                         }
1398                 }
1399         }
1400
1401         debug_data = _tbm_surface_internal_debug_data_create(key, value);
1402         if (!debug_data) {
1403                 TBM_LOG_E("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1404                 _tbm_surface_mutex_unlock();
1405                 return 0;
1406         }
1407
1408         TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1409
1410         LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1411
1412 add_debug_key_list:
1413         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1414                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1415                         if (!strcmp(old_data->key, key)) {
1416                                 _tbm_surface_mutex_unlock();
1417                                 return 1;
1418                         }
1419                 }
1420         }
1421
1422         debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1423         LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1424
1425         _tbm_surface_mutex_unlock();
1426
1427         return 1;
1428 }
1429
1430 char *
1431 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1432 {
1433         tbm_surface_debug_data *old_data = NULL;
1434
1435         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1436
1437         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1438                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1439                         if (!strcmp(old_data->key, key))
1440                                 return old_data->value;
1441                 }
1442         }
1443
1444         return NULL;
1445 }
1446
1447 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1448 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1449
1450 struct _tbm_surface_dump_buf_info {
1451         int index;
1452         tbm_bo bo;
1453         int size;
1454         int dirty;
1455         int dirty_shm;
1456         int shm_stride;
1457         int shm_h;
1458         char name[1024];
1459
1460         tbm_surface_info_s info;
1461
1462         struct list_head link;
1463 };
1464
1465 struct _tbm_surface_dump_info {
1466         char *path;  // copy???
1467         int dump_max;
1468         int count;
1469         struct list_head *link;
1470         struct list_head surface_list; /* link of surface */
1471 };
1472
1473 static tbm_surface_dump_info *g_dump_info = NULL;
1474 static const char *dump_postfix[2] = {"png", "yuv"};
1475
1476 static void
1477 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1478                                 void *data2, int size2, void *data3, int size3)
1479 {
1480         FILE *fp = fopen(file, "w+");
1481         TBM_RETURN_IF_FAIL(fp != NULL);
1482         unsigned int *blocks;
1483
1484         blocks = (unsigned int *)data1;
1485         fwrite(blocks, 1, size1, fp);
1486
1487         if (size2 > 0) {
1488                 blocks = (unsigned int *)data2;
1489                 fwrite(blocks, 1, size2, fp);
1490         }
1491
1492         if (size3 > 0) {
1493                 blocks = (unsigned int *)data3;
1494                 fwrite(blocks, 1, size3, fp);
1495         }
1496
1497         fclose(fp);
1498 }
1499
1500 static void
1501 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height)
1502 {
1503         unsigned int *blocks = (unsigned int *)data;
1504         FILE *fp = fopen(file, "wb");
1505         TBM_RETURN_IF_FAIL(fp != NULL);
1506         const int pixel_size = 4;       // RGBA
1507         png_bytep *row_pointers;
1508         int depth = 8, y;
1509
1510         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1511                                                         NULL, NULL, NULL);
1512         if (!pPngStruct) {
1513                 TBM_LOG_E("fail to create a png write structure.\n");
1514                 fclose(fp);
1515                 return;
1516         }
1517
1518         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1519         if (!pPngInfo) {
1520                 TBM_LOG_E("fail to create a png info structure.\n");
1521                 png_destroy_write_struct(&pPngStruct, NULL);
1522                 fclose(fp);
1523                 return;
1524         }
1525
1526         png_init_io(pPngStruct, fp);
1527         png_set_IHDR(pPngStruct,
1528                         pPngInfo,
1529                         width,
1530                         height,
1531                         depth,
1532                         PNG_COLOR_TYPE_RGBA,
1533                         PNG_INTERLACE_NONE,
1534                         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1535
1536         png_set_bgr(pPngStruct);
1537         png_write_info(pPngStruct, pPngInfo);
1538
1539         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1540         if (!row_pointers) {
1541                 TBM_LOG_E("fail to allocate the png row_pointers.\n");
1542                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1543                 fclose(fp);
1544                 return;
1545         }
1546
1547         for (y = 0; y < height; ++y) {
1548                 png_bytep row;
1549                 int x = 0;
1550
1551                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1552                 if (!row) {
1553                         TBM_LOG_E("fail to allocate the png row.\n");
1554                         for (x = 0; x < y; x++)
1555                                 png_free(pPngStruct, row_pointers[x]);
1556                         png_free(pPngStruct, row_pointers);
1557                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1558                         fclose(fp);
1559                         return;
1560                 }
1561                 row_pointers[y] = (png_bytep)row;
1562
1563                 for (x = 0; x < width; ++x) {
1564                         unsigned int curBlock = blocks[y * width + x];
1565
1566                         row[x * pixel_size] = (curBlock & 0xFF);
1567                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1568                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1569                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1570                 }
1571         }
1572
1573         png_write_image(pPngStruct, row_pointers);
1574         png_write_end(pPngStruct, pPngInfo);
1575
1576         for (y = 0; y < height; y++)
1577                 png_free(pPngStruct, row_pointers[y]);
1578         png_free(pPngStruct, row_pointers);
1579
1580         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1581
1582         fclose(fp);
1583 }
1584
1585 void
1586 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1587 {
1588         TBM_RETURN_IF_FAIL(path != NULL);
1589         TBM_RETURN_IF_FAIL(w > 0);
1590         TBM_RETURN_IF_FAIL(h > 0);
1591         TBM_RETURN_IF_FAIL(count > 0);
1592
1593         tbm_surface_dump_buf_info *buf_info = NULL;
1594         tbm_surface_h tbm_surface;
1595         tbm_surface_info_s info;
1596         int buffer_size, i;
1597
1598         /* check running */
1599         if (g_dump_info) {
1600                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1601                 return;
1602         }
1603
1604         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1605         TBM_RETURN_IF_FAIL(g_dump_info);
1606
1607         LIST_INITHEAD(&g_dump_info->surface_list);
1608         g_dump_info->count = 0;
1609         g_dump_info->dump_max = count;
1610
1611         /* get buffer size */
1612         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1613         if (tbm_surface == NULL) {
1614                 TBM_LOG_E("tbm_surface_create fail\n");
1615                 free(g_dump_info);
1616                 g_dump_info = NULL;
1617                 return;
1618         }
1619
1620         if (TBM_SURFACE_ERROR_NONE != tbm_surface_map(tbm_surface,
1621                                                 TBM_SURF_OPTION_READ, &info)) {
1622                 TBM_LOG_E("tbm_surface_map fail\n");
1623                 tbm_surface_destroy(tbm_surface);
1624                 free(g_dump_info);
1625                 g_dump_info = NULL;
1626                 return;
1627         }
1628         buffer_size = info.planes[0].stride * h;
1629
1630         tbm_surface_unmap(tbm_surface);
1631         tbm_surface_destroy(tbm_surface);
1632
1633         /* create dump lists */
1634         for (i = 0; i < count; i++) {
1635                 tbm_bo bo = NULL;
1636
1637                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1638                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1639
1640                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1641                 if (bo == NULL) {
1642                         TBM_LOG_E("fail to allocate the tbm_bo[%d]\n", i);
1643                         free(buf_info);
1644                         goto fail;
1645                 }
1646
1647                 buf_info->index = i;
1648                 buf_info->bo = bo;
1649                 buf_info->size = buffer_size;
1650
1651                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1652         }
1653
1654         g_dump_info->path = path;
1655         g_dump_info->link = &g_dump_info->surface_list;
1656
1657         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1658
1659         return;
1660
1661 fail:
1662         /* free resources */
1663         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1664                 tbm_surface_dump_buf_info *tmp;
1665
1666                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1667                         tbm_bo_unref(buf_info->bo);
1668                         LIST_DEL(&buf_info->link);
1669                         free(buf_info);
1670                 }
1671         }
1672
1673         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1674
1675         free(g_dump_info);
1676         g_dump_info = NULL;
1677
1678         return;
1679 }
1680
1681 void
1682 tbm_surface_internal_dump_end(void)
1683 {
1684         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1685         tbm_bo_handle bo_handle;
1686
1687         if (!g_dump_info)
1688                 return;
1689
1690         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1691                 free(g_dump_info);
1692                 g_dump_info = NULL;
1693                 return;
1694         }
1695
1696         /* make files */
1697         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1698                 char file[2048];
1699
1700                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1701                 if (bo_handle.ptr == NULL) {
1702                         tbm_bo_unref(buf_info->bo);
1703                         LIST_DEL(&buf_info->link);
1704                         free(buf_info);
1705                         continue;
1706                 }
1707
1708                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1709                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1710
1711                 if (buf_info->dirty) {
1712                         void *ptr1 = NULL, *ptr2 = NULL;
1713
1714                         switch (buf_info->info.format) {
1715                         case TBM_FORMAT_ARGB8888:
1716                         case TBM_FORMAT_XRGB8888:
1717                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1718                                                         buf_info->info.planes[0].stride >> 2,
1719                                                         buf_info->info.height);
1720                                 break;
1721                         case TBM_FORMAT_YVU420:
1722                         case TBM_FORMAT_YUV420:
1723                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1724                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1725                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1726                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1727                                                         ptr1,
1728                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1729                                                         ptr2,
1730                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1731                                 break;
1732                         case TBM_FORMAT_NV12:
1733                         case TBM_FORMAT_NV21:
1734                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
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                                                         NULL, 0);
1740                                 break;
1741                         case TBM_FORMAT_YUYV:
1742                         case TBM_FORMAT_UYVY:
1743                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1744                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1745                                                         NULL, 0, NULL, 0);
1746                                 break;
1747                         default:
1748                                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1749                                 break;
1750                         }
1751                 } else if (buf_info->dirty_shm)
1752                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1753                                                         buf_info->shm_stride >> 2,
1754                                                         buf_info->shm_h);
1755
1756                 tbm_bo_unmap(buf_info->bo);
1757                 tbm_bo_unref(buf_info->bo);
1758                 LIST_DEL(&buf_info->link);
1759                 free(buf_info);
1760         }
1761
1762         free(g_dump_info);
1763         g_dump_info = NULL;
1764
1765         TBM_LOG_I("Dump End..\n");
1766 }
1767
1768 void
1769 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1770 {
1771         TBM_RETURN_IF_FAIL(surface != NULL);
1772         TBM_RETURN_IF_FAIL(type != NULL);
1773
1774         tbm_surface_dump_buf_info *buf_info;
1775         struct list_head *next_link;
1776         tbm_surface_info_s info;
1777         tbm_bo_handle bo_handle;
1778         const char *postfix;
1779         int ret;
1780
1781         if (!g_dump_info)
1782                 return;
1783
1784         next_link = g_dump_info->link->next;
1785         TBM_RETURN_IF_FAIL(next_link != NULL);
1786
1787         if (next_link == &g_dump_info->surface_list) {
1788                 next_link = next_link->next;
1789                 TBM_RETURN_IF_FAIL(next_link != NULL);
1790         }
1791
1792         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1793         TBM_RETURN_IF_FAIL(buf_info != NULL);
1794
1795         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1796         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1797
1798         if (info.size > buf_info->size) {
1799                 TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1800                                 info.size, buf_info->size);
1801                 tbm_surface_unmap(surface);
1802                 return;
1803         }
1804
1805         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1806                 postfix = dump_postfix[0];
1807         else
1808                 postfix = dump_postfix[1];
1809
1810         /* make the file information */
1811         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1812
1813         /* dump */
1814         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1815         if (!bo_handle.ptr) {
1816                 TBM_LOG_E("fail to map bo");
1817                 tbm_surface_unmap(surface);
1818                 return;
1819         }
1820         memset(bo_handle.ptr, 0x00, buf_info->size);
1821
1822         switch (info.format) {
1823         case TBM_FORMAT_ARGB8888:
1824         case TBM_FORMAT_XRGB8888:
1825                 snprintf(buf_info->name, sizeof(buf_info->name),
1826                                 "%10.3f_%03d_%p-%s.%s",
1827                                  _tbm_surface_internal_get_time(),
1828                                  g_dump_info->count++, surface, type, postfix);
1829                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1830                 break;
1831         case TBM_FORMAT_YVU420:
1832         case TBM_FORMAT_YUV420:
1833                 snprintf(buf_info->name, sizeof(buf_info->name),
1834                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1835                                  _tbm_surface_internal_get_time(),
1836                                  g_dump_info->count++, type, info.planes[0].stride,
1837                                 info.height, FOURCC_STR(info.format), postfix);
1838                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1839                 bo_handle.ptr += info.planes[0].stride * info.height;
1840                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1841                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1842                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1843                 break;
1844         case TBM_FORMAT_NV12:
1845         case TBM_FORMAT_NV21:
1846                 snprintf(buf_info->name, sizeof(buf_info->name),
1847                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1848                                  _tbm_surface_internal_get_time(),
1849                                  g_dump_info->count++, type, info.planes[0].stride,
1850                                 info.height, FOURCC_STR(info.format), postfix);
1851                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1852                 bo_handle.ptr += info.planes[0].stride * info.height;
1853                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1854                 break;
1855         case TBM_FORMAT_YUYV:
1856         case TBM_FORMAT_UYVY:
1857                 snprintf(buf_info->name, sizeof(buf_info->name),
1858                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1859                                  _tbm_surface_internal_get_time(),
1860                                  g_dump_info->count++, type, info.planes[0].stride,
1861                                 info.height, FOURCC_STR(info.format), postfix);
1862                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1863                 break;
1864         default:
1865                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1866                 tbm_bo_unmap(buf_info->bo);
1867                 tbm_surface_unmap(surface);
1868                 return;
1869         }
1870
1871         tbm_bo_unmap(buf_info->bo);
1872
1873         tbm_surface_unmap(surface);
1874
1875         buf_info->dirty = 1;
1876         buf_info->dirty_shm = 0;
1877
1878         if (g_dump_info->count == 1000)
1879                 g_dump_info->count = 0;
1880
1881         g_dump_info->link = next_link;
1882
1883         TBM_LOG_I("Dump %s \n", buf_info->name);
1884 }
1885
1886 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
1887                                                 const char *type)
1888 {
1889         TBM_RETURN_IF_FAIL(ptr != NULL);
1890         TBM_RETURN_IF_FAIL(w > 0);
1891         TBM_RETURN_IF_FAIL(h > 0);
1892         TBM_RETURN_IF_FAIL(stride > 0);
1893         TBM_RETURN_IF_FAIL(type != NULL);
1894
1895         tbm_surface_dump_buf_info *buf_info;
1896         struct list_head *next_link;
1897         tbm_bo_handle bo_handle;
1898         int size;
1899
1900         if (!g_dump_info)
1901                 return;
1902
1903         next_link = g_dump_info->link->next;
1904         TBM_RETURN_IF_FAIL(next_link != NULL);
1905
1906         if (next_link == &g_dump_info->surface_list) {
1907                 next_link = next_link->next;
1908                 TBM_RETURN_IF_FAIL(next_link != NULL);
1909         }
1910
1911         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1912         TBM_RETURN_IF_FAIL(buf_info != NULL);
1913
1914         size = stride * h;
1915         if (size > buf_info->size) {
1916                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
1917                                 size, buf_info->size);
1918                 return;
1919         }
1920
1921         /* dump */
1922         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1923         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1924
1925         memset(bo_handle.ptr, 0x00, buf_info->size);
1926         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1927
1928         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1929                          _tbm_surface_internal_get_time(),
1930                          g_dump_info->count++, type, dump_postfix[0]);
1931         memcpy(bo_handle.ptr, ptr, size);
1932
1933         tbm_bo_unmap(buf_info->bo);
1934
1935         buf_info->dirty = 0;
1936         buf_info->dirty_shm = 1;
1937         buf_info->shm_stride = stride;
1938         buf_info->shm_h = h;
1939
1940         if (g_dump_info->count == 1000)
1941                 g_dump_info->count = 0;
1942
1943         g_dump_info->link = next_link;
1944
1945         TBM_LOG_I("Dump %s \n", buf_info->name);
1946 }
1947
1948 int
1949 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
1950 {
1951         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
1952         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1953         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
1954
1955         tbm_surface_info_s info;
1956         const char *postfix;
1957         int ret;
1958         char file[1024];
1959
1960         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1961         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
1962
1963         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1964                 postfix = dump_postfix[0];
1965         else
1966                 postfix = dump_postfix[1];
1967
1968         if (strcmp(postfix, type)) {
1969                 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
1970                 tbm_surface_unmap(surface);
1971                 return 0;
1972         }
1973
1974         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
1975
1976         if (!access(file, 0)) {
1977                 TBM_LOG_E("can't capture  buffer, exist file %s", file);
1978                 tbm_surface_unmap(surface);
1979                 return 0;
1980         }
1981
1982         switch (info.format) {
1983         case TBM_FORMAT_ARGB8888:
1984         case TBM_FORMAT_XRGB8888:
1985                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
1986                                                         info.planes[0].stride >> 2,
1987                                                         info.height);
1988                 break;
1989         case TBM_FORMAT_YVU420:
1990         case TBM_FORMAT_YUV420:
1991                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
1992                                 info.planes[0].stride * info.height,
1993                                 info.planes[1].ptr,
1994                                 info.planes[1].stride * (info.height >> 1),
1995                                 info.planes[2].ptr,
1996                                 info.planes[2].stride * (info.height >> 1));
1997                 break;
1998         case TBM_FORMAT_NV12:
1999         case TBM_FORMAT_NV21:
2000                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2001                                         info.planes[0].stride * info.height,
2002                                         info.planes[1].ptr,
2003                                         info.planes[1].stride * (info.height >> 1),
2004                                         NULL, 0);
2005                 break;
2006         case TBM_FORMAT_YUYV:
2007         case TBM_FORMAT_UYVY:
2008                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2009                                         info.planes[0].stride * info.height,
2010                                         NULL, 0, NULL, 0);
2011                 break;
2012         default:
2013                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2014                 tbm_surface_unmap(surface);
2015                 return 0;
2016         }
2017
2018         tbm_surface_unmap(surface);
2019
2020         TBM_LOG_I("Capture %s \n", file);
2021
2022         return 1;
2023 }
2024
2025 int
2026 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2027                                                 const char *path, const char *name, const char *type)
2028 {
2029         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2030         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2031         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2032         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2033         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2034         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2035
2036         char file[1024];
2037
2038         if (strcmp(dump_postfix[0], type)) {
2039                 TBM_LOG_E("Not supported type:%s'", type);
2040                 return 0;
2041         }
2042
2043         if (!access(file, 0)) {
2044                 TBM_LOG_E("can't capture buffer, exist file %s", file);
2045                 return 0;
2046         }
2047
2048         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2049
2050         _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2051
2052         TBM_LOG_I("Capture %s \n", file);
2053
2054         return 1;
2055 }
2056 /*LCOV_EXCL_STOP*/