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