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