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