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