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