tbm_bo: free hal_tbm_bo when it is allocated by tbm_bo_alloc
[platform/core/uifw/libtbm.git] / src / tbm_bo.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2012 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 #include "tbm_bufmgr.h"
34 #include "tbm_bufmgr_int.h"
35 #include "list.h"
36
37 #define TBM_BO_MAGIC 0xBF011234
38
39 /* check condition */
40 #define TBM_BO_RETURN_IF_FAIL(cond) {\
41         if (!(cond)) {\
42                 TBM_ERR("'%s' failed.\n", #cond);\
43                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
44                 _tbm_bufmgr_mutex_unlock();\
45                 return;\
46         } \
47 }
48
49 #define TBM_BO_RETURN_VAL_IF_FAIL(cond, val) {\
50         if (!(cond)) {\
51                 TBM_ERR("'%s' failed.\n", #cond);\
52                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
53                 _tbm_bufmgr_mutex_unlock();\
54                 return val;\
55         } \
56 }
57
58 static char *
59 _tbm_flag_to_str(int f)
60 {
61         static char str[255];
62
63         if (f == TBM_BO_DEFAULT)
64                  snprintf(str, 255, "DEFAULT");
65         else {
66                 int c = 0;
67
68                 if (f & TBM_BO_SCANOUT)
69                         c += snprintf(&str[c], 255-c, "SCANOUT");
70
71                 if (f & TBM_BO_NONCACHABLE) {
72                         if (c >= 0 && c < 255)
73                                 c += snprintf(&str[c], 255-c, ", ");
74
75                         if (c >= 0 && c < 255)
76                                 c += snprintf(&str[c], 255-c, "NONCACHABLE,");
77                 }
78
79                 if (f & TBM_BO_WC) {
80                         if (c >= 0 && c < 255)
81                                 c += snprintf(&str[c], 255-c, ", ");
82
83                         if (c >= 0 && c < 255)
84                                 c += snprintf(&str[c], 255-c, "WC");
85                 }
86         }
87
88         return str;
89 }
90
91 static void
92 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
93 {
94         static int last_chk_bo_cnt = 0;
95
96         if ((bufmgr->bo_cnt >= 500) && ((bufmgr->bo_cnt % 20) == 0) &&
97                 (bufmgr->bo_cnt > last_chk_bo_cnt)) {
98                 TBM_DBG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
99                 tbm_bufmgr_debug_show(bufmgr);
100                 last_chk_bo_cnt = bufmgr->bo_cnt;
101         }
102 }
103 /* LCOV_EXCL_STOP */
104
105 tbm_user_data *
106 user_data_lookup(struct list_head *user_data_list, unsigned long key)
107 {
108         tbm_user_data *old_data = NULL;
109
110         if (LIST_IS_EMPTY(user_data_list))
111                 return NULL;
112
113         LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
114                 if (old_data->key == key)
115                         return old_data;
116         }
117
118         return NULL;
119 }
120
121 tbm_user_data *
122 user_data_create(unsigned long key, tbm_data_free data_free_func)
123 {
124         tbm_user_data *user_data;
125
126         user_data = calloc(1, sizeof(tbm_user_data));
127         if (!user_data) {
128                 /* LCOV_EXCL_START */
129                 TBM_ERR("fail to allocate an user_date\n");
130                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
131                 return NULL;
132                 /* LCOV_EXCL_STOP */
133         }
134
135         user_data->key = key;
136         user_data->free_func = data_free_func;
137
138         return user_data;
139 }
140
141 void
142 user_data_delete(tbm_user_data *user_data)
143 {
144         if (user_data->data && user_data->free_func)
145                 user_data->free_func(user_data->data);
146
147         LIST_DEL(&user_data->item_link);
148
149         free(user_data);
150 }
151
152 static int
153 _bo_lock(tbm_bo bo, int device, int opt)
154 {
155         int ret = 1;
156         tbm_error_e error;
157
158         if (bo->bufmgr->use_hal_tbm) {
159                 error = (tbm_error_e)hal_tbm_bo_lock((hal_tbm_bo *)bo->bo_data, device, opt);
160                 if (error == TBM_ERROR_NOT_SUPPORTED) {
161                         _tbm_set_last_result(TBM_ERROR_NONE);
162                 } else {
163                         if (error != TBM_ERROR_NONE) {
164                                 TBM_WRN("fail to lock");
165                                 _tbm_set_last_result(error);
166                                 ret = 0;
167                         }
168                 }
169         } else if (bo->bufmgr->backend_module_data) {
170                 if (bo->bufmgr->bo_func->bo_lock) {
171                         error = bo->bufmgr->bo_func->bo_lock(bo->bo_data, device, opt);
172                         if (error != TBM_ERROR_NONE) {
173                                 TBM_WRN("fail to lock");
174                                 _tbm_set_last_result(error);
175                                 ret = 0;
176                         }
177                 }
178         } else {
179                 if (bo->bufmgr->backend->bo_lock) {
180                         ret = bo->bufmgr->backend->bo_lock(bo, device, opt);
181                         if (!ret)
182                                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
183                 }
184         }
185
186         return ret;
187 }
188
189 static void
190 _bo_unlock(tbm_bo bo)
191 {
192         tbm_error_e error;
193
194         if (bo->bufmgr->use_hal_tbm) {
195                 error = (tbm_error_e)hal_tbm_bo_unlock((hal_tbm_bo *)bo->bo_data);
196                 if (error == TBM_ERROR_NOT_SUPPORTED) {
197                         _tbm_set_last_result(TBM_ERROR_NONE);
198                 } else {
199                         if (error != TBM_ERROR_NONE) {
200                                 TBM_WRN("fail to lock");
201                                 _tbm_set_last_result(error);
202                         }
203                 }
204         } else if (bo->bufmgr->backend_module_data) {
205                 if (bo->bufmgr->bo_func->bo_unlock) {
206                         error = bo->bufmgr->bo_func->bo_unlock(bo->bo_data);
207                         if (error != TBM_ERROR_NONE) {
208                                 TBM_WRN("fail to unlock");
209                                 _tbm_set_last_result(error);
210                         }
211                 }
212         } else {
213                 if (bo->bufmgr->backend->bo_unlock)
214                         bo->bufmgr->backend->bo_unlock(bo);
215         }
216 }
217
218 static int
219 _tbm_bo_lock(tbm_bo bo, int device, int opt)
220 {
221         int old, ret;
222
223         if (!bo)
224                 return 0;
225
226         /* do not try to lock the bo */
227         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
228                 return 1;
229
230         if (bo->lock_cnt < 0) {
231                 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
232                         bo, bo->lock_cnt);
233                 return 0;
234         }
235
236         old = bo->lock_cnt;
237
238         switch (bo->bufmgr->bo_lock_type) {
239         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
240                 if (bo->lock_cnt == 0) {
241                         _tbm_bufmgr_mutex_unlock();
242                         ret = _bo_lock(bo, device, opt);
243                         _tbm_bufmgr_mutex_lock();
244                         if (ret)
245                                 bo->lock_cnt++;
246                 } else
247                         ret = 1;
248                 break;
249         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
250                 _tbm_bufmgr_mutex_unlock();
251                 ret = _bo_lock(bo, device, opt);
252                 _tbm_bufmgr_mutex_lock();
253                 if (ret)
254                         bo->lock_cnt++;
255                 break;
256         default:
257                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
258                                 bo, bo->bufmgr->bo_lock_type);
259                 ret = 0;
260                 break;
261         }
262
263         TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
264
265         return ret;
266 }
267
268 static void
269 _tbm_bo_unlock(tbm_bo bo)
270 {
271         int old;
272
273         /* do not try to unlock the bo */
274         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
275                 return;
276
277         old = bo->lock_cnt;
278
279         switch (bo->bufmgr->bo_lock_type) {
280         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
281                 if (bo->lock_cnt > 0) {
282                         bo->lock_cnt--;
283                         if (bo->lock_cnt == 0)
284                                 _bo_unlock(bo);
285                 }
286                 break;
287         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
288                 if (bo->lock_cnt > 0) {
289                         bo->lock_cnt--;
290                         _bo_unlock(bo);
291                 }
292                 break;
293         default:
294                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
295                                 bo, bo->bufmgr->bo_lock_type);
296                 break;
297         }
298
299         if (bo->lock_cnt < 0)
300                 bo->lock_cnt = 0;
301
302         TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
303 }
304
305 static int
306 _tbm_bo_magic_check(tbm_bo bo)
307 {
308         if (bo->magic != TBM_BO_MAGIC)
309                 return 0;
310
311         return 1;
312 }
313
314 static int
315 _tbm_bo_is_valid(tbm_bo bo)
316 {
317         if (!bo) {
318                 TBM_ERR("error: bo is NULL.\n");
319                 return 0;
320         }
321
322         if (!_tbm_bo_magic_check(bo)) {
323                 TBM_ERR("error: No valid bo(%p).\n", bo);
324                 return 0;
325         }
326
327         return 1;
328 }
329
330 static void
331 _tbm_bo_init(tbm_bufmgr bufmgr, tbm_bo bo, int flags)
332 {
333         bo->bufmgr = bufmgr;
334         bo->flags = flags;
335         bo->magic = TBM_BO_MAGIC;
336         bo->ref_cnt = 1;
337
338         LIST_INITHEAD(&bo->user_data_list);
339
340         bufmgr->bo_cnt++;
341         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
342 }
343
344 static void
345 _tbm_bo_deinit(tbm_bo bo)
346 {
347         bo->magic = 0;
348
349         bo->bufmgr->bo_cnt--;
350         LIST_DEL(&bo->item_link);
351 }
352
353 tbm_bo
354 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
355 {
356         tbm_bo bo;
357         void *bo_priv;
358         tbm_backend_bo_data *bo_data;
359         tbm_error_e error;
360
361         _tbm_bufmgr_mutex_lock();
362         _tbm_set_last_result(TBM_ERROR_NONE);
363
364         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
365         TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
366
367         bo = calloc(1, sizeof(struct _tbm_bo));
368         if (!bo) {
369                 /* LCOV_EXCL_START */
370                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
371                 _tbm_bufmgr_mutex_unlock();
372                 return NULL;
373                 /* LCOV_EXCL_STOP */
374         }
375
376         _tbm_util_check_bo_cnt(bufmgr);
377
378         if (bufmgr->use_hal_tbm) {
379                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_alloc_bo(bufmgr->hal_bufmgr, size, flags, (hal_tbm_error *)&error);
380                 /* LCOV_EXCL_START */
381                 if (!bo_data) {
382                         _tbm_set_last_result(error);
383                         goto alloc_fail;
384                 }
385                 /* LCOV_EXCL_STOP */
386                 bo->bo_data = bo_data;
387                 bo->allocated_hal_tbm_bo = 1;
388         } else if (bufmgr->backend_module_data) {
389                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo(bufmgr->bufmgr_data, (unsigned int)size, flags, &error);
390                 if (!bo_data) {
391                         /* LCOV_EXCL_START */
392                         _tbm_set_last_result(error);
393                         goto alloc_fail;
394                         /* LCOV_EXCL_STOP */
395                 }
396                 bo->bo_data = bo_data;
397         } else {
398                 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
399                 if (!bo_priv) {
400                         /* LCOV_EXCL_START */
401                         
402                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
403                         goto alloc_fail;
404                         /* LCOV_EXCL_STOP */
405                 }
406                 bo->priv = bo_priv;
407         }
408
409         _tbm_bo_init(bufmgr, bo, flags);
410
411         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
412                         _tbm_flag_to_str(bo->flags));
413
414         _tbm_bufmgr_mutex_unlock();
415
416         return bo;
417
418 alloc_fail:
419         TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, _tbm_flag_to_str(flags));
420         free(bo);
421         _tbm_bufmgr_mutex_unlock();
422         return NULL;
423 }
424
425 /* LCOV_EXCL_START */
426 tbm_bo
427 tbm_bo_alloc_with_format(tbm_bufmgr bufmgr, int format, int bo_idx, int width,
428                                                 int height, int bpp, tbm_bo_memory_type flags, tbm_error_e *error)
429 {
430         tbm_bo bo;
431         tbm_backend_bo_data *bo_data;
432
433         _tbm_bufmgr_mutex_lock();
434         _tbm_set_last_result(TBM_ERROR_NONE);
435
436         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
437
438         bo = calloc(1, sizeof(struct _tbm_bo));
439         if (!bo) {
440                 TBM_ERR("error: fail to tbm_bo_alloc_with_format fmt(%s) idx(%d) w(%d) h(%d) mem_types(%s)\n",
441                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
442                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
443                 goto calloc_fail;
444         }
445
446         _tbm_util_check_bo_cnt(bufmgr);
447
448         /* LCOV_EXCL_START */
449         if (!bufmgr->use_hal_tbm) {
450                 if (!bufmgr->backend_module_data || !bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
451                         
452                         TBM_ERR("error: not supported tbm_bo_alloc_with_format\n");
453                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
454                         goto bo_alloc_fail;
455                 }
456         }
457         /* LCOV_EXCL_STOP */
458
459         if (bufmgr->use_hal_tbm) {
460                 hal_tbm_error ret;
461                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_alloc_bo_with_format(bufmgr->hal_bufmgr,
462                                                                 format, bo_idx, width, height, bpp, (hal_tbm_bo_memory_type)flags, &ret);
463                 if (error)
464                         *error = (tbm_error_e)ret;
465                 if (ret != HAL_TBM_ERROR_NONE) {
466                         if (ret != HAL_TBM_ERROR_NOT_SUPPORTED) {
467                                 TBM_ERR("error: fail to tbm_bo_alloc_with_format\n");
468                                 if (error)
469                                         _tbm_set_last_result(*error);
470                         }
471                         goto bo_alloc_fail;
472                 }
473         } else {
474                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format(bufmgr->bufmgr_data, format, bo_idx,
475                                                                                                                                 width, height, flags, error);
476                 if (!bo_data) {
477                         TBM_ERR("error: fail to tbm_bo_alloc_with_format fmt(%s) idx(%d) w(%d) h(%d) mem_types(%s)\n",
478                                         FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
479                         if (error)
480                                 _tbm_set_last_result(*error);
481                         goto bo_alloc_fail;
482                 }
483         }
484
485         bo->bo_data = bo_data;
486         _tbm_bo_init(bufmgr, bo, flags);
487
488         _tbm_bufmgr_mutex_unlock();
489
490         return bo;
491
492 bo_alloc_fail:
493         free(bo);
494 calloc_fail:
495         _tbm_bufmgr_mutex_unlock();
496         return NULL;
497 }
498
499 tbm_bo
500 tbm_bo_alloc_with_tiled_format(tbm_bufmgr bufmgr, int width, int height, int bpp, int format,
501                                                         tbm_bo_memory_type flags, int bo_idx, tbm_error_e *error)
502 {
503         tbm_bo bo;
504         tbm_backend_bo_data *bo_data;
505
506         _tbm_bufmgr_mutex_lock();
507         _tbm_set_last_result(TBM_ERROR_NONE);
508
509         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
510
511         bo = calloc(1, sizeof(struct _tbm_bo));
512         if (!bo) {
513                 TBM_ERR("error: fail to tbm_bo_alloc_with_tiled_format fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
514                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
515                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
516                 _tbm_bufmgr_mutex_unlock();
517                 return NULL;
518         }
519
520         _tbm_util_check_bo_cnt(bufmgr);
521
522         if (!bufmgr->use_hal_tbm) {
523                 if (!bufmgr->backend_module_data || !bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format) {
524                         TBM_ERR("error: not supported tbm_bo_alloc_with_tiled_format\n");
525                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
526                         goto bo_alloc_fail;
527                 }
528         }
529
530         if (bufmgr->use_hal_tbm) {
531                 hal_tbm_error ret;
532                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_alloc_bo_with_format(bufmgr->hal_bufmgr,
533                                                                 width, height, bpp, format, (hal_tbm_bo_memory_type)flags, bo_idx, &ret);
534                 if (error)
535                         *error = (tbm_error_e)ret;
536                 if (ret != HAL_TBM_ERROR_NONE) {
537                         if (ret != HAL_TBM_ERROR_NOT_SUPPORTED) {
538                                 TBM_ERR("error: fail to tbm_bo_alloc_with_tiled_format fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
539                                         FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
540                                 if (error)
541                                         _tbm_set_last_result(*error);
542                         }
543                         goto bo_alloc_fail;
544                 }
545         } else {
546                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format(bufmgr->bufmgr_data, width, height,
547                                                                                                                                         bpp, format, flags, bo_idx, error);
548                 if (!bo_data) {
549                         TBM_ERR("error: fail to tbm_bo_alloc_with_tiled_format fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
550                                         FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
551                         if (error)
552                                 _tbm_set_last_result(*error);
553                         goto bo_alloc_fail;
554                 }
555         }
556
557         bo->bo_data = bo_data;
558         _tbm_bo_init(bufmgr, bo, flags);
559
560         _tbm_bufmgr_mutex_unlock();
561
562         return bo;
563
564 bo_alloc_fail:
565         free(bo);
566         _tbm_bufmgr_mutex_unlock();
567         return NULL;
568 }
569
570 tbm_bo
571 tbm_bo_alloc_with_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, int bo_idx)
572 {
573         tbm_bo bo;
574         void *bo_priv;
575
576         _tbm_bufmgr_mutex_lock();
577         _tbm_set_last_result(TBM_ERROR_NONE);
578
579         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
580
581         bo = calloc(1, sizeof(struct _tbm_bo));
582         if (!bo) {
583                 TBM_ERR("error: fail to tbm_bo_alloc_with_surface fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
584                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
585                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
586                 _tbm_bufmgr_mutex_unlock();
587                 return NULL;
588         }
589
590         _tbm_util_check_bo_cnt(bufmgr);
591
592         if (!bufmgr->backend->surface_bo_alloc) {
593                 TBM_ERR("error: not supported tbm_bo_alloc_with_surface\n");
594                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
595                 free(bo);
596                 _tbm_bufmgr_mutex_unlock();
597                 return NULL;
598         }
599
600         bo_priv = bufmgr->backend->surface_bo_alloc(bo, width, height, format, flags, bo_idx);
601         if (!bo_priv) {
602                 TBM_ERR("error: fail to tbm_bo_alloc_with_surface fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
603                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
604                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
605                 free(bo);
606                 _tbm_bufmgr_mutex_unlock();
607                 return NULL;
608         }
609
610         bo->priv = bo_priv;
611         _tbm_bo_init(bufmgr, bo, flags);
612
613         _tbm_bufmgr_mutex_unlock();
614
615         return bo;
616 }
617
618 tbm_bo
619 tbm_bo_alloc_with_bo_data(tbm_bufmgr bufmgr, tbm_backend_bo_data *bo_data, int flags)
620 {
621         tbm_bo bo;
622
623         _tbm_bufmgr_mutex_lock();
624         _tbm_set_last_result(TBM_ERROR_NONE);
625
626         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
627         TBM_BO_RETURN_VAL_IF_FAIL(bo_data, NULL);
628
629         bo = calloc(1, sizeof(struct _tbm_bo));
630         if (!bo) {
631                 /* LCOV_EXCL_START */
632                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
633                 _tbm_bufmgr_mutex_unlock();
634                 return NULL;
635                 /* LCOV_EXCL_STOP */
636         }
637
638         _tbm_util_check_bo_cnt(bufmgr);
639
640         bo->bo_data = bo_data;
641
642         _tbm_bo_init(bufmgr, bo, flags);
643
644         TBM_TRACE_BO("bo(%p) refcnt(%d), flag(%s)\n", bo, bo->ref_cnt, _tbm_flag_to_str(bo->flags));
645
646         _tbm_bufmgr_mutex_unlock();
647
648         return bo;
649 }
650
651 /* LCOV_EXCL_STOP */
652
653 tbm_bo
654 tbm_bo_ref(tbm_bo bo)
655 {
656         _tbm_bufmgr_mutex_lock();
657         _tbm_set_last_result(TBM_ERROR_NONE);
658
659         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
660
661         bo->ref_cnt++;
662
663         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
664
665         _tbm_bufmgr_mutex_unlock();
666
667         return bo;
668 }
669
670 void
671 tbm_bo_unref(tbm_bo bo)
672 {
673         _tbm_bufmgr_mutex_lock();
674         _tbm_set_last_result(TBM_ERROR_NONE);
675
676         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
677
678         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
679
680         if (bo->ref_cnt <= 0) {
681                 _tbm_bufmgr_mutex_unlock();
682                 return;
683         }
684
685         bo->ref_cnt--;
686         if (bo->ref_cnt == 0)
687                 _tbm_bo_free(bo);
688
689         _tbm_bufmgr_mutex_unlock();
690 }
691
692 tbm_bo_handle
693 tbm_bo_map(tbm_bo bo, int device, int opt)
694 {
695         tbm_bo_handle bo_handle;
696         tbm_error_e error;
697
698         _tbm_bufmgr_mutex_lock();
699         _tbm_set_last_result(TBM_ERROR_NONE);
700
701         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
702
703         if (!_tbm_bo_lock(bo, device, opt)) {
704                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
705                 _tbm_bufmgr_mutex_unlock();
706                 return (tbm_bo_handle) NULL;
707         }
708
709         if (bo->bufmgr->use_hal_tbm) {
710                 hal_tbm_bo_handle hbo_handle;
711                 hbo_handle = hal_tbm_bo_map((hal_tbm_bo *)bo->bo_data, device, opt, (hal_tbm_error *)&error);
712                 if (hbo_handle.ptr == NULL) {
713                         /* LCOV_EXCL_START */
714                         _tbm_set_last_result(error);
715                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
716                         goto bo_map_fail;
717                         /* LCOV_EXCL_STOP */
718                 }
719                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
720         } else if (bo->bufmgr->backend_module_data) {
721                 bo_handle = bo->bufmgr->bo_func->bo_map(bo->bo_data, device, opt, &error);
722                 if (bo_handle.ptr == NULL) {
723                         /* LCOV_EXCL_START */
724                         _tbm_set_last_result(error);
725                         TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
726                         goto bo_map_fail;
727                         /* LCOV_EXCL_STOP */
728                 }
729         } else {
730                 bo_handle = bo->bufmgr->backend->bo_map(bo, device, opt);
731                 if (bo_handle.ptr == NULL) {
732                         /* LCOV_EXCL_START */
733                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
734                         TBM_ERR("error: fail to map bo:%p\n", bo);
735                         goto bo_map_fail;
736                         /* LCOV_EXCL_STOP */
737                 }
738         }
739
740         /* increase the map_count */
741         bo->map_cnt++;
742
743         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
744
745         _tbm_bufmgr_mutex_unlock();
746
747         return bo_handle;
748
749 bo_map_fail:
750         _tbm_bo_unlock(bo);
751         _tbm_bufmgr_mutex_unlock();
752         return (tbm_bo_handle) NULL;
753 }
754
755 int
756 tbm_bo_unmap(tbm_bo bo)
757 {
758         int ret = 1;
759         tbm_error_e error;
760
761         _tbm_bufmgr_mutex_lock();
762         _tbm_set_last_result(TBM_ERROR_NONE);
763
764         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
765         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
766
767         if (bo->bufmgr->use_hal_tbm) {
768                 error = (hal_tbm_error)hal_tbm_bo_unmap((hal_tbm_bo *)bo->bo_data);
769                 if (error != TBM_ERROR_NONE) {
770                         /* LCOV_EXCL_START */
771                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
772                         _tbm_set_last_result(error);
773                         ret = 0;
774                         goto done;
775                         /* LCOV_EXCL_STOP */
776                 }
777         } else if (bo->bufmgr->backend_module_data) {
778                 error = bo->bufmgr->bo_func->bo_unmap(bo->bo_data);
779                 if (error != TBM_ERROR_NONE) {
780                         /* LCOV_EXCL_START */
781                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
782                         _tbm_set_last_result(error);
783                         ret = 0;
784                         goto done;
785                         /* LCOV_EXCL_STOP */
786                 }
787         } else {
788                 ret = bo->bufmgr->backend->bo_unmap(bo);
789                 if (!ret) {
790                         /* LCOV_EXCL_START */
791                         TBM_ERR("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
792                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
793                         goto done;
794                         /* LCOV_EXCL_STOP */
795                 }
796         }
797
798         /* decrease the map_count */
799         bo->map_cnt--;
800
801         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
802
803         _tbm_bo_unlock(bo);
804
805 done:
806         _tbm_bufmgr_mutex_unlock();
807
808         return ret;
809 }
810
811 tbm_bo_handle
812 tbm_bo_get_handle(tbm_bo bo, int device)
813 {
814         tbm_bo_handle bo_handle;
815         tbm_error_e error;
816
817         _tbm_bufmgr_mutex_lock();
818         _tbm_set_last_result(TBM_ERROR_NONE);
819
820         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
821
822         if (bo->bufmgr->use_hal_tbm) {
823                 hal_tbm_bo_handle hbo_handle;
824                 hbo_handle = hal_tbm_bo_get_handle((hal_tbm_bo *)bo->bo_data, device, (hal_tbm_error *)&error);
825                 if (hbo_handle.ptr == NULL) {
826                         /* LCOV_EXCL_START */
827                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
828                         _tbm_set_last_result(error);
829                         goto bo_handle_fail;
830                         /* LCOV_EXCL_STOP */
831                 }
832                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
833         } else if (bo->bufmgr->backend_module_data) {
834                 bo_handle = bo->bufmgr->bo_func->bo_get_handle(bo->bo_data, device, &error);
835                 if (bo_handle.ptr == NULL) {
836                         /* LCOV_EXCL_START */
837                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
838                         _tbm_set_last_result(error);
839                         goto bo_handle_fail;
840                         /* LCOV_EXCL_STOP */
841                 }
842         } else {
843                 bo_handle = bo->bufmgr->backend->bo_get_handle(bo, device);
844                 if (bo_handle.ptr == NULL) {
845                         /* LCOV_EXCL_START */
846                         TBM_ERR("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
847                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
848                         goto bo_handle_fail;
849                         /* LCOV_EXCL_STOP */
850                 }
851         }
852
853         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
854
855         _tbm_bufmgr_mutex_unlock();
856
857         return bo_handle;
858
859 bo_handle_fail:
860         _tbm_bufmgr_mutex_unlock();
861         return (tbm_bo_handle) NULL;
862 }
863
864 tbm_key
865 tbm_bo_export(tbm_bo bo)
866 {
867         tbm_key ret;
868         tbm_error_e error;
869
870         _tbm_bufmgr_mutex_lock();
871         _tbm_set_last_result(TBM_ERROR_NONE);
872
873         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
874
875         if (bo->bufmgr->use_hal_tbm) {
876                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
877                 if (!ret) {
878                         /* LCOV_EXCL_START */
879                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
880                         _tbm_set_last_result(error);
881                         goto done;
882                         /* LCOV_EXCL_STOP */
883                 }
884         } else if (bo->bufmgr->backend_module_data) {
885                 if (!bo->bufmgr->bo_func->bo_export_key) {
886                         /* LCOV_EXCL_START */
887                         _tbm_bufmgr_mutex_unlock();
888                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
889                         return 0;
890                         /* LCOV_EXCL_STOP */
891                 }
892
893                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
894                 if (!ret) {
895                         /* LCOV_EXCL_START */
896                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
897                         _tbm_set_last_result(error);
898                         goto done;
899                         /* LCOV_EXCL_STOP */
900                 }
901         } else {
902                 if (!bo->bufmgr->backend->bo_export) {
903                         /* LCOV_EXCL_START */
904                         _tbm_bufmgr_mutex_unlock();
905                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
906                         return 0;
907                         /* LCOV_EXCL_STOP */
908                 }
909
910                 ret = bo->bufmgr->backend->bo_export(bo);
911                 if (!ret) {
912                         /* LCOV_EXCL_START */
913                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
914                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
915                         goto done;
916                         /* LCOV_EXCL_STOP */
917                 }
918         }
919
920         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
921
922 done:
923         _tbm_bufmgr_mutex_unlock();
924
925         return ret;
926 }
927
928 tbm_fd
929 tbm_bo_export_fd(tbm_bo bo)
930 {
931         tbm_fd ret;
932         tbm_error_e error;
933
934         _tbm_bufmgr_mutex_lock();
935         _tbm_set_last_result(TBM_ERROR_NONE);
936
937         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
938
939         if (bo->bufmgr->use_hal_tbm) {
940                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
941                 if (ret < 0) {
942                         /* LCOV_EXCL_START */
943                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
944                         _tbm_set_last_result(error);
945                         goto done;
946                         /* LCOV_EXCL_STOP */
947                 }
948         } else if (bo->bufmgr->backend_module_data) {
949                 if (!bo->bufmgr->bo_func->bo_export_fd) {
950                         /* LCOV_EXCL_START */
951                         _tbm_bufmgr_mutex_unlock();
952                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
953                         return -1;
954                         /* LCOV_EXCL_STOP */
955                 }
956
957                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
958                 if (ret < 0) {
959                         /* LCOV_EXCL_START */
960                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
961                         _tbm_set_last_result(error);
962                         goto done;
963                         /* LCOV_EXCL_STOP */
964                 }
965         } else {
966                 if (!bo->bufmgr->backend->bo_export_fd) {
967                         /* LCOV_EXCL_START */
968                         _tbm_bufmgr_mutex_unlock();
969                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
970                         return -1;
971                         /* LCOV_EXCL_STOP */
972                 }
973
974                 ret = bo->bufmgr->backend->bo_export_fd(bo);
975                 if (ret < 0) {
976                         /* LCOV_EXCL_START */
977                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
978                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
979                         goto done;
980                         /* LCOV_EXCL_STOP */
981                 }
982         }
983
984         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
985
986 done:
987         _tbm_bufmgr_mutex_unlock();
988
989         return ret;
990 }
991
992 tbm_bo
993 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
994 {
995         tbm_bo bo;
996         tbm_bo bo2 = NULL;
997         void *bo_priv;
998         tbm_error_e error;
999         tbm_backend_bo_data *bo_data;
1000         int flags;
1001
1002         _tbm_bufmgr_mutex_lock();
1003         _tbm_set_last_result(TBM_ERROR_NONE);
1004
1005         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1006
1007         if (!bufmgr->use_hal_tbm) {
1008                 if (bufmgr->backend_module_data) {
1009                         if (!bufmgr->bufmgr_func->bufmgr_import_key) {
1010                                 /* LCOV_EXCL_START */
1011                                 _tbm_bufmgr_mutex_unlock();
1012                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1013                                 return NULL;
1014                                 /* LCOV_EXCL_STOP */
1015                         }
1016                 } else {
1017                         if (!bufmgr->backend->bo_import) {
1018                                 /* LCOV_EXCL_START */
1019                                 _tbm_bufmgr_mutex_unlock();
1020                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1021                                 return NULL;
1022                                 /* LCOV_EXCL_STOP */
1023                         }
1024                 }
1025         }
1026
1027         _tbm_util_check_bo_cnt(bufmgr);
1028
1029         bo = calloc(1, sizeof(struct _tbm_bo));
1030         if (!bo) {
1031                 /* LCOV_EXCL_START */
1032                 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
1033                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1034                 _tbm_bufmgr_mutex_unlock();
1035                 return NULL;
1036                 /* LCOV_EXCL_STOP */
1037         }
1038
1039         if (bufmgr->use_hal_tbm) {
1040                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_import_key(bufmgr->hal_bufmgr, key, (hal_tbm_error *)&error);
1041                 /* LCOV_EXCL_START */
1042                 if (!bo_data) {
1043                         TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
1044                         _tbm_set_last_result(error);
1045                         goto import_fail;
1046                 }
1047                 /* LCOV_EXCL_STOP */
1048                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1049                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1050                                 if (bo2->bo_data == bo_data) {
1051                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1052                                                         bo2, bo2->ref_cnt, key,
1053                                                         _tbm_flag_to_str(bo2->flags));
1054                                         bo2->ref_cnt++;
1055                                         free(bo);
1056                                         _tbm_bufmgr_mutex_unlock();
1057                                         return bo2;
1058                                 }
1059                         }
1060                 }
1061                 bo->bo_data = bo_data;
1062         } else if (bufmgr->backend_module_data) {
1063                 bo_data = bufmgr->bufmgr_func->bufmgr_import_key(bufmgr->bufmgr_data, key, &error);
1064                 if (!bo_data) {
1065                         /* LCOV_EXCL_START */
1066                         TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
1067                         _tbm_set_last_result(error);
1068                         goto import_fail;
1069                         /* LCOV_EXCL_STOP */
1070                 }
1071
1072                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1073                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1074                                 if (bo2->bo_data == bo_data) {
1075                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1076                                                         bo2, bo2->ref_cnt, key,
1077                                                         _tbm_flag_to_str(bo2->flags));
1078                                         bo2->ref_cnt++;
1079                                         free(bo);
1080                                         _tbm_bufmgr_mutex_unlock();
1081                                         return bo2;
1082                                 }
1083                         }
1084                 }
1085                 bo->bo_data = bo_data;
1086         } else {
1087                 bo_priv = bufmgr->backend->bo_import(bo, key);
1088                 if (!bo_priv) {
1089                         /* LCOV_EXCL_START */
1090                         TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
1091                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1092                         goto import_fail;
1093                         /* LCOV_EXCL_STOP */
1094                 }
1095
1096                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1097                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1098                                 if (bo2->priv == bo_priv) {
1099                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1100                                                         bo2, bo2->ref_cnt, key,
1101                                                         _tbm_flag_to_str(bo2->flags));
1102                                         bo2->ref_cnt++;
1103                                         free(bo);
1104                                         _tbm_bufmgr_mutex_unlock();
1105                                         return bo2;
1106                                 }
1107                         }
1108                 }
1109                 bo->priv = bo_priv;
1110         }
1111
1112         if (bufmgr->use_hal_tbm) {
1113                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1114                 if (error != TBM_ERROR_NONE) {
1115                         TBM_ERR("fail to get the bo flags(memory_types)");
1116                         _tbm_set_last_result(error);
1117                         flags = TBM_BO_DEFAULT;
1118                 }
1119         } else if (bufmgr->backend_module_data) {
1120                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
1121                 if (error != TBM_ERROR_NONE) {
1122                         TBM_ERR("fail to get the bo flags(memory_types)");
1123                         _tbm_set_last_result(error);
1124                         flags = TBM_BO_DEFAULT;
1125                 }
1126         } else {
1127                 if (bufmgr->backend->bo_get_flags)
1128                         flags = bufmgr->backend->bo_get_flags(bo);
1129                 else
1130                         flags = TBM_BO_DEFAULT;
1131         }
1132
1133         _tbm_bo_init(bufmgr, bo, flags);
1134
1135         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1136                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
1137
1138         _tbm_bufmgr_mutex_unlock();
1139
1140         return bo;
1141
1142 import_fail:
1143         free(bo);
1144         _tbm_bufmgr_mutex_unlock();
1145         return NULL;
1146 }
1147
1148 tbm_bo
1149 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
1150 {
1151         tbm_bo bo;
1152         tbm_bo bo2 = NULL;
1153         void *bo_priv;
1154         tbm_backend_bo_data *bo_data;
1155         tbm_error_e error;
1156         int flags;
1157
1158         _tbm_bufmgr_mutex_lock();
1159         _tbm_set_last_result(TBM_ERROR_NONE);
1160
1161         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1162
1163         if (!bufmgr->use_hal_tbm) {
1164                 if (bufmgr->backend_module_data) {
1165                         if (!bufmgr->bufmgr_func->bufmgr_import_fd) {
1166                                 /* LCOV_EXCL_START */
1167                                 _tbm_bufmgr_mutex_unlock();
1168                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1169                                 return NULL;
1170                                 /* LCOV_EXCL_STOP */
1171                         }
1172                 } else {
1173                         if (!bufmgr->backend->bo_import_fd) {
1174                                 /* LCOV_EXCL_START */
1175                                 _tbm_bufmgr_mutex_unlock();
1176                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1177                                 return NULL;
1178                                 /* LCOV_EXCL_STOP */
1179                         }
1180                 }
1181         }
1182
1183         _tbm_util_check_bo_cnt(bufmgr);
1184
1185         bo = calloc(1, sizeof(struct _tbm_bo));
1186         if (!bo) {
1187                 /* LCOV_EXCL_START */
1188                 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1189                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1190                 _tbm_bufmgr_mutex_unlock();
1191                 return NULL;
1192                 /* LCOV_EXCL_STOP */
1193         }
1194
1195         if (bufmgr->use_hal_tbm) {
1196                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_import_fd(bufmgr->hal_bufmgr, (hal_tbm_fd)fd, (hal_tbm_error *)&error);
1197                 /* LCOV_EXCL_START */
1198                 if (!bo_data) {
1199                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
1200                         _tbm_set_last_result(error);
1201                         goto import_fail;
1202                 }
1203                 /* LCOV_EXCL_STOP */
1204
1205                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1206                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1207                                 if (bo2->bo_data == bo_data) {
1208                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1209                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1210                                         bo2->ref_cnt++;
1211                                         free(bo);
1212                                         _tbm_bufmgr_mutex_unlock();
1213                                         return bo2;
1214                                 }
1215                         }
1216                 }
1217                 bo->bo_data = bo_data;
1218         } else if (bufmgr->backend_module_data) {
1219                 bo_data = bufmgr->bufmgr_func->bufmgr_import_fd(bufmgr->bufmgr_data, fd, &error);
1220                 if (!bo_data) {
1221                         /* LCOV_EXCL_START */
1222                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
1223                         _tbm_set_last_result(error);
1224                         goto import_fail;
1225                         /* LCOV_EXCL_STOP */
1226                 }
1227
1228                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1229                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1230                                 if (bo2->bo_data == bo_data) {
1231                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1232                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1233                                         bo2->ref_cnt++;
1234                                         free(bo);
1235                                         _tbm_bufmgr_mutex_unlock();
1236                                         return bo2;
1237                                 }
1238                         }
1239                 }
1240                 bo->bo_data = bo_data;
1241         } else {
1242                 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1243                 if (!bo_priv) {
1244                         /* LCOV_EXCL_START */
1245                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1246                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1247                         goto import_fail;
1248                         /* LCOV_EXCL_STOP */
1249                 }
1250
1251                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1252                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1253                                 if (bo2->priv == bo_priv) {
1254                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1255                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1256                                         bo2->ref_cnt++;
1257                                         free(bo);
1258                                         _tbm_bufmgr_mutex_unlock();
1259                                         return bo2;
1260                                 }
1261                         }
1262                 }
1263                 bo->priv = bo_priv;
1264         }
1265
1266         if (bufmgr->use_hal_tbm) {
1267                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1268                 if (error != TBM_ERROR_NONE) {
1269                         TBM_ERR("fail to get the bo flags(memory_types)");
1270                         _tbm_set_last_result(error);
1271                         flags = TBM_BO_DEFAULT;
1272                 }
1273         } else if (bufmgr->backend_module_data) {
1274                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
1275                 if (error != TBM_ERROR_NONE) {
1276                         TBM_ERR("fail to get the bo flags(memory_types)");
1277                         _tbm_set_last_result(error);
1278                         flags = TBM_BO_DEFAULT;
1279                 }
1280         } else {
1281                 if (bufmgr->backend->bo_get_flags)
1282                         flags = bufmgr->backend->bo_get_flags(bo);
1283                 else
1284                         flags = TBM_BO_DEFAULT;
1285         }
1286
1287         _tbm_bo_init(bufmgr, bo, flags);
1288
1289         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
1290                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1291
1292         _tbm_bufmgr_mutex_unlock();
1293
1294         return bo;
1295
1296 import_fail:
1297         free(bo);
1298         _tbm_bufmgr_mutex_unlock();
1299         return NULL;
1300 }
1301
1302 int
1303 tbm_bo_size(tbm_bo bo)
1304 {
1305         int size;
1306         tbm_error_e error;
1307
1308         _tbm_bufmgr_mutex_lock();
1309         _tbm_set_last_result(TBM_ERROR_NONE);
1310
1311         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1312
1313         if (bo->bufmgr->use_hal_tbm) {
1314                 size = hal_tbm_bo_get_size((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1315                 if (error != TBM_ERROR_NONE) {
1316                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
1317                         _tbm_set_last_result(TBM_ERROR_NONE);
1318                 }
1319         } else if (bo->bufmgr->backend_module_data) {
1320                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
1321                 if (error != TBM_ERROR_NONE) {
1322                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
1323                         _tbm_set_last_result(TBM_ERROR_NONE);
1324                 }
1325         } else
1326                 size = bo->bufmgr->backend->bo_size(bo);
1327
1328         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
1329
1330         _tbm_bufmgr_mutex_unlock();
1331
1332         return size;
1333 }
1334
1335 int
1336 tbm_bo_locked(tbm_bo bo)
1337 {
1338         _tbm_bufmgr_mutex_lock();
1339         _tbm_set_last_result(TBM_ERROR_NONE);
1340
1341         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1342
1343         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
1344                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1345                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1346                 _tbm_bufmgr_mutex_unlock();
1347                 return 0;
1348         }
1349
1350         if (bo->lock_cnt > 0) {
1351                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1352                 _tbm_bufmgr_mutex_unlock();
1353                 return 1;
1354         }
1355
1356         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1357         _tbm_bufmgr_mutex_unlock();
1358
1359         return 0;
1360 }
1361
1362 int
1363 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1364 {
1365         tbm_error_e error1, error2;
1366         int size1 = -1, size2 = -2;
1367         void *temp;
1368
1369         _tbm_bufmgr_mutex_lock();
1370         _tbm_set_last_result(TBM_ERROR_NONE);
1371
1372         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1373         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1374
1375         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1376
1377         if (bo1->bufmgr->use_hal_tbm) {
1378                 size1 = hal_tbm_bo_get_size((hal_tbm_bo *)bo1->bo_data, (hal_tbm_error *)&error1);
1379                 if (error1 != TBM_ERROR_NONE) {
1380                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1381                         _tbm_set_last_result(error1);
1382                         goto fail;
1383                 }
1384                 size2 = hal_tbm_bo_get_size((hal_tbm_bo *)bo2->bo_data, (hal_tbm_error *)&error2);
1385                 if (error2 != TBM_ERROR_NONE) {
1386                         TBM_ERR("fail to get the size of bo1.(%d)", error2);
1387                         _tbm_set_last_result(error2);
1388                         goto fail;
1389                 }
1390         } else if (bo1->bufmgr->backend_module_data) {
1391                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
1392                 if (error1 != TBM_ERROR_NONE) {
1393                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1394                         _tbm_set_last_result(error1);
1395                         goto fail;
1396                 }
1397                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
1398                 if (error2 != TBM_ERROR_NONE) {
1399                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
1400                         _tbm_set_last_result(error2);
1401                         goto fail;
1402                 }
1403         } else {
1404                 size1 = bo1->bufmgr->backend->bo_size(bo1);
1405                 size2 = bo2->bufmgr->backend->bo_size(bo2);
1406         }
1407
1408         if (size1 != size2) {
1409                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
1410                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1411                 goto fail;
1412         }
1413
1414         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1415
1416         temp = bo1->priv;
1417         bo1->priv = bo2->priv;
1418         bo2->priv = temp;
1419
1420         _tbm_bufmgr_mutex_unlock();
1421
1422         return 1;
1423
1424 fail:
1425         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1426         _tbm_bufmgr_mutex_unlock();
1427
1428         return 0;
1429 }
1430
1431 int
1432 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1433                      tbm_data_free data_free_func)
1434 {
1435         tbm_user_data *data;
1436
1437         _tbm_bufmgr_mutex_lock();
1438         _tbm_set_last_result(TBM_ERROR_NONE);
1439
1440         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1441
1442         /* check if the data according to the key exist if so, return false. */
1443         data = user_data_lookup(&bo->user_data_list, key);
1444         if (data) {
1445                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
1446                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1447                 _tbm_bufmgr_mutex_unlock();
1448                 return 0;
1449         }
1450
1451         data = user_data_create(key, data_free_func);
1452         if (!data) {
1453                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
1454                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1455                 _tbm_bufmgr_mutex_unlock();
1456                 return 0;
1457         }
1458
1459         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1460
1461         LIST_ADD(&data->item_link, &bo->user_data_list);
1462
1463         _tbm_bufmgr_mutex_unlock();
1464
1465         return 1;
1466 }
1467
1468 int
1469 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1470 {
1471         tbm_user_data *old_data;
1472
1473         _tbm_bufmgr_mutex_lock();
1474         _tbm_set_last_result(TBM_ERROR_NONE);
1475
1476         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1477
1478         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1479                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1480                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1481                 _tbm_bufmgr_mutex_unlock();
1482                 return 0;
1483         }
1484
1485         old_data = user_data_lookup(&bo->user_data_list, key);
1486         if (!old_data) {
1487                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1488                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1489                 _tbm_bufmgr_mutex_unlock();
1490                 return 0;
1491         }
1492
1493         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1494
1495         user_data_delete(old_data);
1496
1497         _tbm_bufmgr_mutex_unlock();
1498
1499         return 1;
1500 }
1501
1502 int
1503 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1504 {
1505         tbm_user_data *old_data;
1506
1507         _tbm_bufmgr_mutex_lock();
1508         _tbm_set_last_result(TBM_ERROR_NONE);
1509
1510         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1511
1512         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1513                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1514                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1515                 _tbm_bufmgr_mutex_unlock();
1516                 return 0;
1517         }
1518
1519         old_data = user_data_lookup(&bo->user_data_list, key);
1520         if (!old_data) {
1521                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1522                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1523                 _tbm_bufmgr_mutex_unlock();
1524                 return 0;
1525         }
1526
1527         if (old_data->data && old_data->free_func)
1528                 old_data->free_func(old_data->data);
1529         old_data->data = data;
1530
1531         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1532
1533         _tbm_bufmgr_mutex_unlock();
1534
1535         return 1;
1536 }
1537
1538 int
1539 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1540 {
1541         tbm_user_data *old_data;
1542
1543         _tbm_bufmgr_mutex_lock();
1544         _tbm_set_last_result(TBM_ERROR_NONE);
1545
1546         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1547
1548         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1549                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1550                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1551                 _tbm_bufmgr_mutex_unlock();
1552                 return 0;
1553         }
1554
1555         old_data = user_data_lookup(&bo->user_data_list, key);
1556         if (!old_data) {
1557                 *data = NULL;
1558                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1559                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1560                 _tbm_bufmgr_mutex_unlock();
1561                 return 0;
1562         }
1563
1564         *data = old_data->data;
1565
1566         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1567
1568         _tbm_bufmgr_mutex_unlock();
1569
1570         return 1;
1571 }
1572
1573 int
1574 tbm_bo_get_flags(tbm_bo bo)
1575 {
1576         int flags;
1577
1578         _tbm_bufmgr_mutex_lock();
1579
1580         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1581
1582         flags = bo->flags;
1583
1584         TBM_TRACE_BO("bo(%p)\n", bo);
1585
1586         _tbm_bufmgr_mutex_unlock();
1587
1588         return flags;
1589 }
1590
1591 /* LCOV_EXCL_START */
1592 /* internal function */
1593 int
1594 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1595 {
1596         _tbm_bufmgr_mutex_lock();
1597
1598         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1599
1600         bo->surface = surface;
1601
1602         _tbm_bufmgr_mutex_unlock();
1603
1604         return 1;
1605 }
1606
1607 void
1608 _tbm_bo_free(tbm_bo bo)
1609 {
1610         /* destory the user_data_list */
1611         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1612                 tbm_user_data *old_data = NULL, *tmp;
1613
1614                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1615                                 &bo->user_data_list, item_link) {
1616                         TBM_DBG("free user_data\n");
1617                         user_data_delete(old_data);
1618                 }
1619         }
1620
1621         while (bo->lock_cnt > 0) {
1622                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1623                 _bo_unlock(bo);
1624                 bo->lock_cnt--;
1625         }
1626
1627         /* call the bo_free */
1628         if (bo->bufmgr->use_hal_tbm) {
1629                 // call hal_tbm_bo_free when bo is created by tbm_bo_alloc api.
1630                 if (bo->allocated_hal_tbm_bo) {
1631                         hal_tbm_bo_free(bo->bo_data);
1632                         bo->bo_data = NULL;
1633                         bo->allocated_hal_tbm_bo = 0;
1634                 }
1635         } else if (bo->bufmgr->backend_module_data) {
1636                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1637                 bo->bo_data = NULL;
1638         } else {
1639                 bo->bufmgr->backend->bo_free(bo);
1640                 bo->priv = NULL;
1641         }
1642
1643         _tbm_bo_deinit(bo);
1644
1645         free(bo);
1646 }
1647 /* LCOV_EXCL_STOP */