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