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