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