Package version up to 4.1.31
[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 #define TBM_SURFACE_MAGIC 0xBF021234
45
46 static tbm_bufmgr g_surface_bufmgr;
47 static pthread_mutex_t tbm_surface_lock = PTHREAD_MUTEX_INITIALIZER;
48 void _tbm_surface_mutex_unlock(void);
49
50 /* check condition */
51 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
52         if (!(cond)) {\
53                 TBM_ERR("'%s' failed.", #cond);\
54                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
55                 _tbm_surface_mutex_unlock();\
56                 return;\
57         } \
58 }
59
60 #define TBM_SURFACE_RETURN_ERR_IF_FAIL(cond, error_type) {\
61         if (!(cond)) {\
62                 TBM_ERR("'%s' failed.", #cond);\
63                 _tbm_set_last_result(error_type);\
64                 _tbm_surface_mutex_unlock();\
65                 return;\
66         } \
67 }
68
69 #define TBM_SURFACE_RETURN_SET_ERR_IF_FAIL(cond, error, error_type) {\
70         if (!(cond)) {\
71                 TBM_ERR("'%s' failed.", #cond);\
72                 error = error_type;\
73                 _tbm_set_last_result(error_type);\
74                 _tbm_surface_mutex_unlock();\
75                 return;\
76         } \
77 }
78
79 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
80         if (!(cond)) {\
81                 TBM_ERR("'%s' failed.", #cond);\
82                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
83                 _tbm_surface_mutex_unlock();\
84                 return val;\
85         } \
86 }
87
88
89 #define TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(cond, val, error_type) {\
90         if (!(cond)) {\
91                 TBM_ERR("'%s' failed.", #cond);\
92                 _tbm_set_last_result(error_type);\
93                 _tbm_surface_mutex_unlock();\
94                 return val;\
95         } \
96 }
97
98 #define TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(cond, val, error, error_type) {\
99         if (!(cond)) {\
100                 TBM_ERR("'%s' failed.", #cond);\
101                 if (error)\
102                         *error = error_type;\
103                 _tbm_set_last_result(error_type);\
104                 _tbm_surface_mutex_unlock();\
105                 return val;\
106         } \
107 }
108
109 #define TBM_SURFACE_RETURN_VAL_SET_ERR_NO_LOG_IF_FAIL(cond, val, error, error_type) {\
110         if (!(cond)) {\
111                 if (error)\
112                         *error = error_type;\
113                 _tbm_set_last_result(error_type);\
114                 _tbm_surface_mutex_unlock();\
115                 return val;\
116         } \
117 }
118
119 /* LCOV_EXCL_START */
120
121 static void
122 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
123 {
124         LIST_DEL(&debug_data->item_link);
125
126         if (debug_data->key) free(debug_data->key);
127         if (debug_data->value) free(debug_data->value);
128         free(debug_data);
129 }
130
131 char *
132 _tbm_surface_internal_format_to_str(tbm_format format)
133 {
134         switch (format) {
135         case TBM_FORMAT_C8:
136                 return "TBM_FORMAT_C8";
137         case TBM_FORMAT_RGB332:
138                 return "TBM_FORMAT_RGB332";
139         case TBM_FORMAT_BGR233:
140                 return "TBM_FORMAT_BGR233";
141         case TBM_FORMAT_XRGB4444:
142                 return "TBM_FORMAT_XRGB4444";
143         case TBM_FORMAT_XBGR4444:
144                 return "TBM_FORMAT_XBGR4444";
145         case TBM_FORMAT_RGBX4444:
146                 return "TBM_FORMAT_RGBX4444";
147         case TBM_FORMAT_BGRX4444:
148                 return "TBM_FORMAT_BGRX4444";
149         case TBM_FORMAT_ARGB4444:
150                 return "TBM_FORMAT_ARGB4444";
151         case TBM_FORMAT_ABGR4444:
152                 return "TBM_FORMAT_ABGR4444";
153         case TBM_FORMAT_RGBA4444:
154                 return "TBM_FORMAT_RGBA4444";
155         case TBM_FORMAT_BGRA4444:
156                 return "TBM_FORMAT_BGRA4444";
157         case TBM_FORMAT_XRGB1555:
158                 return "TBM_FORMAT_XRGB1555";
159         case TBM_FORMAT_XBGR1555:
160                 return "TBM_FORMAT_XBGR1555";
161         case TBM_FORMAT_RGBX5551:
162                 return "TBM_FORMAT_RGBX5551";
163         case TBM_FORMAT_BGRX5551:
164                 return "TBM_FORMAT_BGRX5551";
165         case TBM_FORMAT_ARGB1555:
166                 return "TBM_FORMAT_ARGB1555";
167         case TBM_FORMAT_ABGR1555:
168                 return "TBM_FORMAT_ABGR1555";
169         case TBM_FORMAT_RGBA5551:
170                 return "TBM_FORMAT_RGBA5551";
171         case TBM_FORMAT_BGRA5551:
172                 return "TBM_FORMAT_BGRA5551";
173         case TBM_FORMAT_RGB565:
174                 return "TBM_FORMAT_RGB565";
175         case TBM_FORMAT_BGR565:
176                 return "TBM_FORMAT_BGR565";
177         case TBM_FORMAT_RGB888:
178                 return "TBM_FORMAT_RGB888";
179         case TBM_FORMAT_BGR888:
180                 return "TBM_FORMAT_BGR888";
181         case TBM_FORMAT_XRGB8888:
182                 return "TBM_FORMAT_XRGB8888";
183         case TBM_FORMAT_XBGR8888:
184                 return "TBM_FORMAT_XBGR8888";
185         case TBM_FORMAT_RGBX8888:
186                 return "TBM_FORMAT_RGBX8888";
187         case TBM_FORMAT_BGRX8888:
188                 return "TBM_FORMAT_BGRX8888";
189         case TBM_FORMAT_ARGB8888:
190                 return "TBM_FORMAT_ARGB8888";
191         case TBM_FORMAT_ABGR8888:
192                 return "TBM_FORMAT_ABGR8888";
193         case TBM_FORMAT_RGBA8888:
194                 return "TBM_FORMAT_RGBA8888";
195         case TBM_FORMAT_BGRA8888:
196                 return "TBM_FORMAT_BGRA8888";
197         case TBM_FORMAT_XRGB2101010:
198                 return "TBM_FORMAT_XRGB2101010";
199         case TBM_FORMAT_XBGR2101010:
200                 return "TBM_FORMAT_XBGR2101010";
201         case TBM_FORMAT_RGBX1010102:
202                 return "TBM_FORMAT_RGBX1010102";
203         case TBM_FORMAT_BGRX1010102:
204                 return "TBM_FORMAT_BGRX1010102";
205         case TBM_FORMAT_ARGB2101010:
206                 return "TBM_FORMAT_ARGB2101010";
207         case TBM_FORMAT_ABGR2101010:
208                 return "TBM_FORMAT_ABGR2101010";
209         case TBM_FORMAT_RGBA1010102:
210                 return "TBM_FORMAT_RGBA1010102";
211         case TBM_FORMAT_BGRA1010102:
212                 return "TBM_FORMAT_BGRA1010102";
213         case TBM_FORMAT_YUYV:
214                 return "TBM_FORMAT_YUYV";
215         case TBM_FORMAT_YVYU:
216                 return "TBM_FORMAT_YVYU";
217         case TBM_FORMAT_UYVY:
218                 return "TBM_FORMAT_UYVY";
219         case TBM_FORMAT_VYUY:
220                 return "TBM_FORMAT_VYUY";
221         case TBM_FORMAT_AYUV:
222                 return "TBM_FORMAT_AYUV";
223         case TBM_FORMAT_NV12:
224                 return "TBM_FORMAT_NV12";
225         case TBM_FORMAT_NV21:
226                 return "TBM_FORMAT_NV21";
227         case TBM_FORMAT_NV16:
228                 return "TBM_FORMAT_NV16";
229         case TBM_FORMAT_NV61:
230                 return "TBM_FORMAT_NV61";
231         case TBM_FORMAT_YUV410:
232                 return "TBM_FORMAT_YUV410";
233         case TBM_FORMAT_YVU410:
234                 return "TBM_FORMAT_YVU410";
235         case TBM_FORMAT_YUV411:
236                 return "TBM_FORMAT_YUV411";
237         case TBM_FORMAT_YVU411:
238                 return "TBM_FORMAT_YVU411";
239         case TBM_FORMAT_YUV420:
240                 return "TBM_FORMAT_YUV420";
241         case TBM_FORMAT_YVU420:
242                 return "TBM_FORMAT_YVU420";
243         case TBM_FORMAT_YUV422:
244                 return "TBM_FORMAT_YUV422";
245         case TBM_FORMAT_YVU422:
246                 return "TBM_FORMAT_YVU422";
247         case TBM_FORMAT_YUV444:
248                 return "TBM_FORMAT_YUV444";
249         case TBM_FORMAT_YVU444:
250                 return "TBM_FORMAT_YVU444";
251         case TBM_FORMAT_NV12MT:
252                 return "TBM_FORMAT_NV12MT";
253         default:
254                 return "unknwon";
255         }
256 }
257
258 void
259 _tbm_surface_mutex_lock(void)
260 {
261         pthread_mutex_lock(&tbm_surface_lock);
262 }
263
264 void
265 _tbm_surface_mutex_unlock(void)
266 {
267         pthread_mutex_unlock(&tbm_surface_lock);
268 }
269
270 static void
271 _init_surface_bufmgr(void)
272 {
273         g_surface_bufmgr = tbm_bufmgr_init(-1);
274 }
275
276 static void
277 _deinit_surface_bufmgr(void)
278 {
279         if (!g_surface_bufmgr)
280                 return;
281
282         tbm_bufmgr_deinit(g_surface_bufmgr);
283         g_surface_bufmgr = NULL;
284 }
285 /* LCOV_EXCL_STOP */
286
287 static int
288 _tbm_surface_internal_magic_check(tbm_surface_h surface)
289 {
290         if (surface->magic != TBM_SURFACE_MAGIC)
291                 return 0;
292
293         return 1;
294 }
295
296 static int
297 _tbm_surface_internal_is_valid(tbm_surface_h surface)
298 {
299         if (!surface) {
300                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
301                 TBM_ERR("error: No valid tbm_surface is NULL");
302                 return 0;
303         }
304
305         if (!_tbm_surface_internal_magic_check(surface)) {
306                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
307                 TBM_ERR("error: No valid tbm_surface(%p)", surface);
308                 return 0;
309         }
310
311         return 1;
312 }
313
314 static int
315 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
316                                        int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
317 {
318         TBM_RETURN_VAL_IF_FAIL(surface, 0);
319         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
320
321         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
322         struct _tbm_bufmgr *bufmgr = surf->bufmgr;
323         tbm_error_e error;
324
325         TBM_RETURN_VAL_IF_FAIL(bufmgr != NULL, 0);
326         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
327         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
328         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
329
330         error = tbm_module_get_plane_data(bufmgr->module, surf->info.format, plane_idx, surf->info.width, surf->info.height, size, offset, pitch, bo_idx);
331         if (error != TBM_ERROR_NONE) {
332                 _tbm_set_last_result(error);
333                 return 0;
334         }
335
336         return 1;
337 }
338
339 static void
340 _tbm_surface_internal_destroy(tbm_surface_h surface)
341 {
342         int i;
343         tbm_bufmgr bufmgr = surface->bufmgr;
344         tbm_user_data *old_data = NULL, *tmp = NULL;
345         tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
346         tbm_surface_destroy_func_info *func_info = NULL, *func_next = NULL;
347
348         if (!LIST_IS_EMPTY(&surface->destroy_funcs)) {
349                 LIST_FOR_EACH_ENTRY_SAFE(func_info, func_next, &surface->destroy_funcs, item_link) {
350                         func_info->destroy_func(surface, func_info->user_data);
351                 }
352                 TBM_DBG("free destroy_funcs %p", surface);
353                 LIST_FOR_EACH_ENTRY_SAFE(func_info, func_next, &surface->destroy_funcs, item_link) {
354                         LIST_DEL(&func_info->item_link);
355                         free(func_info);
356                 }
357         }
358
359         /* destory the user_data_list */
360         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
361                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
362                         TBM_DBG("free user_data");
363                         user_data_delete(old_data);
364                 }
365         }
366
367         for (i = 0; i < surface->num_bos; i++) {
368                 surface->bos[i]->surface = NULL;
369
370                 tbm_bo_unref(surface->bos[i]);
371                 surface->bos[i] = NULL;
372         }
373
374         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
375                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
376                         _tbm_surface_internal_debug_data_delete(debug_old_data);
377         }
378
379         LIST_DEL(&surface->item_link);
380         surface->magic = 0;
381
382         if (surface->surface_data) {
383                 tbm_surface_data_free(surface->surface_data);
384                 surface->surface_data = NULL;
385         }
386
387         free(surface);
388         surface = NULL;
389
390         if (bufmgr && LIST_IS_EMPTY(&bufmgr->surf_list)) {
391                 LIST_DELINIT(&bufmgr->surf_list);
392
393                 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
394                         LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
395                                 _tbm_surface_internal_debug_data_delete(debug_old_data);
396                         }
397                 }
398
399                 _deinit_surface_bufmgr();
400         }
401 }
402
403 /* LCOV_EXCL_START */
404 static int
405 _tbm_surface_check_file_is_symbolic_link(const char* path)
406 {
407         struct stat sb;
408
409         if (!path)
410                 return 0;
411
412         if (stat(path, &sb) != 0)
413                 return 0;
414
415         if (S_ISLNK(sb.st_mode))
416                 return 1;
417
418         return 0;
419 }
420 /* LCOV_EXCL_STOP */
421
422 static int
423 _tbm_surface_internal_get_num_planes(tbm_format format)
424 {
425         int num_planes = 0;
426
427         switch (format) {
428         case TBM_FORMAT_C8:
429         case TBM_FORMAT_RGB332:
430         case TBM_FORMAT_BGR233:
431         case TBM_FORMAT_XRGB4444:
432         case TBM_FORMAT_XBGR4444:
433         case TBM_FORMAT_RGBX4444:
434         case TBM_FORMAT_BGRX4444:
435         case TBM_FORMAT_ARGB4444:
436         case TBM_FORMAT_ABGR4444:
437         case TBM_FORMAT_RGBA4444:
438         case TBM_FORMAT_BGRA4444:
439         case TBM_FORMAT_XRGB1555:
440         case TBM_FORMAT_XBGR1555:
441         case TBM_FORMAT_RGBX5551:
442         case TBM_FORMAT_BGRX5551:
443         case TBM_FORMAT_ARGB1555:
444         case TBM_FORMAT_ABGR1555:
445         case TBM_FORMAT_RGBA5551:
446         case TBM_FORMAT_BGRA5551:
447         case TBM_FORMAT_RGB565:
448         case TBM_FORMAT_BGR565:
449         case TBM_FORMAT_RGB888:
450         case TBM_FORMAT_BGR888:
451         case TBM_FORMAT_XRGB8888:
452         case TBM_FORMAT_XBGR8888:
453         case TBM_FORMAT_RGBX8888:
454         case TBM_FORMAT_BGRX8888:
455         case TBM_FORMAT_ARGB8888:
456         case TBM_FORMAT_ABGR8888:
457         case TBM_FORMAT_RGBA8888:
458         case TBM_FORMAT_BGRA8888:
459         case TBM_FORMAT_XRGB2101010:
460         case TBM_FORMAT_XBGR2101010:
461         case TBM_FORMAT_RGBX1010102:
462         case TBM_FORMAT_BGRX1010102:
463         case TBM_FORMAT_ARGB2101010:
464         case TBM_FORMAT_ABGR2101010:
465         case TBM_FORMAT_RGBA1010102:
466         case TBM_FORMAT_BGRA1010102:
467         case TBM_FORMAT_YUYV:
468         case TBM_FORMAT_YVYU:
469         case TBM_FORMAT_UYVY:
470         case TBM_FORMAT_VYUY:
471         case TBM_FORMAT_AYUV:
472                 num_planes = 1;
473                 break;
474         case TBM_FORMAT_NV12:
475         case TBM_FORMAT_NV12MT:
476         case TBM_FORMAT_NV21:
477         case TBM_FORMAT_NV16:
478         case TBM_FORMAT_NV61:
479                 num_planes = 2;
480                 break;
481         case TBM_FORMAT_YUV410:
482         case TBM_FORMAT_YVU410:
483         case TBM_FORMAT_YUV411:
484         case TBM_FORMAT_YVU411:
485         case TBM_FORMAT_YUV420:
486         case TBM_FORMAT_YVU420:
487         case TBM_FORMAT_YUV422:
488         case TBM_FORMAT_YVU422:
489         case TBM_FORMAT_YUV444:
490         case TBM_FORMAT_YVU444:
491                 num_planes = 3;
492                 break;
493
494         default:
495                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
496                 break;
497         }
498
499         return num_planes;
500 }
501
502 static int
503 _tbm_surface_internal_get_bpp(tbm_format format)
504 {
505
506         int bpp = 0;
507
508         switch (format) {
509         case TBM_FORMAT_C8:
510         case TBM_FORMAT_RGB332:
511         case TBM_FORMAT_BGR233:
512                 bpp = 8;
513                 break;
514         case TBM_FORMAT_XRGB4444:
515         case TBM_FORMAT_XBGR4444:
516         case TBM_FORMAT_RGBX4444:
517         case TBM_FORMAT_BGRX4444:
518         case TBM_FORMAT_ARGB4444:
519         case TBM_FORMAT_ABGR4444:
520         case TBM_FORMAT_RGBA4444:
521         case TBM_FORMAT_BGRA4444:
522         case TBM_FORMAT_XRGB1555:
523         case TBM_FORMAT_XBGR1555:
524         case TBM_FORMAT_RGBX5551:
525         case TBM_FORMAT_BGRX5551:
526         case TBM_FORMAT_ARGB1555:
527         case TBM_FORMAT_ABGR1555:
528         case TBM_FORMAT_RGBA5551:
529         case TBM_FORMAT_BGRA5551:
530         case TBM_FORMAT_RGB565:
531         case TBM_FORMAT_BGR565:
532                 bpp = 16;
533                 break;
534         case TBM_FORMAT_RGB888:
535         case TBM_FORMAT_BGR888:
536                 bpp = 24;
537                 break;
538         case TBM_FORMAT_XRGB8888:
539         case TBM_FORMAT_XBGR8888:
540         case TBM_FORMAT_RGBX8888:
541         case TBM_FORMAT_BGRX8888:
542         case TBM_FORMAT_ARGB8888:
543         case TBM_FORMAT_ABGR8888:
544         case TBM_FORMAT_RGBA8888:
545         case TBM_FORMAT_BGRA8888:
546         case TBM_FORMAT_XRGB2101010:
547         case TBM_FORMAT_XBGR2101010:
548         case TBM_FORMAT_RGBX1010102:
549         case TBM_FORMAT_BGRX1010102:
550         case TBM_FORMAT_ARGB2101010:
551         case TBM_FORMAT_ABGR2101010:
552         case TBM_FORMAT_RGBA1010102:
553         case TBM_FORMAT_BGRA1010102:
554                 bpp = 32;
555                 break;
556         case TBM_FORMAT_YUYV:
557         case TBM_FORMAT_YVYU:
558         case TBM_FORMAT_UYVY:
559         case TBM_FORMAT_VYUY:
560                 bpp = 16;
561                 break;
562         case TBM_FORMAT_AYUV:
563                 bpp = 32;
564                 break;
565         case TBM_FORMAT_NV12:
566         case TBM_FORMAT_NV12MT:
567         case TBM_FORMAT_NV21:
568                 bpp = 12;
569                 break;
570         case TBM_FORMAT_NV16:
571         case TBM_FORMAT_NV61:
572                 bpp = 16;
573                 break;
574         case TBM_FORMAT_YUV410:
575         case TBM_FORMAT_YVU410:
576                 bpp = 9;
577                 break;
578         case TBM_FORMAT_YUV411:
579         case TBM_FORMAT_YVU411:
580         case TBM_FORMAT_YUV420:
581         case TBM_FORMAT_YVU420:
582                 bpp = 12;
583                 break;
584         case TBM_FORMAT_YUV422:
585         case TBM_FORMAT_YVU422:
586                 bpp = 16;
587                 break;
588         case TBM_FORMAT_YUV444:
589         case TBM_FORMAT_YVU444:
590                 bpp = 24;
591                 break;
592         default:
593                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
594                 break;
595         }
596
597         return bpp;
598 }
599
600 static void
601 _tbm_surface_internal_free(struct _tbm_surface *surf)
602 {
603         if (!surf)
604                 return;
605
606         free(surf);
607 }
608
609 static struct _tbm_surface *
610 _tbm_surface_internal_alloc(tbm_bufmgr bufmgr, int width, int height, int format, tbm_error_e *error)
611 {
612         struct _tbm_surface *surf = NULL;
613
614         surf = calloc(1, sizeof(struct _tbm_surface));
615         if (!surf) {
616                 /* LCOV_EXCL_START */
617                 TBM_ERR("memory allocation failed.");
618                 *error = TBM_ERROR_OUT_OF_MEMORY;
619                 return NULL;
620                 /* LCOV_EXCL_STOP */
621         }
622         surf->refcnt = 1;
623
624         surf->magic = TBM_SURFACE_MAGIC;
625         surf->bufmgr = bufmgr;
626         surf->info.width = width;
627         surf->info.height = height;
628         surf->info.format = format;
629         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
630         if (!surf->info.bpp) {
631                 /* LCOV_EXCL_START */
632                 TBM_ERR("_tbm_surface_internal_get_bpp failed. format:%d error:%s", format, tbm_error_str(*error));
633                 *error = tbm_get_last_error();
634                 free(surf);
635                 return NULL;
636                 /* LCOV_EXCL_STOP */
637         }
638
639         // get number of planes
640         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
641         if (!surf->info.num_planes) {
642                 /* LCOV_EXCL_START */
643                 TBM_ERR("_tbm_surface_internal_get_num_planes failed. format:%d error:%s", format, tbm_error_str(*error));
644                 *error = tbm_get_last_error();
645                 free(surf);
646                 return NULL;
647                 /* LCOV_EXCL_STOP */
648         }
649
650         return surf;
651 }
652
653 static tbm_error_e
654 _tbm_surface_internal_set_data(struct _tbm_surface *surf, int flags, int can_share_surface)
655 {
656         tbm_error_e error;
657         uint32_t size = 0, offset = 0, stride = 0, bo_size = 0;;
658         int i, j, bo_idx;
659         tbm_bo_data **bo_data_array = NULL;
660         int num_bos = 0;
661         int memory_types;
662
663          // set data with surface
664         if (can_share_surface) {
665                 // set infomation of planes
666                 for (i = 0; i < surf->info.num_planes; i++) {
667                         error = tbm_surface_data_get_plane_data(surf->surface_data, i, &size, &offset, &stride, &bo_idx);
668                         if (error != TBM_ERROR_NONE) {
669                                 TBM_ERR("tbm_surface_data_get_plane_data failed. error:%s", tbm_error_str(error));
670                                 return error;
671                         }
672
673                         surf->info.planes[i].size = size;
674                         surf->info.planes[i].offset = offset;
675                         surf->info.planes[i].stride = stride;
676                         surf->planes_bo_idx[i] = bo_idx;
677                 }
678
679                 // calculate the size of a surface
680                 for (i = 0; i < surf->info.num_planes; i++)
681                         surf->info.size += surf->info.planes[i].size;
682
683                 // get the bo_data_array
684                 bo_data_array = tbm_surface_data_get_bo_data_array(surf->surface_data, &num_bos, &memory_types, &error);
685                 if (!bo_data_array) {
686                         TBM_ERR("tbm_surface_data_get_bo_data_array failed. error:%s", tbm_error_str(error));
687                         return error;
688                 }
689
690                 // set num_bos
691                 surf->num_bos = num_bos;
692
693                 // set flags
694                 surf->flags = memory_types;
695
696                 // allocate the array of tbm_bos
697                 for (i = 0; i < num_bos; i++) {
698                         surf->bos[i] = tbm_bufmgr_internal_alloc_bo_with_bo_data(surf->bufmgr, bo_data_array[i], memory_types, &error);
699                         if (!surf->bos[i]) {
700                                 TBM_ERR("tbm_bufmgr_internal_alloc_bo_with_bo_data failed. error:%s idx:%d", tbm_error_str(error), i);
701                                 goto failed;
702                         }
703
704                         _tbm_bo_set_surface(surf->bos[i], surf);
705                 }
706
707                 // only free the pointers of the arrary, not the item(tbm_bo_data).
708                 // the item(tbm_bo_data) is set to the tbm_bo. tbm_bo handles the life cycle of the tbm_bo_data.
709                 free(bo_data_array);
710         } else {
711                 // set infomation of planes
712                 for (i = 0; i < surf->info.num_planes; i++) {
713                         if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
714                                 TBM_ERR("_tbm_surface_internal_query_plane_data failed.");
715                                 error = tbm_get_last_error();
716                                 return error;
717                         }
718
719                         surf->info.planes[i].size = size;
720                         surf->info.planes[i].offset = offset;
721                         surf->info.planes[i].stride = stride;
722                         surf->planes_bo_idx[i] = bo_idx;
723                 }
724
725                 // calculate the number of bos
726                 surf->num_bos = 1;
727                 for (i = 0; i < surf->info.num_planes; i++) {
728                         surf->info.size += surf->info.planes[i].size;
729
730                         if (surf->num_bos < surf->planes_bo_idx[i] + 1)
731                                 surf->num_bos = surf->planes_bo_idx[i] + 1;
732                 }
733
734                 // set flags
735                 surf->flags = flags;
736
737                 // allocate the array of tbm_bos
738                 for (i = 0; i < surf->num_bos; i++) {
739                         bo_size = 0;
740                         for (j = 0; j < surf->info.num_planes; j++) {
741                                 if (surf->planes_bo_idx[j] == i)
742                                         bo_size += surf->info.planes[j].size;
743                         }
744
745                         surf->bos[i] = tbm_bufmgr_internal_alloc_bo_with_format(surf->bufmgr,
746                                                                                 surf->info.format, i, surf->info.width, surf->info.height,
747                                                                                 surf->info.bpp/8, flags, &error);
748                         if (!surf->bos[i]) {
749                                 surf->bos[i] = tbm_bo_alloc(surf->bufmgr, bo_size, flags);
750                                 if (!surf->bos[i]) {
751                                         TBM_ERR("tbm_bo_alloc failed. idx:%d", i);
752                                         error = tbm_get_last_error();
753                                         goto failed;
754                                 }
755                         }
756
757                         _tbm_bo_set_surface(surf->bos[i], surf);
758                 }
759         }
760
761         return TBM_ERROR_NONE;
762
763 failed:
764         if (can_share_surface) {
765                 for (j = 0; j < num_bos; j++) {
766                         if (bo_data_array[j]) {
767                                 free(bo_data_array[j]);
768                                 surf->bos[j] = NULL;
769                         }
770                 }
771                 free(bo_data_array);
772         }
773
774         for (j = 0; j < i; j++) {
775                 if (surf->bos[j])
776                         tbm_bo_unref(surf->bos[j]);
777         }
778
779         return error;
780 }
781
782 static struct _tbm_surface *
783 _tbm_surface_internal_create_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, tbm_error_e *error)
784 {
785         struct _tbm_surface *surf;
786         int can_share_surface = 0;
787
788         surf = _tbm_surface_internal_alloc(bufmgr, width, height, format, error);
789         if (!surf) {
790                 /* LCOV_EXCL_START */
791                 TBM_ERR("_tbm_surface_internal_alloc failed.");
792                 return NULL;
793                 /* LCOV_EXCL_STOP */
794         }
795
796         can_share_surface = tbm_bufmgr_internal_support_capabilites(bufmgr, TBM_BUFMGR_CAPABILITY_SHARE_SURFACE);
797         if (can_share_surface) {
798                 // alloc surface_data
799                 surf->surface_data = tbm_module_alloc_surface_data(bufmgr->module, width, height, format, flags, error);
800                 if (!surf->surface_data) {
801                         TBM_ERR("tbm_module_alloc_surface_data failed. width:%d height:%d format:%d error:%s",
802                                         width, height, format, tbm_error_str(*error));
803                         _tbm_surface_internal_free(surf);
804                         return NULL;
805                 }
806         }
807
808         // set the surface data
809         *error =  _tbm_surface_internal_set_data(surf, flags, can_share_surface);
810         if (*error != TBM_ERROR_NONE) {
811                 tbm_surface_data_free(surf->surface_data);
812                 surf->surface_data = NULL;
813                 _tbm_surface_internal_free(surf);
814                 return NULL;
815         }
816
817         return surf;
818 }
819
820 static struct _tbm_surface *
821 _tbm_surface_internal_import_surface(tbm_bufmgr bufmgr, int width, int height, int format, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)
822 {
823         struct _tbm_surface *surf = NULL;
824
825         surf = _tbm_surface_internal_alloc(bufmgr, width, height, format, error);
826         if (!surf) {
827                 /* LCOV_EXCL_START */
828                 TBM_ERR("_tbm_surface_internal_alloc failed.");
829                 return NULL;
830                 /* LCOV_EXCL_STOP */
831         }
832
833         // import surface_data
834         surf->surface_data = tbm_module_import_surface_data(bufmgr->module, width, height, format, buffer_data, error);
835         if (!surf->surface_data) {
836                 /* LCOV_EXCL_START */
837                 TBM_ERR("tbm_module_import_surface_data failed. width:%d height:%d format:%d error:%s",
838                                 width, height, format, tbm_error_str(*error));
839                 _tbm_surface_internal_free(surf);
840                 return NULL;
841                 /* LCOV_EXCL_STOP */
842         }
843
844         // set the surface data
845         *error =  _tbm_surface_internal_set_data(surf, TBM_BO_DEFAULT, 1);
846         if (*error != TBM_ERROR_NONE) {
847                 /* LCOV_EXCL_START */
848                 tbm_surface_data_free(surf->surface_data);
849                 surf->surface_data = NULL;
850                 _tbm_surface_internal_free(surf);
851                 return NULL;
852                 /* LCOV_EXCL_STOP */
853         }
854
855         return surf;
856 }
857
858 int
859 tbm_surface_internal_is_valid(tbm_surface_h surface)
860 {
861         int ret = 0;
862
863         _tbm_surface_mutex_lock();
864         _tbm_set_last_result(TBM_ERROR_NONE);
865
866         /* Return silently if surface is null. */
867         if (!surface) {
868                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
869                 _tbm_surface_mutex_unlock();
870                 return 0;
871         }
872
873         ret = _tbm_surface_internal_is_valid(surface);
874
875         _tbm_surface_mutex_unlock();
876
877         return ret;
878 }
879
880 int
881 tbm_surface_internal_query_supported_formats(uint32_t **formats,
882                 uint32_t *num)
883 {
884         struct _tbm_bufmgr *bufmgr;
885         bool bufmgr_initialized = false;
886         tbm_error_e error;
887
888         _tbm_surface_mutex_lock();
889         _tbm_set_last_result(TBM_ERROR_NONE);
890
891         TBM_SURFACE_RETURN_VAL_IF_FAIL(formats, 0);
892         TBM_SURFACE_RETURN_VAL_IF_FAIL(num, 0);
893
894         if (!g_surface_bufmgr) {
895                 _init_surface_bufmgr();
896                 if (!g_surface_bufmgr) {
897                         TBM_ERR("fail bufmgr initialization");
898                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
899                         goto fail;
900                 }
901                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
902                 bufmgr_initialized = true;
903         }
904
905         bufmgr = g_surface_bufmgr;
906
907         error = tbm_module_get_supported_formats(bufmgr->module, formats, num);
908         if (error != TBM_ERROR_NONE) {
909                 _tbm_set_last_result(error);
910                 goto fail;
911         }
912
913         TBM_TRACE_SURFACE_INTERNAL("tbm_bufmgr(%p) format num(%u)", g_surface_bufmgr, *num);
914
915         if (bufmgr_initialized) {
916                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
917                 _deinit_surface_bufmgr();
918         }
919
920         _tbm_surface_mutex_unlock();
921
922         return 1;
923
924 /* LCOV_EXCL_START */
925 fail:
926         if (bufmgr_initialized) {
927                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
928                 _deinit_surface_bufmgr();
929         }
930         _tbm_surface_mutex_unlock();
931
932         TBM_ERR("error: tbm_bufmgr(%p)", g_surface_bufmgr);
933
934         return 0;
935 /* LCOV_EXCL_STOP */
936 }
937
938 int
939 tbm_surface_internal_get_num_planes(tbm_format format)
940 {
941         int num_planes = 0;
942
943         _tbm_surface_mutex_lock();
944         _tbm_set_last_result(TBM_ERROR_NONE);
945
946         num_planes = _tbm_surface_internal_get_num_planes(format);
947         if (!num_planes) {
948                 TBM_ERR("error: tbm_error(%s)", tbm_error_str(tbm_get_last_error()));
949                 _tbm_surface_mutex_unlock();
950                 return 0;
951         }
952
953         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) num_planes(%d)", _tbm_surface_internal_format_to_str(format), num_planes);
954
955         _tbm_surface_mutex_unlock();
956
957         return num_planes;
958 }
959
960 int
961 tbm_surface_internal_get_bpp(tbm_format format)
962 {
963         int bpp = 0;
964
965         _tbm_surface_mutex_lock();
966         _tbm_set_last_result(TBM_ERROR_NONE);
967
968         bpp = _tbm_surface_internal_get_bpp(format);
969         if (!bpp) {
970                 TBM_ERR("error: tbm_error(%s)", tbm_error_str(tbm_get_last_error()));
971                 _tbm_surface_mutex_unlock();
972                 return 0;
973         }
974
975         _tbm_surface_mutex_unlock();
976
977         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) bpp(%d)", _tbm_surface_internal_format_to_str(format), bpp);
978
979         return bpp;
980 }
981
982 tbm_surface_h
983 tbm_surface_internal_create_with_flags(int width, int height,
984                                        int format, int flags)
985 {
986         struct _tbm_bufmgr *bufmgr;
987         struct _tbm_surface *surf = NULL;
988         tbm_error_e error = TBM_ERROR_INVALID_OPERATION;
989         bool bufmgr_initialized = false;
990
991         _tbm_surface_mutex_lock();
992         _tbm_set_last_result(TBM_ERROR_NONE);
993
994         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, NULL);
995         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, NULL);
996
997         if (!g_surface_bufmgr) {
998                 _init_surface_bufmgr();
999                 if (!g_surface_bufmgr) {
1000                         TBM_ERR("fail bufmgr initialization");
1001                         error = TBM_ERROR_INVALID_OPERATION;
1002                         goto check_valid_fail;
1003                 }
1004                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1005                 bufmgr_initialized = true;
1006         }
1007
1008         bufmgr = g_surface_bufmgr;
1009         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
1010                 TBM_ERR("The bufmgr is invalid");
1011                 error = TBM_ERROR_INVALID_PARAMETER;
1012                 goto check_valid_fail;
1013         }
1014
1015         surf = _tbm_surface_internal_create_surface(bufmgr, width, height, format, flags, &error);
1016         if (!surf) {
1017                 TBM_ERR("_tbm_surface_internal_create_surface failed.");
1018                 goto surface_alloc_fail;
1019         }
1020
1021         TBM_TRACE_SURFACE_INTERNAL("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)",
1022                         width, height, _tbm_surface_internal_format_to_str(format), flags, surf);
1023
1024         LIST_INITHEAD(&surf->user_data_list);
1025         LIST_INITHEAD(&surf->debug_data_list);
1026         LIST_INITHEAD(&surf->destroy_funcs);
1027
1028         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1029
1030         _tbm_set_last_result(error);
1031         _tbm_surface_mutex_unlock();
1032
1033         return surf;
1034
1035 /* LCOV_EXCL_START */
1036
1037 surface_alloc_fail:
1038 check_valid_fail:
1039         if (bufmgr_initialized && bufmgr) {
1040                 LIST_DELINIT(&bufmgr->surf_list);
1041                 _deinit_surface_bufmgr();
1042         }
1043
1044         TBM_ERR("error: width(%d) height(%d) format(%s) flags(%d)",
1045                 width, height, _tbm_surface_internal_format_to_str(format), flags);
1046
1047         _tbm_set_last_result(error);
1048         _tbm_surface_mutex_unlock();
1049
1050 /* LCOV_EXCL_STOP */
1051
1052         return NULL;
1053 }
1054
1055 tbm_surface_h
1056 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
1057                                      tbm_bo *bos, int num)
1058 {
1059         struct _tbm_bufmgr *bufmgr;
1060         struct _tbm_surface *surf = NULL;
1061         int i;
1062         bool bufmgr_initialized = false;
1063
1064         _tbm_surface_mutex_lock();
1065         _tbm_set_last_result(TBM_ERROR_NONE);
1066
1067         TBM_SURFACE_RETURN_VAL_IF_FAIL(bos, NULL);
1068         TBM_SURFACE_RETURN_VAL_IF_FAIL(info, NULL);
1069         TBM_SURFACE_RETURN_VAL_IF_FAIL(info->num_planes > 0, NULL);
1070         TBM_SURFACE_RETURN_VAL_IF_FAIL(num > 0, NULL);
1071         TBM_SURFACE_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
1072
1073         if (!g_surface_bufmgr) {
1074                 _init_surface_bufmgr();
1075                 if (!g_surface_bufmgr) {
1076                         TBM_ERR("fail bufmgr initialization");
1077                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1078                         goto check_valid_fail;
1079                 }
1080                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1081                 bufmgr_initialized = true;
1082         }
1083
1084         bufmgr = g_surface_bufmgr;
1085         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
1086                 TBM_ERR("fail to validate the Bufmgr.");
1087                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1088                 goto check_valid_fail;
1089         }
1090
1091         surf = calloc(1, sizeof(struct _tbm_surface));
1092         if (!surf) {
1093                 /* LCOV_EXCL_START */
1094                 TBM_ERR("fail to allocate struct _tbm_surface.");
1095                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1096                 goto alloc_surf_fail;
1097                 /* LCOV_EXCL_STOP */
1098         }
1099
1100         surf->magic = TBM_SURFACE_MAGIC;
1101         surf->bufmgr = bufmgr;
1102         surf->info.width = info->width;
1103         surf->info.height = info->height;
1104         surf->info.format = info->format;
1105         if (info->bpp > 0)
1106                 surf->info.bpp = info->bpp;
1107         else {
1108                 surf->info.bpp = _tbm_surface_internal_get_bpp(info->format);
1109                 if (!surf->info.bpp) {
1110                         TBM_ERR("fail to get bpp. error(%s)", tbm_error_str(tbm_get_last_error()));
1111                         goto bpp_fail;
1112                 }
1113         }
1114         surf->info.num_planes = info->num_planes;
1115         surf->refcnt = 1;
1116
1117         /* get size, stride and offset */
1118         for (i = 0; i < info->num_planes; i++) {
1119                 surf->info.planes[i].offset = info->planes[i].offset;
1120                 surf->info.planes[i].stride = info->planes[i].stride;
1121
1122                 if (info->planes[i].size > 0)
1123                         surf->info.planes[i].size = info->planes[i].size;
1124                 else {
1125                         uint32_t size = 0, offset = 0, stride = 0;
1126                         int32_t bo_idx = 0;
1127
1128                         if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
1129                                 TBM_ERR("fail to get plane_data. error(%s)", tbm_error_str(tbm_get_last_error()));
1130                                 goto plane_data_fail;
1131                         }
1132                         surf->info.planes[i].size = size;
1133                 }
1134
1135                 if (num == 1)
1136                         surf->planes_bo_idx[i] = 0;
1137                 else
1138                         surf->planes_bo_idx[i] = i;
1139         }
1140
1141         if (info->size > 0) {
1142                 surf->info.size = info->size;
1143         } else {
1144                 surf->info.size = 0;
1145                 for (i = 0; i < info->num_planes; i++)
1146                         surf->info.size += surf->info.planes[i].size;
1147         }
1148
1149         surf->flags = TBM_BO_DEFAULT;
1150
1151         /* create only one bo */
1152         surf->num_bos = num;
1153         for (i = 0; i < num; i++) {
1154                 if (bos[i] == NULL) {
1155                         TBM_ERR("bos[%d] is null.", i);
1156                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1157                         goto check_bo_fail;
1158                 }
1159
1160                 surf->bos[i] = tbm_bo_ref(bos[i]);
1161                 _tbm_bo_set_surface(bos[i], surf);
1162         }
1163
1164         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)", surf,
1165                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
1166
1167         LIST_INITHEAD(&surf->user_data_list);
1168         LIST_INITHEAD(&surf->debug_data_list);
1169         LIST_INITHEAD(&surf->destroy_funcs);
1170
1171         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1172
1173         _tbm_surface_mutex_unlock();
1174
1175         return surf;
1176
1177 /* LCOV_EXCL_START */
1178 check_bo_fail:
1179 plane_data_fail:
1180 bpp_fail:
1181         for (i = 0; i < num; i++) {
1182                 if (surf->bos[i])
1183                         tbm_bo_unref(surf->bos[i]);
1184         }
1185         free(surf);
1186 alloc_surf_fail:
1187 check_valid_fail:
1188         if (bufmgr_initialized && bufmgr) {
1189                 LIST_DELINIT(&bufmgr->surf_list);
1190                 _deinit_surface_bufmgr();
1191         }
1192         _tbm_surface_mutex_unlock();
1193
1194         TBM_ERR("error: width(%u) height(%u) format(%s) bo_num(%d)",
1195                         info->width, info->height,
1196                         _tbm_surface_internal_format_to_str(info->format), num);
1197 /* LCOV_EXCL_STOP */
1198
1199         return NULL;
1200 }
1201
1202 void
1203 tbm_surface_internal_destroy(tbm_surface_h surface)
1204 {
1205         _tbm_surface_mutex_lock();
1206         _tbm_set_last_result(TBM_ERROR_NONE);
1207
1208         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1209
1210         surface->refcnt--;
1211
1212         if (surface->refcnt > 0) {
1213                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)", surface->refcnt, surface);
1214                 _tbm_surface_mutex_unlock();
1215                 return;
1216         }
1217
1218         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)", surface, surface->refcnt);
1219
1220         if (surface->refcnt == 0)
1221                 _tbm_surface_internal_destroy(surface);
1222         else // if (surface->refcnt < 0)
1223                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1224
1225         _tbm_surface_mutex_unlock();
1226 }
1227
1228 void
1229 tbm_surface_internal_ref(tbm_surface_h surface)
1230 {
1231         _tbm_surface_mutex_lock();
1232         _tbm_set_last_result(TBM_ERROR_NONE);
1233
1234         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1235
1236         surface->refcnt++;
1237
1238         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)", surface, surface->refcnt);
1239
1240         _tbm_surface_mutex_unlock();
1241 }
1242
1243 void
1244 tbm_surface_internal_unref(tbm_surface_h surface)
1245 {
1246         _tbm_surface_mutex_lock();
1247         _tbm_set_last_result(TBM_ERROR_NONE);
1248
1249         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1250
1251         surface->refcnt--;
1252
1253         if (surface->refcnt > 0) {
1254                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)", surface->refcnt, surface);
1255                 _tbm_surface_mutex_unlock();
1256                 return;
1257         }
1258
1259         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)", surface, surface->refcnt);
1260
1261         if (surface->refcnt == 0)
1262                 _tbm_surface_internal_destroy(surface);
1263
1264         _tbm_surface_mutex_unlock();
1265 }
1266
1267 int
1268 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1269 {
1270         struct _tbm_surface *surf;
1271         int num;
1272
1273         _tbm_surface_mutex_lock();
1274         _tbm_set_last_result(TBM_ERROR_NONE);
1275
1276         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1277
1278         surf = (struct _tbm_surface *)surface;
1279         num = surf->num_bos;
1280
1281         if (!num)
1282                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1283
1284         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)", surface, num);
1285
1286         _tbm_surface_mutex_unlock();
1287
1288         return num;
1289 }
1290
1291 tbm_bo
1292 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1293 {
1294         struct _tbm_surface *surf;
1295         tbm_bo bo;
1296
1297         _tbm_surface_mutex_lock();
1298         _tbm_set_last_result(TBM_ERROR_NONE);
1299
1300         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1301         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1302
1303         surf = (struct _tbm_surface *)surface;
1304         bo = surf->bos[bo_idx];
1305
1306         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)", surface, bo_idx, bo);
1307
1308         _tbm_surface_mutex_unlock();
1309
1310         return bo;
1311 }
1312
1313 unsigned int
1314 tbm_surface_internal_get_size(tbm_surface_h surface)
1315 {
1316         struct _tbm_surface *surf;
1317         unsigned int size;
1318
1319         _tbm_surface_mutex_lock();
1320         _tbm_set_last_result(TBM_ERROR_NONE);
1321
1322         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1323
1324         surf = (struct _tbm_surface *)surface;
1325         size = surf->info.size;
1326
1327         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)", surface, size);
1328
1329         _tbm_surface_mutex_unlock();
1330
1331         return size;
1332 }
1333
1334 int
1335 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1336                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1337 {
1338         struct _tbm_surface *surf;
1339
1340         _tbm_surface_mutex_lock();
1341         _tbm_set_last_result(TBM_ERROR_NONE);
1342
1343         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1344         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1345
1346         surf = (struct _tbm_surface *)surface;
1347
1348         if (plane_idx >= surf->info.num_planes) {
1349                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)", surface, plane_idx);
1350                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1351                 _tbm_surface_mutex_unlock();
1352                 return 0;
1353         }
1354
1355         if (size)
1356                 *size = surf->info.planes[plane_idx].size;
1357
1358         if (offset)
1359                 *offset = surf->info.planes[plane_idx].offset;
1360
1361         if (pitch)
1362                 *pitch = surf->info.planes[plane_idx].stride;
1363
1364         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)", surface, plane_idx,
1365                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1366                                 surf->info.planes[plane_idx].stride);
1367
1368         _tbm_surface_mutex_unlock();
1369
1370         return 1;
1371 }
1372
1373 int
1374 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1375                               tbm_surface_info_s *info, int map)
1376 {
1377         struct _tbm_surface *surf;
1378         tbm_bo_handle bo_handles[4];
1379         int num_bos = 0;
1380         tbm_bo bos[4];
1381         int planes_bo_idx[TBM_SURF_PLANE_MAX];
1382         int i, j;
1383         tbm_error_e error;
1384
1385         _tbm_surface_mutex_lock();
1386         _tbm_set_last_result(TBM_ERROR_NONE);
1387
1388         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1389
1390         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1391
1392         surf = (struct _tbm_surface *)surface;
1393
1394         memset(info, 0x00, sizeof(tbm_surface_info_s));
1395         info->width = surf->info.width;
1396         info->height = surf->info.height;
1397         info->format = surf->info.format;
1398         info->bpp = surf->info.bpp;
1399         info->size = surf->info.size;
1400         info->num_planes = surf->info.num_planes;
1401
1402         for (i = 0; i < surf->info.num_planes; i++) {
1403                 info->planes[i].size = surf->info.planes[i].size;
1404                 info->planes[i].offset = surf->info.planes[i].offset;
1405                 info->planes[i].stride = surf->info.planes[i].stride;
1406                 planes_bo_idx[i] = surf->planes_bo_idx[i];
1407         }
1408
1409         for (i = 0; i < surf->num_bos; i++)
1410                 bos[i] = surf->bos[i];
1411
1412         num_bos = surf->num_bos;
1413
1414         if (map == 1) {
1415                 _tbm_surface_mutex_unlock();
1416                 for (i = 0; i < num_bos; i++) {
1417                         bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1418                         if (bo_handles[i].ptr == NULL) {
1419                                 error = tbm_get_last_error();
1420                                 for (j = 0; j < i; j++)
1421                                         tbm_bo_unmap(bos[j]);
1422
1423                                 _tbm_set_last_result(error);
1424                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)", surface, opt, map);
1425                                 return 0;
1426                         }
1427                 }
1428                 _tbm_surface_mutex_lock();
1429         } else {
1430                 for (i = 0; i < num_bos; i++) {
1431                         bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1432                         if (bo_handles[i].ptr == NULL) {
1433                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)", surface, opt, map);
1434                                 _tbm_surface_mutex_unlock();
1435                                 return 0;
1436                         }
1437                 }
1438         }
1439
1440         for (i = 0; i < info->num_planes; i++) {
1441                 if (bo_handles[planes_bo_idx[i]].ptr)
1442                         info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1443         }
1444
1445         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)", surface, opt, map);
1446
1447         _tbm_surface_mutex_unlock();
1448
1449         return 1;
1450 }
1451
1452 void
1453 tbm_surface_internal_unmap(tbm_surface_h surface)
1454 {
1455         struct _tbm_surface *surf;
1456         int i;
1457
1458         _tbm_surface_mutex_lock();
1459         _tbm_set_last_result(TBM_ERROR_NONE);
1460
1461         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1462
1463         surf = (struct _tbm_surface *)surface;
1464
1465         for (i = 0; i < surf->num_bos; i++)
1466                 tbm_bo_unmap(surf->bos[i]);
1467
1468         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)", surface);
1469
1470         _tbm_surface_mutex_unlock();
1471 }
1472
1473 unsigned int
1474 tbm_surface_internal_get_width(tbm_surface_h surface)
1475 {
1476         struct _tbm_surface *surf;
1477         unsigned int width;
1478
1479         _tbm_surface_mutex_lock();
1480         _tbm_set_last_result(TBM_ERROR_NONE);
1481
1482         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1483
1484         surf = (struct _tbm_surface *)surface;
1485         width = surf->info.width;
1486
1487         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)", surface, width);
1488
1489         _tbm_surface_mutex_unlock();
1490
1491         return width;
1492 }
1493
1494 unsigned int
1495 tbm_surface_internal_get_height(tbm_surface_h surface)
1496 {
1497         struct _tbm_surface *surf;
1498         unsigned int height;
1499
1500         _tbm_surface_mutex_lock();
1501         _tbm_set_last_result(TBM_ERROR_NONE);
1502
1503         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1504
1505         surf = (struct _tbm_surface *)surface;
1506         height = surf->info.height;
1507
1508         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)", surface, height);
1509
1510         _tbm_surface_mutex_unlock();
1511
1512         return height;
1513
1514 }
1515
1516 tbm_format
1517 tbm_surface_internal_get_format(tbm_surface_h surface)
1518 {
1519         struct _tbm_surface *surf;
1520         tbm_format format;
1521
1522         _tbm_surface_mutex_lock();
1523         _tbm_set_last_result(TBM_ERROR_NONE);
1524
1525         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1526
1527         surf = (struct _tbm_surface *)surface;
1528         format = surf->info.format;
1529
1530         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)", surface, _tbm_surface_internal_format_to_str(format));
1531
1532         _tbm_surface_mutex_unlock();
1533
1534         return format;
1535 }
1536
1537 int
1538 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1539 {
1540         struct _tbm_surface *surf;
1541         int bo_idx;
1542
1543         _tbm_surface_mutex_lock();
1544         _tbm_set_last_result(TBM_ERROR_NONE);
1545
1546         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1547         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1548
1549         surf = (struct _tbm_surface *)surface;
1550         bo_idx = surf->planes_bo_idx[plane_idx];
1551
1552         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)", surface, plane_idx, bo_idx);
1553
1554         _tbm_surface_mutex_unlock();
1555
1556         return bo_idx;
1557 }
1558
1559 int
1560 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1561                                    tbm_data_free data_free_func)
1562 {
1563         tbm_user_data *data;
1564
1565         _tbm_surface_mutex_lock();
1566         _tbm_set_last_result(TBM_ERROR_NONE);
1567
1568         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1569
1570         /* check if the data according to the key exist if so, return false. */
1571         data = user_data_lookup(&surface->user_data_list, key);
1572         if (data) {
1573                 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)", surface, key);
1574                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1575                 _tbm_surface_mutex_unlock();
1576                 return 0;
1577         }
1578
1579         data = user_data_create(key, data_free_func);
1580         if (!data) {
1581                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)", surface, key);
1582                 _tbm_surface_mutex_unlock();
1583                 return 0;
1584         }
1585
1586         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)", surface, key, data);
1587
1588         LIST_ADD(&data->item_link, &surface->user_data_list);
1589
1590         _tbm_surface_mutex_unlock();
1591
1592         return 1;
1593 }
1594
1595 int
1596 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1597                                    void *data)
1598 {
1599         tbm_user_data *old_data;
1600
1601         _tbm_surface_mutex_lock();
1602         _tbm_set_last_result(TBM_ERROR_NONE);
1603
1604         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1605
1606         old_data = user_data_lookup(&surface->user_data_list, key);
1607         if (!old_data) {
1608                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)", surface, key);
1609                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1610                 _tbm_surface_mutex_unlock();
1611                 return 0;
1612         }
1613
1614         if (old_data->data && old_data->free_func)
1615                 old_data->free_func(old_data->data);
1616
1617         old_data->data = data;
1618
1619         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)", surface, key, old_data->data);
1620
1621         _tbm_surface_mutex_unlock();
1622
1623         return 1;
1624 }
1625
1626 int
1627 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1628                                    void **data)
1629 {
1630         tbm_user_data *old_data;
1631
1632         _tbm_surface_mutex_lock();
1633         _tbm_set_last_result(TBM_ERROR_NONE);
1634
1635         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1636
1637         if (!data) {
1638                 TBM_ERR("error: tbm_surface(%p) key(%lu)", surface, key);
1639                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1640                 _tbm_surface_mutex_unlock();
1641                 return 0;
1642         }
1643         *data = NULL;
1644
1645         old_data = user_data_lookup(&surface->user_data_list, key);
1646         if (!old_data) {
1647                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)", surface, key);
1648                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1649                 _tbm_surface_mutex_unlock();
1650                 return 0;
1651         }
1652
1653         *data = old_data->data;
1654
1655         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)", surface, key, old_data->data);
1656
1657         _tbm_surface_mutex_unlock();
1658
1659         return 1;
1660 }
1661
1662 int
1663 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1664                                       unsigned long key)
1665 {
1666         tbm_user_data *old_data = (void *)0;
1667
1668         _tbm_surface_mutex_lock();
1669         _tbm_set_last_result(TBM_ERROR_NONE);
1670
1671         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1672
1673         old_data = user_data_lookup(&surface->user_data_list, key);
1674         if (!old_data) {
1675                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)", surface, key);
1676                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1677                 _tbm_surface_mutex_unlock();
1678                 return 0;
1679         }
1680
1681         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)", surface, key, old_data->data);
1682
1683         user_data_delete(old_data);
1684
1685         _tbm_surface_mutex_unlock();
1686
1687         return 1;
1688 }
1689
1690 /* LCOV_EXCL_START */
1691 unsigned int
1692 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1693 {
1694         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1695
1696         return surface->debug_pid;
1697 }
1698
1699 void
1700 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1701 {
1702         _tbm_surface_mutex_lock();
1703         _tbm_set_last_result(TBM_ERROR_NONE);
1704
1705         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1706
1707         surface->debug_pid = pid;
1708
1709         _tbm_surface_mutex_unlock();
1710 }
1711
1712 static tbm_surface_debug_data *
1713 _tbm_surface_internal_debug_data_create(char *key, char *value)
1714 {
1715         tbm_surface_debug_data *debug_data = NULL;
1716
1717         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1718         if (!debug_data) {
1719                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1720                 TBM_ERR("fail to allocate the debug_data.");
1721                 return NULL;
1722         }
1723
1724         if (key) debug_data->key = strdup(key);
1725         if (value) debug_data->value = strdup(value);
1726
1727         return debug_data;
1728 }
1729
1730 static void
1731 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1732 {
1733         if (!debug_data->value && !value)
1734                 return;
1735
1736         if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1737                 return;
1738
1739         if (debug_data->value)
1740                 free(debug_data->value);
1741
1742         if (value)
1743                 debug_data->value = strdup(value);
1744         else
1745                 debug_data->value = NULL;
1746 }
1747
1748 static tbm_surface_debug_data *
1749 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1750 {
1751         tbm_surface_debug_data *debug_data = NULL;
1752
1753         if (LIST_IS_EMPTY(list))
1754                 return NULL;
1755
1756         LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
1757                 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
1758                         return debug_data;
1759         }
1760
1761         return NULL;
1762 }
1763
1764 int
1765 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1766 {
1767         tbm_surface_debug_data *debug_data = NULL;
1768         tbm_bufmgr bufmgr = NULL;
1769
1770         _tbm_surface_mutex_lock();
1771         _tbm_set_last_result(TBM_ERROR_NONE);
1772
1773         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1774         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1775
1776         bufmgr = surface->bufmgr;
1777
1778         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1779
1780         debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
1781         if (debug_data) {
1782                 _tbm_surface_internal_debug_data_value_update(debug_data, value);
1783         } else {
1784                 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1785                 if (!debug_data) {
1786                         TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)", surface, key, value);
1787                         _tbm_surface_mutex_unlock();
1788                         return 0;
1789                 }
1790
1791                 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1792         }
1793
1794         /* add new debug key to list */
1795         debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
1796         if (!debug_data) {
1797                 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1798                 if (debug_data)
1799                         LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
1800         }
1801
1802         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)", surface, key, value);
1803
1804         _tbm_surface_mutex_unlock();
1805
1806         return 1;
1807 }
1808
1809 char *
1810 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1811 {
1812         tbm_surface_debug_data *old_data = NULL;
1813
1814         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1815
1816         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1817                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1818                         if (!strcmp(old_data->key, key))
1819                                 return old_data->value;
1820                 }
1821         }
1822
1823         return NULL;
1824 }
1825
1826 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1827 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1828
1829 struct _tbm_surface_dump_buf_info {
1830         int index;
1831         tbm_bo bo;
1832         int size;
1833         int dirty;
1834         int dirty_shm;
1835         int shm_stride;
1836         int shm_h;
1837         char name[1024];
1838
1839         tbm_surface_info_s info;
1840
1841         struct list_head link;
1842 };
1843
1844 struct _tbm_surface_dump_info {
1845         char *path;  // copy???
1846         int dump_max;
1847         int count;
1848         struct list_head *link;
1849         struct list_head surface_list; /* link of surface */
1850 };
1851
1852 static tbm_surface_dump_info *g_dump_info = NULL;
1853 static const char *dump_postfix[2] = {"png", "yuv"};
1854 static double scale_factor;
1855
1856 static void
1857 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1858                                 void *data2, int size2, void *data3, int size3)
1859 {
1860         FILE *fp;
1861         unsigned int *blocks;
1862
1863         if (_tbm_surface_check_file_is_symbolic_link(file))
1864                 TBM_ERR("%s is symbolic link", file);
1865
1866         fp = fopen(file, "w+");
1867         TBM_RETURN_IF_FAIL(fp != NULL);
1868
1869         blocks = (unsigned int *)data1;
1870         fwrite(blocks, 1, size1, fp);
1871
1872         if (size2 > 0) {
1873                 blocks = (unsigned int *)data2;
1874                 fwrite(blocks, 1, size2, fp);
1875         }
1876
1877         if (size3 > 0) {
1878                 blocks = (unsigned int *)data3;
1879                 fwrite(blocks, 1, size3, fp);
1880         }
1881
1882         fclose(fp);
1883 }
1884
1885 static void
1886 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
1887 {
1888         unsigned int *blocks = (unsigned int *)data;
1889         FILE *fp;
1890         int pixel_size;
1891         png_bytep *row_pointers;
1892         int depth = 8, y;
1893
1894         if (_tbm_surface_check_file_is_symbolic_link(file))
1895                 TBM_ERR("%s is symbolic link", file);
1896
1897         fp = fopen(file, "wb");
1898         TBM_RETURN_IF_FAIL(fp != NULL);
1899
1900         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1901                                                         NULL, NULL, NULL);
1902         if (!pPngStruct) {
1903                 TBM_ERR("fail to create a png write structure.");
1904                 fclose(fp);
1905                 return;
1906         }
1907
1908         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1909         if (!pPngInfo) {
1910                 TBM_ERR("fail to create a png info structure.");
1911                 png_destroy_write_struct(&pPngStruct, NULL);
1912                 fclose(fp);
1913                 return;
1914         }
1915
1916         if (setjmp(png_jmpbuf(pPngStruct))) {
1917                 /* if png has problem of writing the file, we get here */
1918                 TBM_ERR("fail to write png file.");
1919                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1920                 fclose(fp);
1921                 return;
1922         }
1923
1924         png_init_io(pPngStruct, fp);
1925         if (format == TBM_FORMAT_XRGB8888) {
1926                 pixel_size = 3;
1927                 png_set_IHDR(pPngStruct,
1928                                 pPngInfo,
1929                                 width,
1930                                 height,
1931                                 depth,
1932                                 PNG_COLOR_TYPE_RGB,
1933                                 PNG_INTERLACE_NONE,
1934                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1935         } else {
1936                 pixel_size = 4;
1937                 png_set_IHDR(pPngStruct,
1938                                 pPngInfo,
1939                                 width,
1940                                 height,
1941                                 depth,
1942                                 PNG_COLOR_TYPE_RGBA,
1943                                 PNG_INTERLACE_NONE,
1944                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1945         }
1946
1947         png_set_bgr(pPngStruct);
1948         png_write_info(pPngStruct, pPngInfo);
1949
1950         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1951         if (!row_pointers) {
1952                 TBM_ERR("fail to allocate the png row_pointers.");
1953                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1954                 fclose(fp);
1955                 return;
1956         }
1957
1958         for (y = 0; y < height; ++y) {
1959                 png_bytep row;
1960                 int x = 0;
1961
1962                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1963                 if (!row) {
1964                         TBM_ERR("fail to allocate the png row.");
1965                         for (x = 0; x < y; x++)
1966                                 png_free(pPngStruct, row_pointers[x]);
1967                         png_free(pPngStruct, row_pointers);
1968                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1969                         fclose(fp);
1970                         return;
1971                 }
1972                 row_pointers[y] = (png_bytep)row;
1973
1974                 for (x = 0; x < width; ++x) {
1975                         unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
1976
1977                         if (pixel_size == 3) { // XRGB8888 or XBGR8888
1978                                 if (format == TBM_FORMAT_XRGB8888) {
1979                                         row[x * pixel_size] = (curBlock & 0xFF);
1980                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1981                                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1982                                 } else {
1983                                         row[x * pixel_size] = (curBlock >> 16) & 0xFF;
1984                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1985                                         row[2 + x * pixel_size] = (curBlock & 0xFF);
1986                                 }
1987                         } else { // ARGB8888 or ABGR8888
1988                                 if (format == TBM_FORMAT_ARGB8888) {
1989                                         row[x * pixel_size] = (curBlock & 0xFF);
1990                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1991                                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1992                                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1993                                 } else {
1994                                         row[x * pixel_size] = (curBlock >> 16) & 0xFF;
1995                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1996                                         row[2 + x * pixel_size] =  (curBlock & 0xFF);
1997                                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1998                                 }
1999                         }
2000                 }
2001         }
2002
2003         png_write_image(pPngStruct, row_pointers);
2004         png_write_end(pPngStruct, pPngInfo);
2005
2006         for (y = 0; y < height; y++)
2007                 png_free(pPngStruct, row_pointers[y]);
2008         png_free(pPngStruct, row_pointers);
2009
2010         png_destroy_write_struct(&pPngStruct, &pPngInfo);
2011
2012         fclose(fp);
2013 }
2014
2015 void
2016 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
2017 {
2018         TBM_RETURN_IF_FAIL(path != NULL);
2019         TBM_RETURN_IF_FAIL(w > 0);
2020         TBM_RETURN_IF_FAIL(h > 0);
2021         TBM_RETURN_IF_FAIL(count > 0);
2022
2023         tbm_surface_dump_buf_info *buf_info = NULL;
2024         tbm_surface_h tbm_surface;
2025         tbm_surface_info_s info;
2026         int buffer_size, i;
2027
2028         /* check running */
2029         if (g_dump_info) {
2030                 TBM_WRN("waring already running the tbm_surface_internal_dump.");
2031                 return;
2032         }
2033
2034         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
2035         TBM_RETURN_IF_FAIL(g_dump_info);
2036
2037         LIST_INITHEAD(&g_dump_info->surface_list);
2038         g_dump_info->count = 0;
2039         g_dump_info->dump_max = count;
2040
2041         /* get buffer size */
2042         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
2043         if (tbm_surface == NULL) {
2044                 TBM_ERR("tbm_surface_create fail");
2045                 free(g_dump_info);
2046                 g_dump_info = NULL;
2047                 return;
2048         }
2049
2050         if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
2051                 TBM_ERR("tbm_surface_get_info fail");
2052                 tbm_surface_destroy(tbm_surface);
2053                 free(g_dump_info);
2054                 g_dump_info = NULL;
2055                 return;
2056         }
2057         buffer_size = info.size;
2058         tbm_surface_destroy(tbm_surface);
2059
2060         /* create dump lists */
2061         for (i = 0; i < count; i++) {
2062                 tbm_bo bo = NULL;
2063
2064                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
2065                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
2066
2067                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
2068                 if (bo == NULL) {
2069                         TBM_ERR("fail to allocate the tbm_bo[%d]", i);
2070                         free(buf_info);
2071                         goto fail;
2072                 }
2073
2074                 buf_info->index = i;
2075                 buf_info->bo = bo;
2076                 buf_info->size = buffer_size;
2077
2078                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
2079         }
2080
2081         g_dump_info->path = path;
2082         g_dump_info->link = &g_dump_info->surface_list;
2083
2084         scale_factor = 0.0;
2085
2086         TBM_INFO("Dump Start.. path:%s, count:%d", g_dump_info->path, count);
2087
2088         return;
2089
2090 fail:
2091         /* free resources */
2092         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2093                 tbm_surface_dump_buf_info *tmp;
2094
2095                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2096                         tbm_bo_unref(buf_info->bo);
2097                         LIST_DEL(&buf_info->link);
2098                         free(buf_info);
2099                 }
2100         }
2101
2102         TBM_ERR("Dump Start fail.. path:%s", g_dump_info->path);
2103
2104         free(g_dump_info);
2105         g_dump_info = NULL;
2106
2107         return;
2108 }
2109
2110 void
2111 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
2112 {
2113         if (scale > 0.0) {
2114                 w *= scale;
2115                 h *= scale;
2116         }
2117
2118         tbm_surface_internal_dump_start(path, w, h, count);
2119         scale_factor = scale;
2120 }
2121
2122 void
2123 tbm_surface_internal_dump_end(void)
2124 {
2125         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
2126         tbm_bo_handle bo_handle;
2127
2128         if (!g_dump_info)
2129                 return;
2130
2131         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2132                 free(g_dump_info);
2133                 g_dump_info = NULL;
2134                 return;
2135         }
2136
2137         /* make files */
2138         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2139                 char file[2048];
2140
2141                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2142                 if (bo_handle.ptr == NULL) {
2143                         tbm_bo_unref(buf_info->bo);
2144                         LIST_DEL(&buf_info->link);
2145                         free(buf_info);
2146                         continue;
2147                 }
2148
2149                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2150                 TBM_INFO("Dump File.. %s generated.", file);
2151
2152                 if (buf_info->dirty) {
2153                         void *ptr1 = NULL, *ptr2 = NULL;
2154
2155                         switch (buf_info->info.format) {
2156                         case TBM_FORMAT_ARGB8888:
2157                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2158                                                         buf_info->info.planes[0].stride >> 2,
2159                                                         buf_info->info.height,
2160                                                         buf_info->info.planes[0].stride,
2161                                                         TBM_FORMAT_ARGB8888);
2162                                 break;
2163                         case TBM_FORMAT_XRGB8888:
2164                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2165                                                         buf_info->info.planes[0].stride >> 2,
2166                                                         buf_info->info.height,
2167                                                         buf_info->info.planes[0].stride,
2168                                                         TBM_FORMAT_XRGB8888);
2169                                 break;
2170                         case TBM_FORMAT_ABGR8888:
2171                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2172                                                         buf_info->info.planes[0].stride >> 2,
2173                                                         buf_info->info.height,
2174                                                         buf_info->info.planes[0].stride,
2175                                                         TBM_FORMAT_ABGR8888);
2176                                 break;
2177                         case TBM_FORMAT_XBGR8888:
2178                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2179                                                         buf_info->info.planes[0].stride >> 2,
2180                                                         buf_info->info.height,
2181                                                         buf_info->info.planes[0].stride,
2182                                                         TBM_FORMAT_XBGR8888);
2183                                 break;
2184                         case TBM_FORMAT_YVU420:
2185                         case TBM_FORMAT_YUV420:
2186                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2187                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2188                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2189                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2190                                                         ptr1,
2191                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2192                                                         ptr2,
2193                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2194                                 break;
2195                         case TBM_FORMAT_NV12:
2196                         case TBM_FORMAT_NV21:
2197                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2198                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2199                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2200                                                         ptr1,
2201                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2202                                                         NULL, 0);
2203                                 break;
2204                         case TBM_FORMAT_YUYV:
2205                         case TBM_FORMAT_UYVY:
2206                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2207                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2208                                                         NULL, 0, NULL, 0);
2209                                 break;
2210                         default:
2211                                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2212                                 break;
2213                         }
2214                 } else if (buf_info->dirty_shm)
2215                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2216                                                         buf_info->shm_stride >> 2,
2217                                                         buf_info->shm_h,
2218                                                         buf_info->shm_stride, 0);
2219
2220                 tbm_bo_unmap(buf_info->bo);
2221                 tbm_bo_unref(buf_info->bo);
2222                 LIST_DEL(&buf_info->link);
2223                 free(buf_info);
2224         }
2225
2226         free(g_dump_info);
2227         g_dump_info = NULL;
2228
2229         TBM_INFO("Dump End..");
2230 }
2231
2232 static pixman_format_code_t
2233 _tbm_surface_internal_pixman_format_get(tbm_format format)
2234 {
2235         switch (format) {
2236         case TBM_FORMAT_ARGB8888:
2237         case TBM_FORMAT_ABGR8888:
2238                 return PIXMAN_a8r8g8b8;
2239         case TBM_FORMAT_XRGB8888:
2240         case TBM_FORMAT_XBGR8888:
2241                 return PIXMAN_x8r8g8b8;
2242         default:
2243                 return 0;
2244         }
2245
2246         return 0;
2247 }
2248
2249 /**
2250  * This function supports only if a buffer has below formats.
2251  * - TBM_FORMAT_ARGB8888
2252  * - TBM_FORMAT_XRGB8888
2253  * - TBM_FORMAT_ABGR8888
2254  * - TBM_FORMAT_XBGR8888
2255  */
2256 static tbm_surface_error_e
2257 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2258                                                                    int format, int src_stride, int src_w, int src_h,
2259                                                                    int dst_stride, int dst_w, int dst_h)
2260 {
2261         pixman_image_t *src_img = NULL, *dst_img = NULL;
2262         pixman_format_code_t pixman_format;
2263         pixman_transform_t t;
2264         struct pixman_f_transform ft;
2265         double scale_x, scale_y;
2266
2267         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2268         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2269
2270         pixman_format = _tbm_surface_internal_pixman_format_get(format);
2271         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2272
2273         /* src */
2274         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2275                                                                            (uint32_t*)src_ptr, src_stride);
2276         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2277
2278         /* dst */
2279         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2280                                                                            (uint32_t*)dst_ptr, dst_stride);
2281         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2282
2283         pixman_f_transform_init_identity(&ft);
2284
2285         scale_x = (double)src_w / dst_w;
2286         scale_y = (double)src_h / dst_h;
2287
2288         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2289         pixman_f_transform_translate(&ft, NULL, 0, 0);
2290         pixman_transform_from_pixman_f_transform(&t, &ft);
2291         pixman_image_set_transform(src_img, &t);
2292
2293         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2294                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
2295
2296         pixman_image_unref(src_img);
2297         pixman_image_unref(dst_img);
2298
2299         return TBM_SURFACE_ERROR_NONE;
2300
2301 cant_convert:
2302         if (src_img)
2303                 pixman_image_unref(src_img);
2304
2305         return TBM_SURFACE_ERROR_INVALID_OPERATION;
2306 }
2307
2308 #define MAX_BOS         4       // This value is came from bos[4] in struct _tbm_surface
2309 #define KEY_LEN         5       // "_XXXX"
2310 #define KEYS_LEN        KEY_LEN * MAX_BOS
2311
2312 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2313 {
2314         char *keys, temp_key[KEY_LEN + 1];
2315         struct _tbm_surface *surf;
2316         int i, num_bos;
2317         tbm_bo bo;
2318
2319         _tbm_surface_mutex_lock();
2320
2321         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2322
2323         surf = (struct _tbm_surface *)surface;
2324
2325         num_bos = surf->num_bos;
2326         if (num_bos > MAX_BOS)
2327                 num_bos = MAX_BOS;
2328
2329         keys = calloc(KEYS_LEN + 1, sizeof(char));
2330         if (!keys) {
2331                 TBM_ERR("Failed to alloc memory");
2332                 _tbm_surface_mutex_unlock();
2333                 return NULL;
2334         }
2335
2336         for (i = 0; i < num_bos; i++) {
2337                 memset(temp_key, 0x00, KEY_LEN + 1);
2338                 bo = surf->bos[i];
2339                 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2340                 strncat(keys, temp_key, KEY_LEN + 1);
2341         }
2342
2343         _tbm_surface_mutex_unlock();
2344
2345         return keys;
2346 }
2347
2348 static void _tbm_surface_internal_put_keys(char *keys)
2349 {
2350         if (keys)
2351                 free(keys);
2352 }
2353
2354 void
2355 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2356 {
2357         TBM_RETURN_IF_FAIL(surface != NULL);
2358         TBM_RETURN_IF_FAIL(type != NULL);
2359
2360         tbm_surface_dump_buf_info *buf_info;
2361         struct list_head *next_link;
2362         tbm_surface_info_s info;
2363         tbm_bo_handle bo_handle;
2364         const char *postfix;
2365         const char *format = NULL;
2366         char *keys;
2367         int ret;
2368         struct timespec tp;
2369
2370         if (!g_dump_info)
2371                 return;
2372
2373         next_link = g_dump_info->link->next;
2374         TBM_RETURN_IF_FAIL(next_link != NULL);
2375
2376         if (next_link == &g_dump_info->surface_list) {
2377                 next_link = next_link->next;
2378                 TBM_RETURN_IF_FAIL(next_link != NULL);
2379         }
2380
2381         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2382         TBM_RETURN_IF_FAIL(buf_info != NULL);
2383
2384         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2385         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2386
2387         if (scale_factor > 0.0) {
2388                 const int bpp = 4;
2389
2390                 if ((info.format != TBM_FORMAT_ARGB8888) && (info.format != TBM_FORMAT_XRGB8888) &&
2391                     (info.format != TBM_FORMAT_ABGR8888) && (info.format != TBM_FORMAT_XBGR8888)) {
2392                         TBM_WRN("Dump with scale skip. unsupported format(%s)",
2393                                           _tbm_surface_internal_format_to_str(info.format));
2394                         tbm_surface_unmap(surface);
2395                         return;
2396                 }
2397
2398                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2399
2400                 buf_info->info.width = info.width * scale_factor;
2401                 buf_info->info.height = info.height * scale_factor;
2402                 buf_info->info.format = info.format;
2403                 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2404                 if (!buf_info->info.bpp) {
2405                         TBM_ERR("fail to get bpp. error(%s)", tbm_error_str(tbm_get_last_error()));
2406                         tbm_surface_unmap(surface);
2407                         return;
2408                 }
2409                 buf_info->info.num_planes = 1;
2410                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2411                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2412
2413                 if (buf_info->info.size > buf_info->size) {
2414                         TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)",
2415                                         buf_info->info.size, buf_info->size);
2416                         tbm_surface_unmap(surface);
2417                         return;
2418                 }
2419         } else {
2420                 if (info.size > buf_info->size) {
2421                         TBM_WRN("Dump skip. surface over created buffer size(%u, %d)",
2422                                         info.size, buf_info->size);
2423                         tbm_surface_unmap(surface);
2424                         return;
2425                 }
2426
2427                 /* make the file information */
2428                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2429         }
2430
2431         if ((info.format == TBM_FORMAT_ARGB8888) || (info.format == TBM_FORMAT_XRGB8888) ||
2432                 (info.format == TBM_FORMAT_ABGR8888) || (info.format == TBM_FORMAT_XBGR8888)) {
2433                 postfix = dump_postfix[0];
2434                 format = _tbm_surface_internal_format_to_str(info.format);
2435         } else
2436                 postfix = dump_postfix[1];
2437
2438         keys = _tbm_surface_internal_get_keys(surface);
2439         if (!keys) {
2440                 TBM_ERR("fail to get keys");
2441                 tbm_surface_unmap(surface);
2442                 return;
2443         }
2444
2445         /* dump */
2446         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2447         if (!bo_handle.ptr) {
2448                 TBM_ERR("fail to map bo");
2449                 _tbm_surface_internal_put_keys(keys);
2450                 tbm_surface_unmap(surface);
2451                 return;
2452         }
2453         memset(bo_handle.ptr, 0x00, buf_info->size);
2454
2455         clock_gettime(CLOCK_MONOTONIC, &tp);
2456
2457         switch (info.format) {
2458         case TBM_FORMAT_ARGB8888:
2459         case TBM_FORMAT_XRGB8888:
2460         case TBM_FORMAT_ABGR8888:
2461         case TBM_FORMAT_XBGR8888:
2462                 snprintf(buf_info->name, sizeof(buf_info->name),
2463                                 "%d.%03d_%03d%s_%p_%s-%s.%s",
2464                                  (int)tp.tv_sec, (int)tp.tv_nsec / 1000000,
2465                                  g_dump_info->count++, keys, surface, format, type, postfix);
2466
2467                 if (scale_factor > 0.0) {
2468                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2469                                                                                                          bo_handle.ptr,
2470                                                                                                          buf_info->info.format,
2471                                                                                                          info.planes[0].stride,
2472                                                                                                          info.width, info.height,
2473                                                                                                          buf_info->info.planes[0].stride,
2474                                                                                                          buf_info->info.width,
2475                                                                                                          buf_info->info.height);
2476                         if (ret != TBM_SURFACE_ERROR_NONE) {
2477                                 TBM_ERR("fail to scale buffer");
2478                                 tbm_bo_unmap(buf_info->bo);
2479                                 _tbm_surface_internal_put_keys(keys);
2480                                 tbm_surface_unmap(surface);
2481                                 return;
2482                         }
2483                 } else
2484                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2485                 break;
2486         case TBM_FORMAT_YVU420:
2487         case TBM_FORMAT_YUV420:
2488                 snprintf(buf_info->name, sizeof(buf_info->name),
2489                                 "%d.%03d_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2490                                  (int)tp.tv_sec, (int)tp.tv_nsec / 1000000,
2491                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2492                                 info.height, FOURCC_STR(info.format), postfix);
2493                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2494                 bo_handle.ptr += info.planes[0].stride * info.height;
2495                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2496                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2497                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2498                 break;
2499         case TBM_FORMAT_NV12:
2500         case TBM_FORMAT_NV21:
2501                 snprintf(buf_info->name, sizeof(buf_info->name),
2502                                 "%d.%03d_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2503                                  (int)tp.tv_sec, (int)tp.tv_nsec / 1000000,
2504                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2505                                 info.height, FOURCC_STR(info.format), postfix);
2506                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2507                 bo_handle.ptr += info.planes[0].stride * info.height;
2508                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2509                 break;
2510         case TBM_FORMAT_YUYV:
2511         case TBM_FORMAT_UYVY:
2512                 snprintf(buf_info->name, sizeof(buf_info->name),
2513                                 "%d.%03d_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2514                                  (int)tp.tv_sec, (int)tp.tv_nsec / 1000000,
2515                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2516                                 info.height, FOURCC_STR(info.format), postfix);
2517                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2518                 break;
2519         default:
2520                 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2521                 tbm_bo_unmap(buf_info->bo);
2522                 _tbm_surface_internal_put_keys(keys);
2523                 tbm_surface_unmap(surface);
2524                 return;
2525         }
2526
2527         tbm_bo_unmap(buf_info->bo);
2528
2529         _tbm_surface_internal_put_keys(keys);
2530
2531         tbm_surface_unmap(surface);
2532
2533         buf_info->dirty = 1;
2534         buf_info->dirty_shm = 0;
2535
2536         if (g_dump_info->count == 1000)
2537                 g_dump_info->count = 0;
2538
2539         g_dump_info->link = next_link;
2540
2541         TBM_INFO("Dump %s ", buf_info->name);
2542 }
2543
2544 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2545                                                 const char *type)
2546 {
2547         TBM_RETURN_IF_FAIL(ptr != NULL);
2548         TBM_RETURN_IF_FAIL(w > 0);
2549         TBM_RETURN_IF_FAIL(h > 0);
2550         TBM_RETURN_IF_FAIL(stride > 0);
2551         TBM_RETURN_IF_FAIL(type != NULL);
2552
2553         tbm_surface_dump_buf_info *buf_info;
2554         struct list_head *next_link;
2555         tbm_bo_handle bo_handle;
2556         int ret, size, dw = 0, dh = 0, dstride = 0;
2557         struct timespec tp;
2558
2559         if (!g_dump_info)
2560                 return;
2561
2562         next_link = g_dump_info->link->next;
2563         TBM_RETURN_IF_FAIL(next_link != NULL);
2564
2565         if (next_link == &g_dump_info->surface_list) {
2566                 next_link = next_link->next;
2567                 TBM_RETURN_IF_FAIL(next_link != NULL);
2568         }
2569
2570         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2571         TBM_RETURN_IF_FAIL(buf_info != NULL);
2572
2573         if (scale_factor > 0.0) {
2574                 const int bpp = 4;
2575
2576                 dw = w * scale_factor;
2577                 dh = h * scale_factor;
2578                 dstride = dw * bpp;
2579                 size = dstride * dh;
2580         } else
2581                 size = stride * h;
2582
2583         if (size > buf_info->size) {
2584                 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)",
2585                                 size, buf_info->size);
2586                 return;
2587         }
2588
2589         /* dump */
2590         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2591         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2592
2593         memset(bo_handle.ptr, 0x00, buf_info->size);
2594         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2595
2596         clock_gettime(CLOCK_MONOTONIC, &tp);
2597
2598         snprintf(buf_info->name, sizeof(buf_info->name), "%d.%03d_%03d-%s.%s",
2599                          (int)tp.tv_sec, (int)tp.tv_nsec / 1000000,
2600                          g_dump_info->count++, type, dump_postfix[0]);
2601         if (scale_factor > 0.0) {
2602                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2603                                                                                                  TBM_FORMAT_ARGB8888, stride,
2604                                                                                                  w, h, dstride, dw, dh);
2605                 if (ret != TBM_SURFACE_ERROR_NONE) {
2606                         TBM_ERR("fail to scale buffer");
2607                         tbm_bo_unmap(buf_info->bo);
2608                         return;
2609                 }
2610                 buf_info->shm_stride = dstride;
2611                 buf_info->shm_h = dh;
2612         } else {
2613                 memcpy(bo_handle.ptr, ptr, size);
2614                 buf_info->shm_stride = stride;
2615                 buf_info->shm_h = h;
2616         }
2617
2618         tbm_bo_unmap(buf_info->bo);
2619
2620         buf_info->dirty = 0;
2621         buf_info->dirty_shm = 1;
2622
2623         if (g_dump_info->count == 1000)
2624                 g_dump_info->count = 0;
2625
2626         g_dump_info->link = next_link;
2627
2628         TBM_INFO("Dump %s ", buf_info->name);
2629 }
2630
2631 int
2632 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2633 {
2634         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2635         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2636         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2637
2638         tbm_surface_info_s info;
2639         const char *postfix;
2640         int ret;
2641         char file[1024];
2642
2643         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2644         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2645
2646         if ((info.format == TBM_FORMAT_ARGB8888) || (info.format == TBM_FORMAT_XRGB8888) ||
2647             (info.format == TBM_FORMAT_ABGR8888) || (info.format == TBM_FORMAT_XBGR8888))
2648                 postfix = dump_postfix[0];
2649         else
2650                 postfix = dump_postfix[1];
2651
2652         if (strcmp(postfix, type)) {
2653                 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2654                 tbm_surface_unmap(surface);
2655                 return 0;
2656         }
2657
2658         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2659
2660         if (!access(file, 0)) {
2661                 TBM_ERR("can't capture  buffer, exist file %s", file);
2662                 tbm_surface_unmap(surface);
2663                 return 0;
2664         }
2665
2666         switch (info.format) {
2667         case TBM_FORMAT_ARGB8888:
2668                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2669                                                         info.width,
2670                                                         info.height,
2671                                                         info.planes[0].stride,
2672                                                         TBM_FORMAT_ARGB8888);
2673                 break;
2674         case TBM_FORMAT_XRGB8888:
2675                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2676                                                         info.width,
2677                                                         info.height,
2678                                                         info.planes[0].stride,
2679                                                         TBM_FORMAT_XRGB8888);
2680                 break;
2681         case TBM_FORMAT_ABGR8888:
2682                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2683                                                         info.width,
2684                                                         info.height,
2685                                                         info.planes[0].stride,
2686                                                         TBM_FORMAT_ABGR8888);
2687                 break;
2688         case TBM_FORMAT_XBGR8888:
2689                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2690                                                         info.width,
2691                                                         info.height,
2692                                                         info.planes[0].stride,
2693                                                         TBM_FORMAT_XBGR8888);
2694                 break;
2695         case TBM_FORMAT_YVU420:
2696         case TBM_FORMAT_YUV420:
2697                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2698                                 info.planes[0].stride * info.height,
2699                                 info.planes[1].ptr,
2700                                 info.planes[1].stride * (info.height >> 1),
2701                                 info.planes[2].ptr,
2702                                 info.planes[2].stride * (info.height >> 1));
2703                 break;
2704         case TBM_FORMAT_NV12:
2705         case TBM_FORMAT_NV21:
2706                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2707                                         info.planes[0].stride * info.height,
2708                                         info.planes[1].ptr,
2709                                         info.planes[1].stride * (info.height >> 1),
2710                                         NULL, 0);
2711                 break;
2712         case TBM_FORMAT_YUYV:
2713         case TBM_FORMAT_UYVY:
2714                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2715                                         info.planes[0].stride * info.height,
2716                                         NULL, 0, NULL, 0);
2717                 break;
2718         default:
2719                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2720                 tbm_surface_unmap(surface);
2721                 return 0;
2722         }
2723
2724         tbm_surface_unmap(surface);
2725
2726         TBM_TRACE_SURFACE_INTERNAL("Capture %s ", file);
2727
2728         return 1;
2729 }
2730
2731 int
2732 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2733                                                 const char *path, const char *name, const char *type)
2734 {
2735         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2736         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2737         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2738         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2739         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2740         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2741
2742         char file[1024];
2743
2744         if (strcmp(dump_postfix[0], type)) {
2745                 TBM_ERR("Not supported type:%s'", type);
2746                 return 0;
2747         }
2748
2749         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2750
2751         if (!access(file, 0)) {
2752                 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2753                 return 0;
2754         }
2755
2756         _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2757
2758         TBM_TRACE_SURFACE_INTERNAL("Capture %s ", file);
2759
2760         return 1;
2761 }
2762
2763 int
2764 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2765 {
2766         struct _tbm_surface *surf;
2767
2768         _tbm_surface_mutex_lock();
2769         _tbm_set_last_result(TBM_ERROR_NONE);
2770
2771         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2772         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2773         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2774
2775         surf = (struct _tbm_surface *)surface;
2776
2777         surf->damage.x = x;
2778         surf->damage.y = y;
2779         surf->damage.width = width;
2780         surf->damage.height = height;
2781
2782         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)",
2783                                                         surface, x, y, width, height);
2784
2785         _tbm_surface_mutex_unlock();
2786
2787         return 1;
2788 }
2789
2790 int
2791 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2792 {
2793         struct _tbm_surface *surf;
2794
2795         _tbm_surface_mutex_lock();
2796         _tbm_set_last_result(TBM_ERROR_NONE);
2797
2798         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2799
2800         surf = (struct _tbm_surface *)surface;
2801
2802         if (x) *x = surf->damage.x;
2803         if (y) *y = surf->damage.y;
2804         if (width) *width = surf->damage.width;
2805         if (height) *height = surf->damage.height;
2806
2807         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)",
2808                                                         surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2809
2810         _tbm_surface_mutex_unlock();
2811
2812         return 1;
2813 }
2814
2815 int
2816 tbm_surface_internal_add_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2817 {
2818         struct _tbm_surface *surf;
2819         tbm_surface_destroy_func_info *func_info = NULL;
2820
2821         _tbm_surface_mutex_lock();
2822         _tbm_set_last_result(TBM_ERROR_NONE);
2823
2824         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2825         TBM_SURFACE_RETURN_VAL_IF_FAIL(func != NULL, 0);
2826
2827         surf = (struct _tbm_surface *)surface;
2828         LIST_FOR_EACH_ENTRY(func_info, &surf->destroy_funcs, item_link) {
2829                 if (func_info->destroy_func == func && func_info->user_data == user_data) {
2830                         TBM_ERR("can't add twice");
2831                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
2832                         _tbm_surface_mutex_unlock();
2833                         return 0;
2834                 }
2835         }
2836
2837         func_info = calloc(1, sizeof(tbm_surface_destroy_func_info));
2838         if (func_info == NULL) {
2839                 TBM_ERR("alloc failed");
2840                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2841                 _tbm_surface_mutex_unlock();
2842                 return 0;
2843         }
2844
2845         func_info->destroy_func = func;
2846         func_info->user_data = user_data;
2847
2848         LIST_ADDTAIL(&func_info->item_link, &surf->destroy_funcs);
2849
2850         _tbm_surface_mutex_unlock();
2851
2852         return 1;
2853 }
2854
2855 void
2856 tbm_surface_internal_remove_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2857 {
2858         struct _tbm_surface *surf;
2859         tbm_surface_destroy_func_info *func_info = NULL, *next = NULL;
2860
2861         _tbm_surface_mutex_lock();
2862         _tbm_set_last_result(TBM_ERROR_NONE);
2863
2864         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
2865         TBM_SURFACE_RETURN_IF_FAIL(func != NULL);
2866
2867         surf = (struct _tbm_surface *)surface;
2868         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &surf->destroy_funcs, item_link) {
2869                 if (func_info->destroy_func != func || func_info->user_data != user_data)
2870                         continue;
2871
2872                 LIST_DEL(&func_info->item_link);
2873                 free(func_info);
2874
2875                 _tbm_surface_mutex_unlock();
2876
2877                 return;
2878         }
2879
2880         _tbm_surface_mutex_unlock();
2881 }
2882
2883 tbm_surface_buffer_data *
2884 tbm_surface_internal_export(tbm_surface_h surface, tbm_error_e *error)
2885 {
2886         tbm_surface_buffer_data *buffer_data = NULL;
2887         struct _tbm_bufmgr *bufmgr;
2888
2889         _tbm_surface_mutex_lock();
2890
2891         bufmgr = g_surface_bufmgr;
2892         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr != NULL, NULL, error, TBM_ERROR_INVALID_OPERATION);
2893
2894         // this function supports when the module suppport surface_data.
2895         TBM_SURFACE_RETURN_VAL_SET_ERR_NO_LOG_IF_FAIL(tbm_bufmgr_internal_support_capabilites(bufmgr, TBM_BUFMGR_CAPABILITY_SHARE_SURFACE), NULL, error, TBM_ERROR_NOT_SUPPORTED);
2896
2897         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL, error, TBM_ERROR_INVALID_PARAMETER);
2898
2899         // export a surface
2900         buffer_data = tbm_surface_data_export(surface->surface_data, error);
2901         TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(buffer_data != NULL, NULL, *error);
2902
2903         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) buffer_data(%p)", surface, buffer_data);
2904
2905         _tbm_set_last_result(TBM_ERROR_NONE);
2906         _tbm_surface_mutex_unlock();
2907
2908         return buffer_data;
2909 }
2910
2911 tbm_surface_h
2912 tbm_surface_internal_import(tbm_surface_info_s *surface_info, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)
2913 {
2914         struct _tbm_surface *surf;
2915         struct _tbm_bufmgr *bufmgr;
2916
2917         _tbm_surface_mutex_lock();
2918
2919         bufmgr = g_surface_bufmgr;
2920         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr != NULL, NULL, error, TBM_ERROR_INVALID_OPERATION);
2921
2922         // this function supports when the module suppport surface_data.
2923         TBM_SURFACE_RETURN_VAL_SET_ERR_NO_LOG_IF_FAIL(tbm_bufmgr_internal_support_capabilites(bufmgr, TBM_BUFMGR_CAPABILITY_SHARE_SURFACE), NULL, error, TBM_ERROR_NOT_SUPPORTED);
2924
2925         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info != NULL, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2926         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info->width > 0, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2927         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info->height > 0, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2928         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(buffer_data != NULL, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2929
2930         // import a surface
2931         surf = _tbm_surface_internal_import_surface(bufmgr,
2932                                                                                                         (int)surface_info->width,
2933                                                                                                         (int)surface_info->height,
2934                                                                                                         (int)surface_info->format,
2935                                                                                                         buffer_data,
2936                                                                                                         error);
2937         TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(surf != NULL, NULL, *error);
2938
2939         LIST_INITHEAD(&surf->user_data_list);
2940         LIST_INITHEAD(&surf->debug_data_list);
2941         LIST_INITHEAD(&surf->destroy_funcs);
2942
2943         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
2944
2945         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)", surf);
2946
2947         _tbm_set_last_result(TBM_ERROR_NONE);
2948         _tbm_surface_mutex_unlock();
2949
2950         return (tbm_surface_h)surf;
2951 }
2952
2953 /*LCOV_EXCL_STOP*/