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