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