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