tbm_surface_internal: fix wrong last result when tbm_bo_map is failed
[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 can_share_surface)
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 (can_share_surface) {
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 (can_share_surface) {
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 can_share_surface = 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         can_share_surface = tbm_bufmgr_internal_support_capabilites(bufmgr, TBM_BUFMGR_CAPABILITY_SHARE_SURFACE);
804         if (can_share_surface) {
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, can_share_surface);
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         tbm_error_e error;
1391
1392         _tbm_surface_mutex_lock();
1393         _tbm_set_last_result(TBM_ERROR_NONE);
1394
1395         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1396
1397         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1398
1399         surf = (struct _tbm_surface *)surface;
1400
1401         memset(info, 0x00, sizeof(tbm_surface_info_s));
1402         info->width = surf->info.width;
1403         info->height = surf->info.height;
1404         info->format = surf->info.format;
1405         info->bpp = surf->info.bpp;
1406         info->size = surf->info.size;
1407         info->num_planes = surf->info.num_planes;
1408
1409         for (i = 0; i < surf->info.num_planes; i++) {
1410                 info->planes[i].size = surf->info.planes[i].size;
1411                 info->planes[i].offset = surf->info.planes[i].offset;
1412                 info->planes[i].stride = surf->info.planes[i].stride;
1413                 planes_bo_idx[i] = surf->planes_bo_idx[i];
1414         }
1415
1416         for (i = 0; i < surf->num_bos; i++)
1417                 bos[i] = surf->bos[i];
1418
1419         num_bos = surf->num_bos;
1420
1421         if (map == 1) {
1422                 _tbm_surface_mutex_unlock();
1423                 for (i = 0; i < num_bos; i++) {
1424                         bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1425                         if (bo_handles[i].ptr == NULL) {
1426                                 error = tbm_get_last_error();
1427                                 for (j = 0; j < i; j++)
1428                                         tbm_bo_unmap(bos[j]);
1429
1430                                 _tbm_set_last_result(error);
1431                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1432                                 return 0;
1433                         }
1434                 }
1435                 _tbm_surface_mutex_lock();
1436         } else {
1437                 for (i = 0; i < num_bos; i++) {
1438                         bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1439                         if (bo_handles[i].ptr == NULL) {
1440                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1441                                 _tbm_surface_mutex_unlock();
1442                                 return 0;
1443                         }
1444                 }
1445         }
1446
1447         for (i = 0; i < info->num_planes; i++) {
1448                 if (bo_handles[planes_bo_idx[i]].ptr)
1449                         info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1450         }
1451
1452         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1453
1454         _tbm_surface_mutex_unlock();
1455
1456         return 1;
1457 }
1458
1459 void
1460 tbm_surface_internal_unmap(tbm_surface_h surface)
1461 {
1462         struct _tbm_surface *surf;
1463         int i;
1464
1465         _tbm_surface_mutex_lock();
1466         _tbm_set_last_result(TBM_ERROR_NONE);
1467
1468         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1469
1470         surf = (struct _tbm_surface *)surface;
1471
1472         for (i = 0; i < surf->num_bos; i++)
1473                 tbm_bo_unmap(surf->bos[i]);
1474
1475         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1476
1477         _tbm_surface_mutex_unlock();
1478 }
1479
1480 unsigned int
1481 tbm_surface_internal_get_width(tbm_surface_h surface)
1482 {
1483         struct _tbm_surface *surf;
1484         unsigned int width;
1485
1486         _tbm_surface_mutex_lock();
1487         _tbm_set_last_result(TBM_ERROR_NONE);
1488
1489         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1490
1491         surf = (struct _tbm_surface *)surface;
1492         width = surf->info.width;
1493
1494         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1495
1496         _tbm_surface_mutex_unlock();
1497
1498         return width;
1499 }
1500
1501 unsigned int
1502 tbm_surface_internal_get_height(tbm_surface_h surface)
1503 {
1504         struct _tbm_surface *surf;
1505         unsigned int height;
1506
1507         _tbm_surface_mutex_lock();
1508         _tbm_set_last_result(TBM_ERROR_NONE);
1509
1510         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1511
1512         surf = (struct _tbm_surface *)surface;
1513         height = surf->info.height;
1514
1515         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1516
1517         _tbm_surface_mutex_unlock();
1518
1519         return height;
1520
1521 }
1522
1523 tbm_format
1524 tbm_surface_internal_get_format(tbm_surface_h surface)
1525 {
1526         struct _tbm_surface *surf;
1527         tbm_format format;
1528
1529         _tbm_surface_mutex_lock();
1530         _tbm_set_last_result(TBM_ERROR_NONE);
1531
1532         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1533
1534         surf = (struct _tbm_surface *)surface;
1535         format = surf->info.format;
1536
1537         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1538
1539         _tbm_surface_mutex_unlock();
1540
1541         return format;
1542 }
1543
1544 int
1545 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1546 {
1547         struct _tbm_surface *surf;
1548         int bo_idx;
1549
1550         _tbm_surface_mutex_lock();
1551         _tbm_set_last_result(TBM_ERROR_NONE);
1552
1553         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1554         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1555
1556         surf = (struct _tbm_surface *)surface;
1557         bo_idx = surf->planes_bo_idx[plane_idx];
1558
1559         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1560
1561         _tbm_surface_mutex_unlock();
1562
1563         return bo_idx;
1564 }
1565
1566 int
1567 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1568                                    tbm_data_free data_free_func)
1569 {
1570         tbm_user_data *data;
1571
1572         _tbm_surface_mutex_lock();
1573         _tbm_set_last_result(TBM_ERROR_NONE);
1574
1575         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1576
1577         /* check if the data according to the key exist if so, return false. */
1578         data = user_data_lookup(&surface->user_data_list, key);
1579         if (data) {
1580                 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1581                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1582                 _tbm_surface_mutex_unlock();
1583                 return 0;
1584         }
1585
1586         data = user_data_create(key, data_free_func);
1587         if (!data) {
1588                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1589                 _tbm_surface_mutex_unlock();
1590                 return 0;
1591         }
1592
1593         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1594
1595         LIST_ADD(&data->item_link, &surface->user_data_list);
1596
1597         _tbm_surface_mutex_unlock();
1598
1599         return 1;
1600 }
1601
1602 int
1603 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1604                                    void *data)
1605 {
1606         tbm_user_data *old_data;
1607
1608         _tbm_surface_mutex_lock();
1609         _tbm_set_last_result(TBM_ERROR_NONE);
1610
1611         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1612
1613         old_data = user_data_lookup(&surface->user_data_list, key);
1614         if (!old_data) {
1615                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1616                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1617                 _tbm_surface_mutex_unlock();
1618                 return 0;
1619         }
1620
1621         if (old_data->data && old_data->free_func)
1622                 old_data->free_func(old_data->data);
1623
1624         old_data->data = data;
1625
1626         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1627
1628         _tbm_surface_mutex_unlock();
1629
1630         return 1;
1631 }
1632
1633 int
1634 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1635                                    void **data)
1636 {
1637         tbm_user_data *old_data;
1638
1639         _tbm_surface_mutex_lock();
1640         _tbm_set_last_result(TBM_ERROR_NONE);
1641
1642         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1643
1644         if (!data) {
1645                 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1646                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1647                 _tbm_surface_mutex_unlock();
1648                 return 0;
1649         }
1650         *data = NULL;
1651
1652         old_data = user_data_lookup(&surface->user_data_list, key);
1653         if (!old_data) {
1654                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1655                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1656                 _tbm_surface_mutex_unlock();
1657                 return 0;
1658         }
1659
1660         *data = old_data->data;
1661
1662         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1663
1664         _tbm_surface_mutex_unlock();
1665
1666         return 1;
1667 }
1668
1669 int
1670 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1671                                       unsigned long key)
1672 {
1673         tbm_user_data *old_data = (void *)0;
1674
1675         _tbm_surface_mutex_lock();
1676         _tbm_set_last_result(TBM_ERROR_NONE);
1677
1678         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1679
1680         old_data = user_data_lookup(&surface->user_data_list, key);
1681         if (!old_data) {
1682                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1683                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1684                 _tbm_surface_mutex_unlock();
1685                 return 0;
1686         }
1687
1688         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1689
1690         user_data_delete(old_data);
1691
1692         _tbm_surface_mutex_unlock();
1693
1694         return 1;
1695 }
1696
1697 /* LCOV_EXCL_START */
1698 unsigned int
1699 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1700 {
1701         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1702
1703         return surface->debug_pid;
1704 }
1705
1706 void
1707 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1708 {
1709         _tbm_surface_mutex_lock();
1710         _tbm_set_last_result(TBM_ERROR_NONE);
1711
1712         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1713
1714         surface->debug_pid = pid;
1715
1716         _tbm_surface_mutex_unlock();
1717 }
1718
1719 static tbm_surface_debug_data *
1720 _tbm_surface_internal_debug_data_create(char *key, char *value)
1721 {
1722         tbm_surface_debug_data *debug_data = NULL;
1723
1724         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1725         if (!debug_data) {
1726                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1727                 TBM_ERR("fail to allocate the debug_data.");
1728                 return NULL;
1729         }
1730
1731         if (key) debug_data->key = strdup(key);
1732         if (value) debug_data->value = strdup(value);
1733
1734         return debug_data;
1735 }
1736
1737 static void
1738 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1739 {
1740         if (!debug_data->value && !value)
1741                 return;
1742
1743         if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1744                 return;
1745
1746         if (debug_data->value)
1747                 free(debug_data->value);
1748
1749         if (value)
1750                 debug_data->value = strdup(value);
1751         else
1752                 debug_data->value = NULL;
1753 }
1754
1755 static tbm_surface_debug_data *
1756 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1757 {
1758         tbm_surface_debug_data *debug_data = NULL;
1759
1760         if (LIST_IS_EMPTY(list))
1761                 return NULL;
1762
1763         LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
1764                 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
1765                         return debug_data;
1766         }
1767
1768         return NULL;
1769 }
1770
1771 int
1772 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1773 {
1774         tbm_surface_debug_data *debug_data = NULL;
1775         tbm_bufmgr bufmgr = NULL;
1776
1777         _tbm_surface_mutex_lock();
1778         _tbm_set_last_result(TBM_ERROR_NONE);
1779
1780         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1781         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1782
1783         bufmgr = surface->bufmgr;
1784
1785         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1786
1787         debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
1788         if (debug_data) {
1789                 _tbm_surface_internal_debug_data_value_update(debug_data, value);
1790         } else {
1791                 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1792                 if (!debug_data) {
1793                         TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1794                         _tbm_surface_mutex_unlock();
1795                         return 0;
1796                 }
1797
1798                 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1799         }
1800
1801         /* add new debug key to list */
1802         debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
1803         if (!debug_data) {
1804                 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1805                 if (debug_data)
1806                         LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
1807         }
1808
1809         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1810
1811         _tbm_surface_mutex_unlock();
1812
1813         return 1;
1814 }
1815
1816 char *
1817 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1818 {
1819         tbm_surface_debug_data *old_data = NULL;
1820
1821         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1822
1823         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1824                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1825                         if (!strcmp(old_data->key, key))
1826                                 return old_data->value;
1827                 }
1828         }
1829
1830         return NULL;
1831 }
1832
1833 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1834 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1835
1836 struct _tbm_surface_dump_buf_info {
1837         int index;
1838         tbm_bo bo;
1839         int size;
1840         int dirty;
1841         int dirty_shm;
1842         int shm_stride;
1843         int shm_h;
1844         char name[1024];
1845
1846         tbm_surface_info_s info;
1847
1848         struct list_head link;
1849 };
1850
1851 struct _tbm_surface_dump_info {
1852         char *path;  // copy???
1853         int dump_max;
1854         int count;
1855         struct list_head *link;
1856         struct list_head surface_list; /* link of surface */
1857 };
1858
1859 static tbm_surface_dump_info *g_dump_info = NULL;
1860 static const char *dump_postfix[2] = {"png", "yuv"};
1861 static double scale_factor;
1862
1863 static void
1864 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1865                                 void *data2, int size2, void *data3, int size3)
1866 {
1867         FILE *fp;
1868         unsigned int *blocks;
1869
1870         if (_tbm_surface_check_file_is_symbolic_link(file))
1871                 TBM_ERR("%s is symbolic link\n", file);
1872
1873         fp = fopen(file, "w+");
1874         TBM_RETURN_IF_FAIL(fp != NULL);
1875
1876         blocks = (unsigned int *)data1;
1877         fwrite(blocks, 1, size1, fp);
1878
1879         if (size2 > 0) {
1880                 blocks = (unsigned int *)data2;
1881                 fwrite(blocks, 1, size2, fp);
1882         }
1883
1884         if (size3 > 0) {
1885                 blocks = (unsigned int *)data3;
1886                 fwrite(blocks, 1, size3, fp);
1887         }
1888
1889         fclose(fp);
1890 }
1891
1892 static void
1893 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
1894 {
1895         unsigned int *blocks = (unsigned int *)data;
1896         FILE *fp;
1897         int pixel_size;
1898         png_bytep *row_pointers;
1899         int depth = 8, y;
1900
1901         if (_tbm_surface_check_file_is_symbolic_link(file))
1902                 TBM_ERR("%s is symbolic link\n", file);
1903
1904         fp = fopen(file, "wb");
1905         TBM_RETURN_IF_FAIL(fp != NULL);
1906
1907         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1908                                                         NULL, NULL, NULL);
1909         if (!pPngStruct) {
1910                 TBM_ERR("fail to create a png write structure.\n");
1911                 fclose(fp);
1912                 return;
1913         }
1914
1915         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1916         if (!pPngInfo) {
1917                 TBM_ERR("fail to create a png info structure.\n");
1918                 png_destroy_write_struct(&pPngStruct, NULL);
1919                 fclose(fp);
1920                 return;
1921         }
1922
1923         if (setjmp(png_jmpbuf(pPngStruct))) {
1924                 /* if png has problem of writing the file, we get here */
1925                 TBM_ERR("fail to write png file.\n");
1926                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1927                 fclose(fp);
1928                 return;
1929         }
1930
1931         png_init_io(pPngStruct, fp);
1932         if (format == TBM_FORMAT_XRGB8888) {
1933                 pixel_size = 3;
1934                 png_set_IHDR(pPngStruct,
1935                                 pPngInfo,
1936                                 width,
1937                                 height,
1938                                 depth,
1939                                 PNG_COLOR_TYPE_RGB,
1940                                 PNG_INTERLACE_NONE,
1941                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1942         } else {
1943                 pixel_size = 4;
1944                 png_set_IHDR(pPngStruct,
1945                                 pPngInfo,
1946                                 width,
1947                                 height,
1948                                 depth,
1949                                 PNG_COLOR_TYPE_RGBA,
1950                                 PNG_INTERLACE_NONE,
1951                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1952         }
1953
1954         png_set_bgr(pPngStruct);
1955         png_write_info(pPngStruct, pPngInfo);
1956
1957         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1958         if (!row_pointers) {
1959                 TBM_ERR("fail to allocate the png row_pointers.\n");
1960                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1961                 fclose(fp);
1962                 return;
1963         }
1964
1965         for (y = 0; y < height; ++y) {
1966                 png_bytep row;
1967                 int x = 0;
1968
1969                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1970                 if (!row) {
1971                         TBM_ERR("fail to allocate the png row.\n");
1972                         for (x = 0; x < y; x++)
1973                                 png_free(pPngStruct, row_pointers[x]);
1974                         png_free(pPngStruct, row_pointers);
1975                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1976                         fclose(fp);
1977                         return;
1978                 }
1979                 row_pointers[y] = (png_bytep)row;
1980
1981                 for (x = 0; x < width; ++x) {
1982                         unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
1983
1984                         if (pixel_size == 3) { // XRGB8888 or XBGR8888
1985                                 if (format == TBM_FORMAT_XRGB8888) {
1986                                         row[x * pixel_size] = (curBlock & 0xFF);
1987                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1988                                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1989                                 } else {
1990                                         row[x * pixel_size] = (curBlock >> 16) & 0xFF;
1991                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1992                                         row[2 + x * pixel_size] = (curBlock & 0xFF);
1993                                 }
1994                         } else { // ARGB8888 or ABGR8888
1995                                 if (format == TBM_FORMAT_ARGB8888) {
1996                                         row[x * pixel_size] = (curBlock & 0xFF);
1997                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1998                                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1999                                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
2000                                 } else {
2001                                         row[x * pixel_size] = (curBlock >> 16) & 0xFF;
2002                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2003                                         row[2 + x * pixel_size] =  (curBlock & 0xFF);
2004                                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
2005                                 }
2006                         }
2007                 }
2008         }
2009
2010         png_write_image(pPngStruct, row_pointers);
2011         png_write_end(pPngStruct, pPngInfo);
2012
2013         for (y = 0; y < height; y++)
2014                 png_free(pPngStruct, row_pointers[y]);
2015         png_free(pPngStruct, row_pointers);
2016
2017         png_destroy_write_struct(&pPngStruct, &pPngInfo);
2018
2019         fclose(fp);
2020 }
2021
2022 void
2023 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
2024 {
2025         TBM_RETURN_IF_FAIL(path != NULL);
2026         TBM_RETURN_IF_FAIL(w > 0);
2027         TBM_RETURN_IF_FAIL(h > 0);
2028         TBM_RETURN_IF_FAIL(count > 0);
2029
2030         tbm_surface_dump_buf_info *buf_info = NULL;
2031         tbm_surface_h tbm_surface;
2032         tbm_surface_info_s info;
2033         int buffer_size, i;
2034
2035         /* check running */
2036         if (g_dump_info) {
2037                 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
2038                 return;
2039         }
2040
2041         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
2042         TBM_RETURN_IF_FAIL(g_dump_info);
2043
2044         LIST_INITHEAD(&g_dump_info->surface_list);
2045         g_dump_info->count = 0;
2046         g_dump_info->dump_max = count;
2047
2048         /* get buffer size */
2049         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
2050         if (tbm_surface == NULL) {
2051                 TBM_ERR("tbm_surface_create fail\n");
2052                 free(g_dump_info);
2053                 g_dump_info = NULL;
2054                 return;
2055         }
2056
2057         if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
2058                 TBM_ERR("tbm_surface_get_info fail\n");
2059                 tbm_surface_destroy(tbm_surface);
2060                 free(g_dump_info);
2061                 g_dump_info = NULL;
2062                 return;
2063         }
2064         buffer_size = info.size;
2065         tbm_surface_destroy(tbm_surface);
2066
2067         /* create dump lists */
2068         for (i = 0; i < count; i++) {
2069                 tbm_bo bo = NULL;
2070
2071                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
2072                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
2073
2074                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
2075                 if (bo == NULL) {
2076                         TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
2077                         free(buf_info);
2078                         goto fail;
2079                 }
2080
2081                 buf_info->index = i;
2082                 buf_info->bo = bo;
2083                 buf_info->size = buffer_size;
2084
2085                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
2086         }
2087
2088         g_dump_info->path = path;
2089         g_dump_info->link = &g_dump_info->surface_list;
2090
2091         scale_factor = 0.0;
2092
2093         TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
2094
2095         return;
2096
2097 fail:
2098         /* free resources */
2099         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2100                 tbm_surface_dump_buf_info *tmp;
2101
2102                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2103                         tbm_bo_unref(buf_info->bo);
2104                         LIST_DEL(&buf_info->link);
2105                         free(buf_info);
2106                 }
2107         }
2108
2109         TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
2110
2111         free(g_dump_info);
2112         g_dump_info = NULL;
2113
2114         return;
2115 }
2116
2117 void
2118 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
2119 {
2120         if (scale > 0.0) {
2121                 w *= scale;
2122                 h *= scale;
2123         }
2124
2125         tbm_surface_internal_dump_start(path, w, h, count);
2126         scale_factor = scale;
2127 }
2128
2129 void
2130 tbm_surface_internal_dump_end(void)
2131 {
2132         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
2133         tbm_bo_handle bo_handle;
2134
2135         if (!g_dump_info)
2136                 return;
2137
2138         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2139                 free(g_dump_info);
2140                 g_dump_info = NULL;
2141                 return;
2142         }
2143
2144         /* make files */
2145         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2146                 char file[2048];
2147
2148                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2149                 if (bo_handle.ptr == NULL) {
2150                         tbm_bo_unref(buf_info->bo);
2151                         LIST_DEL(&buf_info->link);
2152                         free(buf_info);
2153                         continue;
2154                 }
2155
2156                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2157                 TBM_INFO("Dump File.. %s generated.\n", file);
2158
2159                 if (buf_info->dirty) {
2160                         void *ptr1 = NULL, *ptr2 = NULL;
2161
2162                         switch (buf_info->info.format) {
2163                         case TBM_FORMAT_ARGB8888:
2164                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2165                                                         buf_info->info.planes[0].stride >> 2,
2166                                                         buf_info->info.height,
2167                                                         buf_info->info.planes[0].stride,
2168                                                         TBM_FORMAT_ARGB8888);
2169                                 break;
2170                         case TBM_FORMAT_XRGB8888:
2171                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2172                                                         buf_info->info.planes[0].stride >> 2,
2173                                                         buf_info->info.height,
2174                                                         buf_info->info.planes[0].stride,
2175                                                         TBM_FORMAT_XRGB8888);
2176                                 break;
2177                         case TBM_FORMAT_ABGR8888:
2178                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2179                                                         buf_info->info.planes[0].stride >> 2,
2180                                                         buf_info->info.height,
2181                                                         buf_info->info.planes[0].stride,
2182                                                         TBM_FORMAT_ABGR8888);
2183                                 break;
2184                         case TBM_FORMAT_XBGR8888:
2185                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2186                                                         buf_info->info.planes[0].stride >> 2,
2187                                                         buf_info->info.height,
2188                                                         buf_info->info.planes[0].stride,
2189                                                         TBM_FORMAT_XBGR8888);
2190                                 break;
2191                         case TBM_FORMAT_YVU420:
2192                         case TBM_FORMAT_YUV420:
2193                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2194                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2195                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2196                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2197                                                         ptr1,
2198                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2199                                                         ptr2,
2200                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2201                                 break;
2202                         case TBM_FORMAT_NV12:
2203                         case TBM_FORMAT_NV21:
2204                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2205                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2206                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2207                                                         ptr1,
2208                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2209                                                         NULL, 0);
2210                                 break;
2211                         case TBM_FORMAT_YUYV:
2212                         case TBM_FORMAT_UYVY:
2213                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2214                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2215                                                         NULL, 0, NULL, 0);
2216                                 break;
2217                         default:
2218                                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2219                                 break;
2220                         }
2221                 } else if (buf_info->dirty_shm)
2222                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2223                                                         buf_info->shm_stride >> 2,
2224                                                         buf_info->shm_h,
2225                                                         buf_info->shm_stride, 0);
2226
2227                 tbm_bo_unmap(buf_info->bo);
2228                 tbm_bo_unref(buf_info->bo);
2229                 LIST_DEL(&buf_info->link);
2230                 free(buf_info);
2231         }
2232
2233         free(g_dump_info);
2234         g_dump_info = NULL;
2235
2236         TBM_INFO("Dump End..\n");
2237 }
2238
2239 static pixman_format_code_t
2240 _tbm_surface_internal_pixman_format_get(tbm_format format)
2241 {
2242         switch (format) {
2243         case TBM_FORMAT_ARGB8888:
2244         case TBM_FORMAT_ABGR8888:
2245                 return PIXMAN_a8r8g8b8;
2246         case TBM_FORMAT_XRGB8888:
2247         case TBM_FORMAT_XBGR8888:
2248                 return PIXMAN_x8r8g8b8;
2249         default:
2250                 return 0;
2251         }
2252
2253         return 0;
2254 }
2255
2256 /**
2257  * This function supports only if a buffer has below formats.
2258  * - TBM_FORMAT_ARGB8888
2259  * - TBM_FORMAT_XRGB8888
2260  * - TBM_FORMAT_ABGR8888
2261  * - TBM_FORMAT_XBGR8888
2262  */
2263 static tbm_surface_error_e
2264 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2265                                                                    int format, int src_stride, int src_w, int src_h,
2266                                                                    int dst_stride, int dst_w, int dst_h)
2267 {
2268         pixman_image_t *src_img = NULL, *dst_img = NULL;
2269         pixman_format_code_t pixman_format;
2270         pixman_transform_t t;
2271         struct pixman_f_transform ft;
2272         double scale_x, scale_y;
2273
2274         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2275         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2276
2277         pixman_format = _tbm_surface_internal_pixman_format_get(format);
2278         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2279
2280         /* src */
2281         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2282                                                                            (uint32_t*)src_ptr, src_stride);
2283         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2284
2285         /* dst */
2286         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2287                                                                            (uint32_t*)dst_ptr, dst_stride);
2288         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2289
2290         pixman_f_transform_init_identity(&ft);
2291
2292         scale_x = (double)src_w / dst_w;
2293         scale_y = (double)src_h / dst_h;
2294
2295         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2296         pixman_f_transform_translate(&ft, NULL, 0, 0);
2297         pixman_transform_from_pixman_f_transform(&t, &ft);
2298         pixman_image_set_transform(src_img, &t);
2299
2300         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2301                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
2302
2303         pixman_image_unref(src_img);
2304         pixman_image_unref(dst_img);
2305
2306         return TBM_SURFACE_ERROR_NONE;
2307
2308 cant_convert:
2309         if (src_img)
2310                 pixman_image_unref(src_img);
2311
2312         return TBM_SURFACE_ERROR_INVALID_OPERATION;
2313 }
2314
2315 #define MAX_BOS         4       // This value is came from bos[4] in struct _tbm_surface
2316 #define KEY_LEN         5       // "_XXXX"
2317 #define KEYS_LEN        KEY_LEN * MAX_BOS
2318
2319 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2320 {
2321         char *keys, temp_key[KEY_LEN + 1];
2322         struct _tbm_surface *surf;
2323         int i, num_bos;
2324         tbm_bo bo;
2325
2326         _tbm_surface_mutex_lock();
2327
2328         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2329
2330         surf = (struct _tbm_surface *)surface;
2331
2332         num_bos = surf->num_bos;
2333         if (num_bos > MAX_BOS)
2334                 num_bos = MAX_BOS;
2335
2336         keys = calloc(KEYS_LEN + 1, sizeof(char));
2337         if (!keys) {
2338                 TBM_ERR("Failed to alloc memory");
2339                 _tbm_surface_mutex_unlock();
2340                 return NULL;
2341         }
2342
2343         for (i = 0; i < num_bos; i++) {
2344                 memset(temp_key, 0x00, KEY_LEN + 1);
2345                 bo = surf->bos[i];
2346                 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2347                 strncat(keys, temp_key, KEY_LEN + 1);
2348         }
2349
2350         _tbm_surface_mutex_unlock();
2351
2352         return keys;
2353 }
2354
2355 static void _tbm_surface_internal_put_keys(char *keys)
2356 {
2357         if (keys)
2358                 free(keys);
2359 }
2360
2361 void
2362 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2363 {
2364         TBM_RETURN_IF_FAIL(surface != NULL);
2365         TBM_RETURN_IF_FAIL(type != NULL);
2366
2367         tbm_surface_dump_buf_info *buf_info;
2368         struct list_head *next_link;
2369         tbm_surface_info_s info;
2370         tbm_bo_handle bo_handle;
2371         const char *postfix;
2372         const char *format = NULL;
2373         char *keys;
2374         int ret;
2375
2376         if (!g_dump_info)
2377                 return;
2378
2379         next_link = g_dump_info->link->next;
2380         TBM_RETURN_IF_FAIL(next_link != NULL);
2381
2382         if (next_link == &g_dump_info->surface_list) {
2383                 next_link = next_link->next;
2384                 TBM_RETURN_IF_FAIL(next_link != NULL);
2385         }
2386
2387         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2388         TBM_RETURN_IF_FAIL(buf_info != NULL);
2389
2390         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2391         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2392
2393         if (scale_factor > 0.0) {
2394                 const int bpp = 4;
2395
2396                 if ((info.format != TBM_FORMAT_ARGB8888) && (info.format != TBM_FORMAT_XRGB8888) &&
2397                     (info.format != TBM_FORMAT_ABGR8888) && (info.format != TBM_FORMAT_XBGR8888)) {
2398                         TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2399                                           _tbm_surface_internal_format_to_str(info.format));
2400                         tbm_surface_unmap(surface);
2401                         return;
2402                 }
2403
2404                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2405
2406                 buf_info->info.width = info.width * scale_factor;
2407                 buf_info->info.height = info.height * scale_factor;
2408                 buf_info->info.format = info.format;
2409                 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2410                 if (!buf_info->info.bpp) {
2411                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2412                         tbm_surface_unmap(surface);
2413                         return;
2414                 }
2415                 buf_info->info.num_planes = 1;
2416                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2417                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2418
2419                 if (buf_info->info.size > buf_info->size) {
2420                         TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2421                                         buf_info->info.size, buf_info->size);
2422                         tbm_surface_unmap(surface);
2423                         return;
2424                 }
2425         } else {
2426                 if (info.size > buf_info->size) {
2427                         TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2428                                         info.size, buf_info->size);
2429                         tbm_surface_unmap(surface);
2430                         return;
2431                 }
2432
2433                 /* make the file information */
2434                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2435         }
2436
2437         if ((info.format == TBM_FORMAT_ARGB8888) || (info.format == TBM_FORMAT_XRGB8888) ||
2438                 (info.format == TBM_FORMAT_ABGR8888) || (info.format == TBM_FORMAT_XBGR8888)) {
2439                 postfix = dump_postfix[0];
2440                 format = _tbm_surface_internal_format_to_str(info.format);
2441         } else
2442                 postfix = dump_postfix[1];
2443
2444         keys = _tbm_surface_internal_get_keys(surface);
2445         if (!keys) {
2446                 TBM_ERR("fail to get keys");
2447                 tbm_surface_unmap(surface);
2448                 return;
2449         }
2450
2451         /* dump */
2452         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2453         if (!bo_handle.ptr) {
2454                 TBM_ERR("fail to map bo");
2455                 _tbm_surface_internal_put_keys(keys);
2456                 tbm_surface_unmap(surface);
2457                 return;
2458         }
2459         memset(bo_handle.ptr, 0x00, buf_info->size);
2460
2461         switch (info.format) {
2462         case TBM_FORMAT_ARGB8888:
2463         case TBM_FORMAT_XRGB8888:
2464         case TBM_FORMAT_ABGR8888:
2465         case TBM_FORMAT_XBGR8888:
2466                 snprintf(buf_info->name, sizeof(buf_info->name),
2467                                 "%10.3f_%03d%s_%p_%s-%s.%s",
2468                                  _tbm_surface_internal_get_time(),
2469                                  g_dump_info->count++, keys, surface, format, type, postfix);
2470
2471                 if (scale_factor > 0.0) {
2472                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2473                                                                                                          bo_handle.ptr,
2474                                                                                                          buf_info->info.format,
2475                                                                                                          info.planes[0].stride,
2476                                                                                                          info.width, info.height,
2477                                                                                                          buf_info->info.planes[0].stride,
2478                                                                                                          buf_info->info.width,
2479                                                                                                          buf_info->info.height);
2480                         if (ret != TBM_SURFACE_ERROR_NONE) {
2481                                 TBM_ERR("fail to scale buffer");
2482                                 tbm_bo_unmap(buf_info->bo);
2483                                 _tbm_surface_internal_put_keys(keys);
2484                                 tbm_surface_unmap(surface);
2485                                 return;
2486                         }
2487                 } else
2488                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2489                 break;
2490         case TBM_FORMAT_YVU420:
2491         case TBM_FORMAT_YUV420:
2492                 snprintf(buf_info->name, sizeof(buf_info->name),
2493                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2494                                  _tbm_surface_internal_get_time(),
2495                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2496                                 info.height, FOURCC_STR(info.format), postfix);
2497                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2498                 bo_handle.ptr += info.planes[0].stride * info.height;
2499                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2500                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2501                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2502                 break;
2503         case TBM_FORMAT_NV12:
2504         case TBM_FORMAT_NV21:
2505                 snprintf(buf_info->name, sizeof(buf_info->name),
2506                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2507                                  _tbm_surface_internal_get_time(),
2508                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2509                                 info.height, FOURCC_STR(info.format), postfix);
2510                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2511                 bo_handle.ptr += info.planes[0].stride * info.height;
2512                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2513                 break;
2514         case TBM_FORMAT_YUYV:
2515         case TBM_FORMAT_UYVY:
2516                 snprintf(buf_info->name, sizeof(buf_info->name),
2517                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2518                                  _tbm_surface_internal_get_time(),
2519                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2520                                 info.height, FOURCC_STR(info.format), postfix);
2521                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2522                 break;
2523         default:
2524                 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2525                 tbm_bo_unmap(buf_info->bo);
2526                 _tbm_surface_internal_put_keys(keys);
2527                 tbm_surface_unmap(surface);
2528                 return;
2529         }
2530
2531         tbm_bo_unmap(buf_info->bo);
2532
2533         _tbm_surface_internal_put_keys(keys);
2534
2535         tbm_surface_unmap(surface);
2536
2537         buf_info->dirty = 1;
2538         buf_info->dirty_shm = 0;
2539
2540         if (g_dump_info->count == 1000)
2541                 g_dump_info->count = 0;
2542
2543         g_dump_info->link = next_link;
2544
2545         TBM_INFO("Dump %s \n", buf_info->name);
2546 }
2547
2548 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2549                                                 const char *type)
2550 {
2551         TBM_RETURN_IF_FAIL(ptr != NULL);
2552         TBM_RETURN_IF_FAIL(w > 0);
2553         TBM_RETURN_IF_FAIL(h > 0);
2554         TBM_RETURN_IF_FAIL(stride > 0);
2555         TBM_RETURN_IF_FAIL(type != NULL);
2556
2557         tbm_surface_dump_buf_info *buf_info;
2558         struct list_head *next_link;
2559         tbm_bo_handle bo_handle;
2560         int ret, size, dw = 0, dh = 0, dstride = 0;
2561
2562         if (!g_dump_info)
2563                 return;
2564
2565         next_link = g_dump_info->link->next;
2566         TBM_RETURN_IF_FAIL(next_link != NULL);
2567
2568         if (next_link == &g_dump_info->surface_list) {
2569                 next_link = next_link->next;
2570                 TBM_RETURN_IF_FAIL(next_link != NULL);
2571         }
2572
2573         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2574         TBM_RETURN_IF_FAIL(buf_info != NULL);
2575
2576         if (scale_factor > 0.0) {
2577                 const int bpp = 4;
2578
2579                 dw = w * scale_factor;
2580                 dh = h * scale_factor;
2581                 dstride = dw * bpp;
2582                 size = dstride * dh;
2583         } else
2584                 size = stride * h;
2585
2586         if (size > buf_info->size) {
2587                 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2588                                 size, buf_info->size);
2589                 return;
2590         }
2591
2592         /* dump */
2593         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2594         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2595
2596         memset(bo_handle.ptr, 0x00, buf_info->size);
2597         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2598
2599         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2600                          _tbm_surface_internal_get_time(),
2601                          g_dump_info->count++, type, dump_postfix[0]);
2602         if (scale_factor > 0.0) {
2603                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2604                                                                                                  TBM_FORMAT_ARGB8888, stride,
2605                                                                                                  w, h, dstride, dw, dh);
2606                 if (ret != TBM_SURFACE_ERROR_NONE) {
2607                         TBM_ERR("fail to scale buffer");
2608                         tbm_bo_unmap(buf_info->bo);
2609                         return;
2610                 }
2611                 buf_info->shm_stride = dstride;
2612                 buf_info->shm_h = dh;
2613         } else {
2614                 memcpy(bo_handle.ptr, ptr, size);
2615                 buf_info->shm_stride = stride;
2616                 buf_info->shm_h = h;
2617         }
2618
2619         tbm_bo_unmap(buf_info->bo);
2620
2621         buf_info->dirty = 0;
2622         buf_info->dirty_shm = 1;
2623
2624         if (g_dump_info->count == 1000)
2625                 g_dump_info->count = 0;
2626
2627         g_dump_info->link = next_link;
2628
2629         TBM_INFO("Dump %s \n", buf_info->name);
2630 }
2631
2632 int
2633 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2634 {
2635         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2636         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2637         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2638
2639         tbm_surface_info_s info;
2640         const char *postfix;
2641         int ret;
2642         char file[1024];
2643
2644         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2645         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2646
2647         if ((info.format == TBM_FORMAT_ARGB8888) || (info.format == TBM_FORMAT_XRGB8888) ||
2648             (info.format == TBM_FORMAT_ABGR8888) || (info.format == TBM_FORMAT_XBGR8888))
2649                 postfix = dump_postfix[0];
2650         else
2651                 postfix = dump_postfix[1];
2652
2653         if (strcmp(postfix, type)) {
2654                 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2655                 tbm_surface_unmap(surface);
2656                 return 0;
2657         }
2658
2659         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2660
2661         if (!access(file, 0)) {
2662                 TBM_ERR("can't capture  buffer, exist file %s", file);
2663                 tbm_surface_unmap(surface);
2664                 return 0;
2665         }
2666
2667         switch (info.format) {
2668         case TBM_FORMAT_ARGB8888:
2669                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2670                                                         info.width,
2671                                                         info.height,
2672                                                         info.planes[0].stride,
2673                                                         TBM_FORMAT_ARGB8888);
2674                 break;
2675         case TBM_FORMAT_XRGB8888:
2676                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2677                                                         info.width,
2678                                                         info.height,
2679                                                         info.planes[0].stride,
2680                                                         TBM_FORMAT_XRGB8888);
2681                 break;
2682         case TBM_FORMAT_ABGR8888:
2683                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2684                                                         info.width,
2685                                                         info.height,
2686                                                         info.planes[0].stride,
2687                                                         TBM_FORMAT_ABGR8888);
2688                 break;
2689         case TBM_FORMAT_XBGR8888:
2690                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2691                                                         info.width,
2692                                                         info.height,
2693                                                         info.planes[0].stride,
2694                                                         TBM_FORMAT_XBGR8888);
2695                 break;
2696         case TBM_FORMAT_YVU420:
2697         case TBM_FORMAT_YUV420:
2698                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2699                                 info.planes[0].stride * info.height,
2700                                 info.planes[1].ptr,
2701                                 info.planes[1].stride * (info.height >> 1),
2702                                 info.planes[2].ptr,
2703                                 info.planes[2].stride * (info.height >> 1));
2704                 break;
2705         case TBM_FORMAT_NV12:
2706         case TBM_FORMAT_NV21:
2707                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2708                                         info.planes[0].stride * info.height,
2709                                         info.planes[1].ptr,
2710                                         info.planes[1].stride * (info.height >> 1),
2711                                         NULL, 0);
2712                 break;
2713         case TBM_FORMAT_YUYV:
2714         case TBM_FORMAT_UYVY:
2715                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2716                                         info.planes[0].stride * info.height,
2717                                         NULL, 0, NULL, 0);
2718                 break;
2719         default:
2720                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2721                 tbm_surface_unmap(surface);
2722                 return 0;
2723         }
2724
2725         tbm_surface_unmap(surface);
2726
2727         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2728
2729         return 1;
2730 }
2731
2732 int
2733 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2734                                                 const char *path, const char *name, const char *type)
2735 {
2736         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2737         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2738         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2739         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2740         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2741         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2742
2743         char file[1024];
2744
2745         if (strcmp(dump_postfix[0], type)) {
2746                 TBM_ERR("Not supported type:%s'", type);
2747                 return 0;
2748         }
2749
2750         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2751
2752         if (!access(file, 0)) {
2753                 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2754                 return 0;
2755         }
2756
2757         _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2758
2759         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2760
2761         return 1;
2762 }
2763
2764 int
2765 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2766 {
2767         struct _tbm_surface *surf;
2768
2769         _tbm_surface_mutex_lock();
2770         _tbm_set_last_result(TBM_ERROR_NONE);
2771
2772         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2773         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2774         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2775
2776         surf = (struct _tbm_surface *)surface;
2777
2778         surf->damage.x = x;
2779         surf->damage.y = y;
2780         surf->damage.width = width;
2781         surf->damage.height = height;
2782
2783         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2784                                                         surface, x, y, width, height);
2785
2786         _tbm_surface_mutex_unlock();
2787
2788         return 1;
2789 }
2790
2791 int
2792 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2793 {
2794         struct _tbm_surface *surf;
2795
2796         _tbm_surface_mutex_lock();
2797         _tbm_set_last_result(TBM_ERROR_NONE);
2798
2799         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2800
2801         surf = (struct _tbm_surface *)surface;
2802
2803         if (x) *x = surf->damage.x;
2804         if (y) *y = surf->damage.y;
2805         if (width) *width = surf->damage.width;
2806         if (height) *height = surf->damage.height;
2807
2808         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2809                                                         surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2810
2811         _tbm_surface_mutex_unlock();
2812
2813         return 1;
2814 }
2815
2816 int
2817 tbm_surface_internal_add_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2818 {
2819         struct _tbm_surface *surf;
2820         tbm_surface_destroy_func_info *func_info = NULL;
2821
2822         _tbm_surface_mutex_lock();
2823         _tbm_set_last_result(TBM_ERROR_NONE);
2824
2825         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2826         TBM_SURFACE_RETURN_VAL_IF_FAIL(func != NULL, 0);
2827
2828         surf = (struct _tbm_surface *)surface;
2829         LIST_FOR_EACH_ENTRY(func_info, &surf->destroy_funcs, item_link) {
2830                 if (func_info->destroy_func == func && func_info->user_data == user_data) {
2831                         TBM_ERR("can't add twice");
2832                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
2833                         _tbm_surface_mutex_unlock();
2834                         return 0;
2835                 }
2836         }
2837
2838         func_info = calloc(1, sizeof(tbm_surface_destroy_func_info));
2839         if (func_info == NULL) {
2840                 TBM_ERR("alloc failed");
2841                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2842                 _tbm_surface_mutex_unlock();
2843                 return 0;
2844         }
2845
2846         func_info->destroy_func = func;
2847         func_info->user_data = user_data;
2848
2849         LIST_ADDTAIL(&func_info->item_link, &surf->destroy_funcs);
2850
2851         _tbm_surface_mutex_unlock();
2852
2853         return 1;
2854 }
2855
2856 void
2857 tbm_surface_internal_remove_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2858 {
2859         struct _tbm_surface *surf;
2860         tbm_surface_destroy_func_info *func_info = NULL, *next = NULL;
2861
2862         _tbm_surface_mutex_lock();
2863         _tbm_set_last_result(TBM_ERROR_NONE);
2864
2865         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
2866         TBM_SURFACE_RETURN_IF_FAIL(func != NULL);
2867
2868         surf = (struct _tbm_surface *)surface;
2869         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &surf->destroy_funcs, item_link) {
2870                 if (func_info->destroy_func != func || func_info->user_data != user_data)
2871                         continue;
2872
2873                 LIST_DEL(&func_info->item_link);
2874                 free(func_info);
2875
2876                 _tbm_surface_mutex_unlock();
2877
2878                 return;
2879         }
2880
2881         _tbm_surface_mutex_unlock();
2882 }
2883
2884 tbm_surface_buffer_data *
2885 tbm_surface_internal_export(tbm_surface_h surface, tbm_error_e *error)
2886 {
2887         tbm_surface_buffer_data *buffer_data = NULL;
2888         struct _tbm_bufmgr *bufmgr;
2889
2890         _tbm_surface_mutex_lock();
2891
2892         bufmgr = g_surface_bufmgr;
2893         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr != NULL, NULL, error, TBM_ERROR_INVALID_OPERATION);
2894
2895         // this function supports when the module suppport surface_data.
2896         TBM_SURFACE_RETURN_VAL_SET_ERR_NO_LOG_IF_FAIL(tbm_bufmgr_internal_support_capabilites(bufmgr, TBM_BUFMGR_CAPABILITY_SHARE_SURFACE), NULL, error, TBM_ERROR_NOT_SUPPORTED);
2897
2898         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL, error, TBM_ERROR_INVALID_PARAMETER);
2899
2900         // export a surface
2901         buffer_data = tbm_surface_data_export(surface->surface_data, error);
2902         TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(buffer_data != NULL, NULL, *error);
2903
2904         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) buffer_data(%p)", surface, buffer_data);
2905
2906         _tbm_set_last_result(TBM_ERROR_NONE);
2907         _tbm_surface_mutex_unlock();
2908
2909         return buffer_data;
2910 }
2911
2912 tbm_surface_h
2913 tbm_surface_internal_import(tbm_surface_info_s *surface_info, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)
2914 {
2915         struct _tbm_surface *surf;
2916         struct _tbm_bufmgr *bufmgr;
2917
2918         _tbm_surface_mutex_lock();
2919
2920         bufmgr = g_surface_bufmgr;
2921         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr != NULL, NULL, error, TBM_ERROR_INVALID_OPERATION);
2922
2923         // this function supports when the module suppport surface_data.
2924         TBM_SURFACE_RETURN_VAL_SET_ERR_NO_LOG_IF_FAIL(tbm_bufmgr_internal_support_capabilites(bufmgr, TBM_BUFMGR_CAPABILITY_SHARE_SURFACE), NULL, error, TBM_ERROR_NOT_SUPPORTED);
2925
2926         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info != NULL, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2927         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info->width > 0, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2928         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info->height > 0, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2929         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(buffer_data != NULL, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2930
2931         // import a surface
2932         surf = _tbm_surface_internal_import_surface(bufmgr,
2933                                                                                                         (int)surface_info->width,
2934                                                                                                         (int)surface_info->height,
2935                                                                                                         (int)surface_info->format,
2936                                                                                                         buffer_data,
2937                                                                                                         error);
2938         TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(surf != NULL, NULL, *error);
2939
2940         LIST_INITHEAD(&surf->user_data_list);
2941         LIST_INITHEAD(&surf->debug_data_list);
2942         LIST_INITHEAD(&surf->destroy_funcs);
2943
2944         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
2945
2946         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)", surf);
2947
2948         _tbm_set_last_result(TBM_ERROR_NONE);
2949         _tbm_surface_mutex_unlock();
2950
2951         return (tbm_surface_h)surf;
2952 }
2953
2954 /*LCOV_EXCL_STOP*/