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