tbm_module: make tbm_module_bufmgr_bo_alloc function
[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         tbm_backend_bo_data *bo_data;
358         tbm_error_e error;
359
360         _tbm_bufmgr_mutex_lock();
361         _tbm_set_last_result(TBM_ERROR_NONE);
362
363         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
364         TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
365
366         bo = calloc(1, sizeof(struct _tbm_bo));
367         if (!bo) {
368                 /* LCOV_EXCL_START */
369                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
370                 _tbm_bufmgr_mutex_unlock();
371                 return NULL;
372                 /* LCOV_EXCL_STOP */
373         }
374
375         _tbm_util_check_bo_cnt(bufmgr);
376
377         bo_data = tbm_module_bufmgr_bo_alloc(bufmgr->module, bo, size, flags, &error);
378         if (!bo_data || error != TBM_ERROR_NONE) {
379                 /* LCOV_EXCL_START */
380                 TBM_ERR("tbm_module_bufmgr_bo_alloc failed. error:%d", error);
381                 _tbm_set_last_result(error);
382                 goto alloc_fail;
383                 /* LCOV_EXCL_STOP */
384         }
385         bo->bo_data = bo_data;
386         bo->priv = (void *)bo_data; // TODO: this will be DEPRECATED.
387
388         _tbm_bo_init(bufmgr, bo, flags);
389
390         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
391                         _tbm_flag_to_str(bo->flags));
392
393         _tbm_bufmgr_mutex_unlock();
394
395         return bo;
396
397 alloc_fail:
398         TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, _tbm_flag_to_str(flags));
399         free(bo);
400         _tbm_bufmgr_mutex_unlock();
401         return NULL;
402 }
403
404 /* LCOV_EXCL_START */
405 tbm_bo
406 tbm_bo_alloc_with_format(tbm_bufmgr bufmgr, int format, int bo_idx, int width,
407                                                 int height, int bpp, tbm_bo_memory_type flags, tbm_error_e *error)
408 {
409         tbm_bo bo;
410         tbm_backend_bo_data *bo_data;
411
412         _tbm_bufmgr_mutex_lock();
413         _tbm_set_last_result(TBM_ERROR_NONE);
414
415         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
416
417         bo = calloc(1, sizeof(struct _tbm_bo));
418         if (!bo) {
419                 TBM_ERR("error: fail to tbm_bo_alloc_with_format fmt(%s) idx(%d) w(%d) h(%d) mem_types(%s)\n",
420                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
421                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
422                 goto calloc_fail;
423         }
424
425         _tbm_util_check_bo_cnt(bufmgr);
426
427         /* LCOV_EXCL_START */
428         if (!bufmgr->use_hal_tbm) {
429                 if (!bufmgr->backend_module_data || !bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
430                         TBM_ERR("error: not supported tbm_bo_alloc_with_format\n");
431                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
432                         goto bo_alloc_fail;
433                 }
434         }
435         /* LCOV_EXCL_STOP */
436
437         if (bufmgr->use_hal_tbm) {
438                 hal_tbm_error ret;
439                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_alloc_bo_with_format(bufmgr->hal_bufmgr,
440                                                                 format, bo_idx, width, height, bpp, (hal_tbm_bo_memory_type)flags, &ret);
441                 if (error)
442                         *error = (tbm_error_e)ret;
443                 if (ret != HAL_TBM_ERROR_NONE) {
444                         if (ret != HAL_TBM_ERROR_NOT_SUPPORTED) {
445                                 TBM_ERR("error: fail to tbm_bo_alloc_with_format\n");
446                                 if (error)
447                                         _tbm_set_last_result(*error);
448                         }
449                         goto bo_alloc_fail;
450                 }
451                 bo->bo_data = bo_data;
452         } else {
453                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format(bufmgr->bufmgr_data, format, bo_idx,
454                                                                                                                                 width, height, flags, error);
455                 if (!bo_data) {
456                         TBM_ERR("error: fail to tbm_bo_alloc_with_format fmt(%s) idx(%d) w(%d) h(%d) mem_types(%s)\n",
457                                         FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
458                         if (error)
459                                 _tbm_set_last_result(*error);
460                         goto bo_alloc_fail;
461                 }
462                 bo->bo_data = bo_data;
463         }
464
465         _tbm_bo_init(bufmgr, bo, flags);
466
467         _tbm_bufmgr_mutex_unlock();
468
469         return bo;
470
471 bo_alloc_fail:
472         free(bo);
473 calloc_fail:
474         _tbm_bufmgr_mutex_unlock();
475         return NULL;
476 }
477
478 tbm_bo
479 tbm_bo_alloc_with_tiled_format(tbm_bufmgr bufmgr, int width, int height, int bpp, int format,
480                                                         tbm_bo_memory_type flags, int bo_idx, tbm_error_e *error)
481 {
482         tbm_bo bo;
483         tbm_backend_bo_data *bo_data;
484
485         _tbm_bufmgr_mutex_lock();
486         _tbm_set_last_result(TBM_ERROR_NONE);
487
488         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
489
490         bo = calloc(1, sizeof(struct _tbm_bo));
491         if (!bo) {
492                 TBM_ERR("error: fail to tbm_bo_alloc_with_tiled_format fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
493                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
494                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
495                 _tbm_bufmgr_mutex_unlock();
496                 return NULL;
497         }
498
499         _tbm_util_check_bo_cnt(bufmgr);
500
501         if (!bufmgr->use_hal_tbm) {
502                 if (!bufmgr->backend_module_data || !bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format) {
503                         TBM_ERR("error: not supported tbm_bo_alloc_with_tiled_format\n");
504                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
505                         goto bo_alloc_fail;
506                 }
507         }
508
509         if (bufmgr->use_hal_tbm) {
510                 hal_tbm_error ret;
511                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_alloc_bo_with_format(bufmgr->hal_bufmgr,
512                                                                 width, height, bpp, format, (hal_tbm_bo_memory_type)flags, bo_idx, &ret);
513                 if (error)
514                         *error = (tbm_error_e)ret;
515                 if (ret != HAL_TBM_ERROR_NONE) {
516                         if (ret != HAL_TBM_ERROR_NOT_SUPPORTED) {
517                                 TBM_ERR("error: fail to tbm_bo_alloc_with_tiled_format fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
518                                         FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
519                                 if (error)
520                                         _tbm_set_last_result(*error);
521                         }
522                         goto bo_alloc_fail;
523                 }
524                 bo->bo_data = bo_data;
525         } else {
526                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format(bufmgr->bufmgr_data, width, height,
527                                                                                                                                         bpp, format, flags, bo_idx, error);
528                 if (!bo_data) {
529                         TBM_ERR("error: fail to tbm_bo_alloc_with_tiled_format fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
530                                         FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
531                         if (error)
532                                 _tbm_set_last_result(*error);
533                         goto bo_alloc_fail;
534                 }
535                 bo->bo_data = bo_data;
536         }
537
538         _tbm_bo_init(bufmgr, bo, flags);
539
540         _tbm_bufmgr_mutex_unlock();
541
542         return bo;
543
544 bo_alloc_fail:
545         free(bo);
546         _tbm_bufmgr_mutex_unlock();
547         return NULL;
548 }
549
550 tbm_bo
551 tbm_bo_alloc_with_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, int bo_idx)
552 {
553         tbm_bo bo;
554         void *bo_priv;
555
556         _tbm_bufmgr_mutex_lock();
557         _tbm_set_last_result(TBM_ERROR_NONE);
558
559         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
560
561         bo = calloc(1, sizeof(struct _tbm_bo));
562         if (!bo) {
563                 TBM_ERR("error: fail to tbm_bo_alloc_with_surface fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
564                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
565                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
566                 _tbm_bufmgr_mutex_unlock();
567                 return NULL;
568         }
569
570         _tbm_util_check_bo_cnt(bufmgr);
571
572         if (!bufmgr->backend->surface_bo_alloc) {
573                 TBM_ERR("error: not supported tbm_bo_alloc_with_surface\n");
574                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
575                 free(bo);
576                 _tbm_bufmgr_mutex_unlock();
577                 return NULL;
578         }
579
580         bo_priv = bufmgr->backend->surface_bo_alloc(bo, width, height, format, flags, bo_idx);
581         if (!bo_priv) {
582                 TBM_ERR("error: fail to tbm_bo_alloc_with_surface fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
583                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
584                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
585                 free(bo);
586                 _tbm_bufmgr_mutex_unlock();
587                 return NULL;
588         }
589
590         bo->priv = bo_priv;
591         _tbm_bo_init(bufmgr, bo, flags);
592
593         _tbm_bufmgr_mutex_unlock();
594
595         return bo;
596 }
597
598 tbm_bo
599 tbm_bo_alloc_with_bo_data(tbm_bufmgr bufmgr, tbm_backend_bo_data *bo_data, int flags)
600 {
601         tbm_bo bo, bo2 = NULL;
602
603         _tbm_bufmgr_mutex_lock();
604         _tbm_set_last_result(TBM_ERROR_NONE);
605
606         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
607         TBM_BO_RETURN_VAL_IF_FAIL(bo_data, NULL);
608
609         // return an existed bo if the bo is already created with the same bo_data.
610         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
611                 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
612                         if (bo2->bo_data == bo_data) {
613                                 TBM_ERR("find bo(%p) ref(%d) flag(%s) in list\n",
614                                                 bo2, bo2->ref_cnt, _tbm_flag_to_str(bo2->flags));
615                                 bo2->ref_cnt++;
616                                 _tbm_bufmgr_mutex_unlock();
617                                 return bo2;
618                         }
619                 }
620         }
621
622         bo = calloc(1, sizeof(struct _tbm_bo));
623         if (!bo) {
624                 /* LCOV_EXCL_START */
625                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
626                 _tbm_bufmgr_mutex_unlock();
627                 return NULL;
628                 /* LCOV_EXCL_STOP */
629         }
630
631         _tbm_util_check_bo_cnt(bufmgr);
632
633         bo->get_from_hal_surface = 1;
634         bo->bo_data = bo_data;
635
636         _tbm_bo_init(bufmgr, bo, flags);
637
638         TBM_TRACE_BO("bo(%p) refcnt(%d), flag(%s)\n", bo, bo->ref_cnt, _tbm_flag_to_str(bo->flags));
639
640         _tbm_bufmgr_mutex_unlock();
641
642         return bo;
643 }
644
645 /* LCOV_EXCL_STOP */
646
647 tbm_bo
648 tbm_bo_ref(tbm_bo bo)
649 {
650         _tbm_bufmgr_mutex_lock();
651         _tbm_set_last_result(TBM_ERROR_NONE);
652
653         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
654
655         bo->ref_cnt++;
656
657         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
658
659         _tbm_bufmgr_mutex_unlock();
660
661         return bo;
662 }
663
664 void
665 tbm_bo_unref(tbm_bo bo)
666 {
667         _tbm_bufmgr_mutex_lock();
668         _tbm_set_last_result(TBM_ERROR_NONE);
669
670         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
671
672         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
673
674         if (bo->ref_cnt <= 0) {
675                 _tbm_bufmgr_mutex_unlock();
676                 return;
677         }
678
679         bo->ref_cnt--;
680         if (bo->ref_cnt == 0)
681                 _tbm_bo_free(bo);
682
683         _tbm_bufmgr_mutex_unlock();
684 }
685
686 tbm_bo_handle
687 tbm_bo_map(tbm_bo bo, int device, int opt)
688 {
689         tbm_bo_handle bo_handle;
690         tbm_error_e error;
691
692         _tbm_bufmgr_mutex_lock();
693         _tbm_set_last_result(TBM_ERROR_NONE);
694
695         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
696
697         if (!_tbm_bo_lock(bo, device, opt)) {
698                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
699                 _tbm_bufmgr_mutex_unlock();
700                 return (tbm_bo_handle) NULL;
701         }
702
703         if (bo->bufmgr->use_hal_tbm) {
704                 hal_tbm_bo_handle hbo_handle;
705                 hbo_handle = hal_tbm_bo_map((hal_tbm_bo *)bo->bo_data, device, opt, (hal_tbm_error *)&error);
706                 if (hbo_handle.ptr == NULL) {
707                         /* LCOV_EXCL_START */
708                         _tbm_set_last_result(error);
709                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
710                         goto bo_map_fail;
711                         /* LCOV_EXCL_STOP */
712                 }
713                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
714         } else if (bo->bufmgr->backend_module_data) {
715                 bo_handle = bo->bufmgr->bo_func->bo_map(bo->bo_data, device, opt, &error);
716                 if (bo_handle.ptr == NULL) {
717                         /* LCOV_EXCL_START */
718                         _tbm_set_last_result(error);
719                         TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
720                         goto bo_map_fail;
721                         /* LCOV_EXCL_STOP */
722                 }
723         } else {
724                 bo_handle = bo->bufmgr->backend->bo_map(bo, device, opt);
725                 if (bo_handle.ptr == NULL) {
726                         /* LCOV_EXCL_START */
727                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
728                         TBM_ERR("error: fail to map bo:%p\n", bo);
729                         goto bo_map_fail;
730                         /* LCOV_EXCL_STOP */
731                 }
732         }
733
734         /* increase the map_count */
735         bo->map_cnt++;
736
737         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
738
739         _tbm_bufmgr_mutex_unlock();
740
741         return bo_handle;
742
743 bo_map_fail:
744         _tbm_bo_unlock(bo);
745         _tbm_bufmgr_mutex_unlock();
746         return (tbm_bo_handle) NULL;
747 }
748
749 int
750 tbm_bo_unmap(tbm_bo bo)
751 {
752         int ret = 1;
753         tbm_error_e error;
754
755         _tbm_bufmgr_mutex_lock();
756         _tbm_set_last_result(TBM_ERROR_NONE);
757
758         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
759         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
760
761         if (bo->bufmgr->use_hal_tbm) {
762                 error = (hal_tbm_error)hal_tbm_bo_unmap((hal_tbm_bo *)bo->bo_data);
763                 if (error != TBM_ERROR_NONE) {
764                         /* LCOV_EXCL_START */
765                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
766                         _tbm_set_last_result(error);
767                         ret = 0;
768                         goto done;
769                         /* LCOV_EXCL_STOP */
770                 }
771         } else if (bo->bufmgr->backend_module_data) {
772                 error = bo->bufmgr->bo_func->bo_unmap(bo->bo_data);
773                 if (error != TBM_ERROR_NONE) {
774                         /* LCOV_EXCL_START */
775                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
776                         _tbm_set_last_result(error);
777                         ret = 0;
778                         goto done;
779                         /* LCOV_EXCL_STOP */
780                 }
781         } else {
782                 ret = bo->bufmgr->backend->bo_unmap(bo);
783                 if (!ret) {
784                         /* LCOV_EXCL_START */
785                         TBM_ERR("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
786                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
787                         goto done;
788                         /* LCOV_EXCL_STOP */
789                 }
790         }
791
792         /* decrease the map_count */
793         bo->map_cnt--;
794
795         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
796
797         _tbm_bo_unlock(bo);
798
799 done:
800         _tbm_bufmgr_mutex_unlock();
801
802         return ret;
803 }
804
805 tbm_bo_handle
806 tbm_bo_get_handle(tbm_bo bo, int device)
807 {
808         tbm_bo_handle bo_handle;
809         tbm_error_e error;
810
811         _tbm_bufmgr_mutex_lock();
812         _tbm_set_last_result(TBM_ERROR_NONE);
813
814         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
815
816         if (bo->bufmgr->use_hal_tbm) {
817                 hal_tbm_bo_handle hbo_handle;
818                 hbo_handle = hal_tbm_bo_get_handle((hal_tbm_bo *)bo->bo_data, device, (hal_tbm_error *)&error);
819                 if (hbo_handle.ptr == NULL) {
820                         /* LCOV_EXCL_START */
821                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
822                         _tbm_set_last_result(error);
823                         goto bo_handle_fail;
824                         /* LCOV_EXCL_STOP */
825                 }
826                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
827         } else if (bo->bufmgr->backend_module_data) {
828                 bo_handle = bo->bufmgr->bo_func->bo_get_handle(bo->bo_data, device, &error);
829                 if (bo_handle.ptr == NULL) {
830                         /* LCOV_EXCL_START */
831                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
832                         _tbm_set_last_result(error);
833                         goto bo_handle_fail;
834                         /* LCOV_EXCL_STOP */
835                 }
836         } else {
837                 bo_handle = bo->bufmgr->backend->bo_get_handle(bo, device);
838                 if (bo_handle.ptr == NULL) {
839                         /* LCOV_EXCL_START */
840                         TBM_ERR("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
841                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
842                         goto bo_handle_fail;
843                         /* LCOV_EXCL_STOP */
844                 }
845         }
846
847         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
848
849         _tbm_bufmgr_mutex_unlock();
850
851         return bo_handle;
852
853 bo_handle_fail:
854         _tbm_bufmgr_mutex_unlock();
855         return (tbm_bo_handle) NULL;
856 }
857
858 tbm_key
859 tbm_bo_export(tbm_bo bo)
860 {
861         tbm_key ret;
862         tbm_error_e error;
863
864         _tbm_bufmgr_mutex_lock();
865         _tbm_set_last_result(TBM_ERROR_NONE);
866
867         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
868
869         if (bo->bufmgr->use_hal_tbm) {
870                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
871                 if (!ret) {
872                         /* LCOV_EXCL_START */
873                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
874                         _tbm_set_last_result(error);
875                         goto done;
876                         /* LCOV_EXCL_STOP */
877                 }
878         } else if (bo->bufmgr->backend_module_data) {
879                 if (!bo->bufmgr->bo_func->bo_export_key) {
880                         /* LCOV_EXCL_START */
881                         _tbm_bufmgr_mutex_unlock();
882                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
883                         return 0;
884                         /* LCOV_EXCL_STOP */
885                 }
886
887                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
888                 if (!ret) {
889                         /* LCOV_EXCL_START */
890                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
891                         _tbm_set_last_result(error);
892                         goto done;
893                         /* LCOV_EXCL_STOP */
894                 }
895         } else {
896                 if (!bo->bufmgr->backend->bo_export) {
897                         /* LCOV_EXCL_START */
898                         _tbm_bufmgr_mutex_unlock();
899                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
900                         return 0;
901                         /* LCOV_EXCL_STOP */
902                 }
903
904                 ret = bo->bufmgr->backend->bo_export(bo);
905                 if (!ret) {
906                         /* LCOV_EXCL_START */
907                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
908                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
909                         goto done;
910                         /* LCOV_EXCL_STOP */
911                 }
912         }
913
914         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
915
916 done:
917         _tbm_bufmgr_mutex_unlock();
918
919         return ret;
920 }
921
922 tbm_fd
923 tbm_bo_export_fd(tbm_bo bo)
924 {
925         tbm_fd ret;
926         tbm_error_e error;
927
928         _tbm_bufmgr_mutex_lock();
929         _tbm_set_last_result(TBM_ERROR_NONE);
930
931         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
932
933         if (bo->bufmgr->use_hal_tbm) {
934                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
935                 if (ret < 0) {
936                         /* LCOV_EXCL_START */
937                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
938                         _tbm_set_last_result(error);
939                         goto done;
940                         /* LCOV_EXCL_STOP */
941                 }
942         } else if (bo->bufmgr->backend_module_data) {
943                 if (!bo->bufmgr->bo_func->bo_export_fd) {
944                         /* LCOV_EXCL_START */
945                         _tbm_bufmgr_mutex_unlock();
946                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
947                         return -1;
948                         /* LCOV_EXCL_STOP */
949                 }
950
951                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
952                 if (ret < 0) {
953                         /* LCOV_EXCL_START */
954                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
955                         _tbm_set_last_result(error);
956                         goto done;
957                         /* LCOV_EXCL_STOP */
958                 }
959         } else {
960                 if (!bo->bufmgr->backend->bo_export_fd) {
961                         /* LCOV_EXCL_START */
962                         _tbm_bufmgr_mutex_unlock();
963                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
964                         return -1;
965                         /* LCOV_EXCL_STOP */
966                 }
967
968                 ret = bo->bufmgr->backend->bo_export_fd(bo);
969                 if (ret < 0) {
970                         /* LCOV_EXCL_START */
971                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
972                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
973                         goto done;
974                         /* LCOV_EXCL_STOP */
975                 }
976         }
977
978         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
979
980 done:
981         _tbm_bufmgr_mutex_unlock();
982
983         return ret;
984 }
985
986 tbm_bo
987 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
988 {
989         tbm_bo bo;
990         tbm_bo bo2 = NULL;
991         void *bo_priv;
992         tbm_error_e error;
993         tbm_backend_bo_data *bo_data;
994         int flags;
995
996         _tbm_bufmgr_mutex_lock();
997         _tbm_set_last_result(TBM_ERROR_NONE);
998
999         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1000
1001         if (!bufmgr->use_hal_tbm) {
1002                 if (bufmgr->backend_module_data) {
1003                         if (!bufmgr->bufmgr_func->bufmgr_import_key) {
1004                                 /* LCOV_EXCL_START */
1005                                 _tbm_bufmgr_mutex_unlock();
1006                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1007                                 return NULL;
1008                                 /* LCOV_EXCL_STOP */
1009                         }
1010                 } else {
1011                         if (!bufmgr->backend->bo_import) {
1012                                 /* LCOV_EXCL_START */
1013                                 _tbm_bufmgr_mutex_unlock();
1014                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1015                                 return NULL;
1016                                 /* LCOV_EXCL_STOP */
1017                         }
1018                 }
1019         }
1020
1021         _tbm_util_check_bo_cnt(bufmgr);
1022
1023         bo = calloc(1, sizeof(struct _tbm_bo));
1024         if (!bo) {
1025                 /* LCOV_EXCL_START */
1026                 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
1027                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1028                 _tbm_bufmgr_mutex_unlock();
1029                 return NULL;
1030                 /* LCOV_EXCL_STOP */
1031         }
1032
1033         if (bufmgr->use_hal_tbm) {
1034                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_import_key(bufmgr->hal_bufmgr, key, (hal_tbm_error *)&error);
1035                 /* LCOV_EXCL_START */
1036                 if (!bo_data) {
1037                         TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
1038                         _tbm_set_last_result(error);
1039                         goto import_fail;
1040                 }
1041                 /* LCOV_EXCL_STOP */
1042                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1043                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1044                                 if (bo2->bo_data == bo_data) {
1045                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1046                                                         bo2, bo2->ref_cnt, key,
1047                                                         _tbm_flag_to_str(bo2->flags));
1048                                         bo2->ref_cnt++;
1049                                         free(bo);
1050                                         _tbm_bufmgr_mutex_unlock();
1051                                         return bo2;
1052                                 }
1053                         }
1054                 }
1055                 bo->bo_data = bo_data;
1056         } else if (bufmgr->backend_module_data) {
1057                 bo_data = bufmgr->bufmgr_func->bufmgr_import_key(bufmgr->bufmgr_data, key, &error);
1058                 if (!bo_data) {
1059                         /* LCOV_EXCL_START */
1060                         TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
1061                         _tbm_set_last_result(error);
1062                         goto import_fail;
1063                         /* LCOV_EXCL_STOP */
1064                 }
1065
1066                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1067                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1068                                 if (bo2->bo_data == bo_data) {
1069                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1070                                                         bo2, bo2->ref_cnt, key,
1071                                                         _tbm_flag_to_str(bo2->flags));
1072                                         bo2->ref_cnt++;
1073                                         free(bo);
1074                                         _tbm_bufmgr_mutex_unlock();
1075                                         return bo2;
1076                                 }
1077                         }
1078                 }
1079                 bo->bo_data = bo_data;
1080         } else {
1081                 bo_priv = bufmgr->backend->bo_import(bo, key);
1082                 if (!bo_priv) {
1083                         /* LCOV_EXCL_START */
1084                         TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
1085                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1086                         goto import_fail;
1087                         /* LCOV_EXCL_STOP */
1088                 }
1089
1090                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1091                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1092                                 if (bo2->priv == bo_priv) {
1093                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1094                                                         bo2, bo2->ref_cnt, key,
1095                                                         _tbm_flag_to_str(bo2->flags));
1096                                         bo2->ref_cnt++;
1097                                         free(bo);
1098                                         _tbm_bufmgr_mutex_unlock();
1099                                         return bo2;
1100                                 }
1101                         }
1102                 }
1103                 bo->priv = bo_priv;
1104         }
1105
1106         if (bufmgr->use_hal_tbm) {
1107                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1108                 if (error != TBM_ERROR_NONE) {
1109                         TBM_ERR("fail to get the bo flags(memory_types)");
1110                         _tbm_set_last_result(error);
1111                         flags = TBM_BO_DEFAULT;
1112                 }
1113         } else if (bufmgr->backend_module_data) {
1114                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
1115                 if (error != TBM_ERROR_NONE) {
1116                         TBM_ERR("fail to get the bo flags(memory_types)");
1117                         _tbm_set_last_result(error);
1118                         flags = TBM_BO_DEFAULT;
1119                 }
1120         } else {
1121                 if (bufmgr->backend->bo_get_flags)
1122                         flags = bufmgr->backend->bo_get_flags(bo);
1123                 else
1124                         flags = TBM_BO_DEFAULT;
1125         }
1126
1127         _tbm_bo_init(bufmgr, bo, flags);
1128
1129         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1130                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
1131
1132         _tbm_bufmgr_mutex_unlock();
1133
1134         return bo;
1135
1136 import_fail:
1137         free(bo);
1138         _tbm_bufmgr_mutex_unlock();
1139         return NULL;
1140 }
1141
1142 tbm_bo
1143 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
1144 {
1145         tbm_bo bo;
1146         tbm_bo bo2 = NULL;
1147         void *bo_priv;
1148         tbm_backend_bo_data *bo_data;
1149         tbm_error_e error;
1150         int flags;
1151
1152         _tbm_bufmgr_mutex_lock();
1153         _tbm_set_last_result(TBM_ERROR_NONE);
1154
1155         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1156
1157         if (!bufmgr->use_hal_tbm) {
1158                 if (bufmgr->backend_module_data) {
1159                         if (!bufmgr->bufmgr_func->bufmgr_import_fd) {
1160                                 /* LCOV_EXCL_START */
1161                                 _tbm_bufmgr_mutex_unlock();
1162                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1163                                 return NULL;
1164                                 /* LCOV_EXCL_STOP */
1165                         }
1166                 } else {
1167                         if (!bufmgr->backend->bo_import_fd) {
1168                                 /* LCOV_EXCL_START */
1169                                 _tbm_bufmgr_mutex_unlock();
1170                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1171                                 return NULL;
1172                                 /* LCOV_EXCL_STOP */
1173                         }
1174                 }
1175         }
1176
1177         _tbm_util_check_bo_cnt(bufmgr);
1178
1179         bo = calloc(1, sizeof(struct _tbm_bo));
1180         if (!bo) {
1181                 /* LCOV_EXCL_START */
1182                 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1183                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1184                 _tbm_bufmgr_mutex_unlock();
1185                 return NULL;
1186                 /* LCOV_EXCL_STOP */
1187         }
1188
1189         if (bufmgr->use_hal_tbm) {
1190                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_import_fd(bufmgr->hal_bufmgr, (hal_tbm_fd)fd, (hal_tbm_error *)&error);
1191                 /* LCOV_EXCL_START */
1192                 if (!bo_data) {
1193                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
1194                         _tbm_set_last_result(error);
1195                         goto import_fail;
1196                 }
1197                 /* LCOV_EXCL_STOP */
1198
1199                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1200                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1201                                 if (bo2->bo_data == bo_data) {
1202                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1203                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1204                                         bo2->ref_cnt++;
1205                                         free(bo);
1206                                         _tbm_bufmgr_mutex_unlock();
1207                                         return bo2;
1208                                 }
1209                         }
1210                 }
1211                 bo->bo_data = bo_data;
1212         } else if (bufmgr->backend_module_data) {
1213                 bo_data = bufmgr->bufmgr_func->bufmgr_import_fd(bufmgr->bufmgr_data, fd, &error);
1214                 if (!bo_data) {
1215                         /* LCOV_EXCL_START */
1216                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
1217                         _tbm_set_last_result(error);
1218                         goto import_fail;
1219                         /* LCOV_EXCL_STOP */
1220                 }
1221
1222                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1223                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1224                                 if (bo2->bo_data == bo_data) {
1225                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1226                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1227                                         bo2->ref_cnt++;
1228                                         free(bo);
1229                                         _tbm_bufmgr_mutex_unlock();
1230                                         return bo2;
1231                                 }
1232                         }
1233                 }
1234                 bo->bo_data = bo_data;
1235         } else {
1236                 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1237                 if (!bo_priv) {
1238                         /* LCOV_EXCL_START */
1239                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1240                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1241                         goto import_fail;
1242                         /* LCOV_EXCL_STOP */
1243                 }
1244
1245                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1246                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1247                                 if (bo2->priv == bo_priv) {
1248                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1249                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1250                                         bo2->ref_cnt++;
1251                                         free(bo);
1252                                         _tbm_bufmgr_mutex_unlock();
1253                                         return bo2;
1254                                 }
1255                         }
1256                 }
1257                 bo->priv = bo_priv;
1258         }
1259
1260         if (bufmgr->use_hal_tbm) {
1261                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1262                 if (error != TBM_ERROR_NONE) {
1263                         TBM_ERR("fail to get the bo flags(memory_types)");
1264                         _tbm_set_last_result(error);
1265                         flags = TBM_BO_DEFAULT;
1266                 }
1267         } else if (bufmgr->backend_module_data) {
1268                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
1269                 if (error != TBM_ERROR_NONE) {
1270                         TBM_ERR("fail to get the bo flags(memory_types)");
1271                         _tbm_set_last_result(error);
1272                         flags = TBM_BO_DEFAULT;
1273                 }
1274         } else {
1275                 if (bufmgr->backend->bo_get_flags)
1276                         flags = bufmgr->backend->bo_get_flags(bo);
1277                 else
1278                         flags = TBM_BO_DEFAULT;
1279         }
1280
1281         _tbm_bo_init(bufmgr, bo, flags);
1282
1283         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
1284                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1285
1286         _tbm_bufmgr_mutex_unlock();
1287
1288         return bo;
1289
1290 import_fail:
1291         free(bo);
1292         _tbm_bufmgr_mutex_unlock();
1293         return NULL;
1294 }
1295
1296 int
1297 tbm_bo_size(tbm_bo bo)
1298 {
1299         int size;
1300         tbm_error_e error;
1301
1302         _tbm_bufmgr_mutex_lock();
1303         _tbm_set_last_result(TBM_ERROR_NONE);
1304
1305         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1306
1307         if (bo->bufmgr->use_hal_tbm) {
1308                 size = hal_tbm_bo_get_size((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1309                 if (error != TBM_ERROR_NONE) {
1310                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
1311                         _tbm_set_last_result(TBM_ERROR_NONE);
1312                 }
1313         } else if (bo->bufmgr->backend_module_data) {
1314                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &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
1320                 size = bo->bufmgr->backend->bo_size(bo);
1321
1322         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
1323
1324         _tbm_bufmgr_mutex_unlock();
1325
1326         return size;
1327 }
1328
1329 int
1330 tbm_bo_locked(tbm_bo bo)
1331 {
1332         _tbm_bufmgr_mutex_lock();
1333         _tbm_set_last_result(TBM_ERROR_NONE);
1334
1335         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1336
1337         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
1338                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1339                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1340                 _tbm_bufmgr_mutex_unlock();
1341                 return 0;
1342         }
1343
1344         if (bo->lock_cnt > 0) {
1345                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1346                 _tbm_bufmgr_mutex_unlock();
1347                 return 1;
1348         }
1349
1350         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1351         _tbm_bufmgr_mutex_unlock();
1352
1353         return 0;
1354 }
1355
1356 int
1357 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1358 {
1359         tbm_error_e error1, error2;
1360         int size1 = -1, size2 = -2;
1361         void *temp;
1362
1363         _tbm_bufmgr_mutex_lock();
1364         _tbm_set_last_result(TBM_ERROR_NONE);
1365
1366         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1367         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1368
1369         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1370
1371         if (bo1->bufmgr->use_hal_tbm) {
1372                 size1 = hal_tbm_bo_get_size((hal_tbm_bo *)bo1->bo_data, (hal_tbm_error *)&error1);
1373                 if (error1 != TBM_ERROR_NONE) {
1374                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1375                         _tbm_set_last_result(error1);
1376                         goto fail;
1377                 }
1378                 size2 = hal_tbm_bo_get_size((hal_tbm_bo *)bo2->bo_data, (hal_tbm_error *)&error2);
1379                 if (error2 != TBM_ERROR_NONE) {
1380                         TBM_ERR("fail to get the size of bo1.(%d)", error2);
1381                         _tbm_set_last_result(error2);
1382                         goto fail;
1383                 }
1384         } else if (bo1->bufmgr->backend_module_data) {
1385                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
1386                 if (error1 != TBM_ERROR_NONE) {
1387                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1388                         _tbm_set_last_result(error1);
1389                         goto fail;
1390                 }
1391                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
1392                 if (error2 != TBM_ERROR_NONE) {
1393                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
1394                         _tbm_set_last_result(error2);
1395                         goto fail;
1396                 }
1397         } else {
1398                 size1 = bo1->bufmgr->backend->bo_size(bo1);
1399                 size2 = bo2->bufmgr->backend->bo_size(bo2);
1400         }
1401
1402         if (size1 != size2) {
1403                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
1404                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1405                 goto fail;
1406         }
1407
1408         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1409
1410         temp = bo1->priv;
1411         bo1->priv = bo2->priv;
1412         bo2->priv = temp;
1413
1414         _tbm_bufmgr_mutex_unlock();
1415
1416         return 1;
1417
1418 fail:
1419         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1420         _tbm_bufmgr_mutex_unlock();
1421
1422         return 0;
1423 }
1424
1425 int
1426 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1427                      tbm_data_free data_free_func)
1428 {
1429         tbm_user_data *data;
1430
1431         _tbm_bufmgr_mutex_lock();
1432         _tbm_set_last_result(TBM_ERROR_NONE);
1433
1434         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1435
1436         /* check if the data according to the key exist if so, return false. */
1437         data = user_data_lookup(&bo->user_data_list, key);
1438         if (data) {
1439                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
1440                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1441                 _tbm_bufmgr_mutex_unlock();
1442                 return 0;
1443         }
1444
1445         data = user_data_create(key, data_free_func);
1446         if (!data) {
1447                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
1448                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1449                 _tbm_bufmgr_mutex_unlock();
1450                 return 0;
1451         }
1452
1453         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1454
1455         LIST_ADD(&data->item_link, &bo->user_data_list);
1456
1457         _tbm_bufmgr_mutex_unlock();
1458
1459         return 1;
1460 }
1461
1462 int
1463 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1464 {
1465         tbm_user_data *old_data;
1466
1467         _tbm_bufmgr_mutex_lock();
1468         _tbm_set_last_result(TBM_ERROR_NONE);
1469
1470         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1471
1472         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1473                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1474                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1475                 _tbm_bufmgr_mutex_unlock();
1476                 return 0;
1477         }
1478
1479         old_data = user_data_lookup(&bo->user_data_list, key);
1480         if (!old_data) {
1481                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1482                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1483                 _tbm_bufmgr_mutex_unlock();
1484                 return 0;
1485         }
1486
1487         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1488
1489         user_data_delete(old_data);
1490
1491         _tbm_bufmgr_mutex_unlock();
1492
1493         return 1;
1494 }
1495
1496 int
1497 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1498 {
1499         tbm_user_data *old_data;
1500
1501         _tbm_bufmgr_mutex_lock();
1502         _tbm_set_last_result(TBM_ERROR_NONE);
1503
1504         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1505
1506         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1507                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1508                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1509                 _tbm_bufmgr_mutex_unlock();
1510                 return 0;
1511         }
1512
1513         old_data = user_data_lookup(&bo->user_data_list, key);
1514         if (!old_data) {
1515                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1516                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1517                 _tbm_bufmgr_mutex_unlock();
1518                 return 0;
1519         }
1520
1521         if (old_data->data && old_data->free_func)
1522                 old_data->free_func(old_data->data);
1523         old_data->data = data;
1524
1525         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1526
1527         _tbm_bufmgr_mutex_unlock();
1528
1529         return 1;
1530 }
1531
1532 int
1533 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1534 {
1535         tbm_user_data *old_data;
1536
1537         _tbm_bufmgr_mutex_lock();
1538         _tbm_set_last_result(TBM_ERROR_NONE);
1539
1540         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1541
1542         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1543                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1544                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1545                 _tbm_bufmgr_mutex_unlock();
1546                 return 0;
1547         }
1548
1549         old_data = user_data_lookup(&bo->user_data_list, key);
1550         if (!old_data) {
1551                 *data = NULL;
1552                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1553                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1554                 _tbm_bufmgr_mutex_unlock();
1555                 return 0;
1556         }
1557
1558         *data = old_data->data;
1559
1560         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1561
1562         _tbm_bufmgr_mutex_unlock();
1563
1564         return 1;
1565 }
1566
1567 int
1568 tbm_bo_get_flags(tbm_bo bo)
1569 {
1570         int flags;
1571
1572         _tbm_bufmgr_mutex_lock();
1573
1574         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1575
1576         flags = bo->flags;
1577
1578         TBM_TRACE_BO("bo(%p)\n", bo);
1579
1580         _tbm_bufmgr_mutex_unlock();
1581
1582         return flags;
1583 }
1584
1585 /* LCOV_EXCL_START */
1586 /* internal function */
1587 int
1588 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1589 {
1590         _tbm_bufmgr_mutex_lock();
1591
1592         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1593
1594         bo->surface = surface;
1595
1596         _tbm_bufmgr_mutex_unlock();
1597
1598         return 1;
1599 }
1600
1601 void
1602 _tbm_bo_free(tbm_bo bo)
1603 {
1604         /* destory the user_data_list */
1605         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1606                 tbm_user_data *old_data = NULL, *tmp;
1607
1608                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1609                                 &bo->user_data_list, item_link) {
1610                         TBM_DBG("free user_data\n");
1611                         user_data_delete(old_data);
1612                 }
1613         }
1614
1615         while (bo->lock_cnt > 0) {
1616                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1617                 _bo_unlock(bo);
1618                 bo->lock_cnt--;
1619         }
1620
1621         /* call the bo_free */
1622         if (bo->bufmgr->use_hal_tbm) {
1623                 // call hal_tbm_bo_free when bo is created by tbm_bo_alloc api.
1624                 if (!bo->get_from_hal_surface) {
1625                         bo->get_from_hal_surface = 0;
1626
1627                         hal_tbm_bo_free(bo->bo_data);
1628                         bo->bo_data = NULL;
1629                 }
1630         } else if (bo->bufmgr->backend_module_data) {
1631                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1632                 bo->bo_data = NULL;
1633         } else {
1634                 bo->bufmgr->backend->bo_free(bo);
1635                 bo->priv = NULL;
1636         }
1637
1638         _tbm_bo_deinit(bo);
1639
1640         free(bo);
1641 }
1642 /* LCOV_EXCL_STOP */