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