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