surface: move function of allocating for surface to tbm_bo
[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->backend_module_data) {
159                 if (bo->bufmgr->bo_func->bo_lock) {
160                         error = bo->bufmgr->bo_func->bo_lock(bo->bo_data, device, opt);
161                         if (error != TBM_ERROR_NONE) {
162                                 TBM_WRN("fail to lock");
163                                 _tbm_set_last_result(error);
164                                 ret = 0;
165                         }
166                 }
167         } else {
168                 if (bo->bufmgr->backend->bo_lock) {
169                         ret = bo->bufmgr->backend->bo_lock(bo, device, opt);
170                         if (!ret)
171                                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
172                 }
173         }
174
175         return ret;
176 }
177
178 static void
179 _bo_unlock(tbm_bo bo)
180 {
181         tbm_error_e error;
182
183         if (bo->bufmgr->backend_module_data) {
184                 if (bo->bufmgr->bo_func->bo_unlock) {
185                         error = bo->bufmgr->bo_func->bo_unlock(bo->bo_data);
186                         if (error != TBM_ERROR_NONE) {
187                                 TBM_WRN("fail to unlock");
188                                 _tbm_set_last_result(error);
189                         }
190                 }
191         } else {
192                 if (bo->bufmgr->backend->bo_unlock)
193                         bo->bufmgr->backend->bo_unlock(bo);
194         }
195 }
196
197 static int
198 _tbm_bo_lock(tbm_bo bo, int device, int opt)
199 {
200         int old, ret;
201
202         if (!bo)
203                 return 0;
204
205         /* do not try to lock the bo */
206         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
207                 return 1;
208
209         if (bo->lock_cnt < 0) {
210                 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
211                         bo, bo->lock_cnt);
212                 return 0;
213         }
214
215         old = bo->lock_cnt;
216
217         switch (bo->bufmgr->bo_lock_type) {
218         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
219                 if (bo->lock_cnt == 0) {
220                         _tbm_bufmgr_mutex_unlock();
221                         ret = _bo_lock(bo, device, opt);
222                         _tbm_bufmgr_mutex_lock();
223                         if (ret)
224                                 bo->lock_cnt++;
225                 } else
226                         ret = 1;
227                 break;
228         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
229                 _tbm_bufmgr_mutex_unlock();
230                 ret = _bo_lock(bo, device, opt);
231                 _tbm_bufmgr_mutex_lock();
232                 if (ret)
233                         bo->lock_cnt++;
234                 break;
235         default:
236                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
237                                 bo, bo->bufmgr->bo_lock_type);
238                 ret = 0;
239                 break;
240         }
241
242         TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
243
244         return ret;
245 }
246
247 static void
248 _tbm_bo_unlock(tbm_bo bo)
249 {
250         int old;
251
252         /* do not try to unlock the bo */
253         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
254                 return;
255
256         old = bo->lock_cnt;
257
258         switch (bo->bufmgr->bo_lock_type) {
259         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
260                 if (bo->lock_cnt > 0) {
261                         bo->lock_cnt--;
262                         if (bo->lock_cnt == 0)
263                                 _bo_unlock(bo);
264                 }
265                 break;
266         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
267                 if (bo->lock_cnt > 0) {
268                         bo->lock_cnt--;
269                         _bo_unlock(bo);
270                 }
271                 break;
272         default:
273                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
274                                 bo, bo->bufmgr->bo_lock_type);
275                 break;
276         }
277
278         if (bo->lock_cnt < 0)
279                 bo->lock_cnt = 0;
280
281         TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
282 }
283
284 static int
285 _tbm_bo_magic_check(tbm_bo bo)
286 {
287         if (bo->magic != TBM_BO_MAGIC)
288                 return 0;
289
290         return 1;
291 }
292
293 static int
294 _tbm_bo_is_valid(tbm_bo bo)
295 {
296         if (!bo) {
297                 TBM_ERR("error: bo is NULL.\n");
298                 return 0;
299         }
300
301         if (!_tbm_bo_magic_check(bo)) {
302                 TBM_ERR("error: No valid bo(%p).\n", bo);
303                 return 0;
304         }
305
306         return 1;
307 }
308
309 static void
310 _tbm_bo_init(tbm_bufmgr bufmgr, tbm_bo bo, int flags)
311 {
312         bo->bufmgr = bufmgr;
313         bo->flags = flags;
314         bo->magic = TBM_BO_MAGIC;
315         bo->ref_cnt = 1;
316
317         LIST_INITHEAD(&bo->user_data_list);
318
319         bufmgr->bo_cnt++;
320         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
321 }
322
323 static void
324 _tbm_bo_deinit(tbm_bo bo)
325 {
326         bo->magic = 0;
327
328         bo->bufmgr->bo_cnt--;
329         LIST_DEL(&bo->item_link);
330 }
331
332 tbm_bo
333 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
334 {
335         tbm_bo bo;
336         void *bo_priv;
337         tbm_backend_bo_data *bo_data;
338         tbm_error_e error;
339
340         _tbm_bufmgr_mutex_lock();
341         _tbm_set_last_result(TBM_ERROR_NONE);
342
343         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
344         TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
345
346         bo = calloc(1, sizeof(struct _tbm_bo));
347         if (!bo) {
348                 /* LCOV_EXCL_START */
349                 TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n",
350                                 size, _tbm_flag_to_str(flags));
351                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
352                 _tbm_bufmgr_mutex_unlock();
353                 return NULL;
354                 /* LCOV_EXCL_STOP */
355         }
356
357         _tbm_util_check_bo_cnt(bufmgr);
358
359         if (bufmgr->backend_module_data) {
360                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo(bufmgr->bufmgr_data, (unsigned int)size, flags, &error);
361                 if (!bo_data) {
362                         /* LCOV_EXCL_START */
363                         TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n",
364                                         size, _tbm_flag_to_str(flags));
365                         _tbm_set_last_result(error);
366                         free(bo);
367                         _tbm_bufmgr_mutex_unlock();
368                         return NULL;
369                         /* LCOV_EXCL_STOP */
370                 }
371                 bo->bo_data = bo_data;
372         } else {
373                 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
374                 if (!bo_priv) {
375                         /* LCOV_EXCL_START */
376                         TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n",
377                                         size, _tbm_flag_to_str(flags));
378                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
379                         free(bo);
380                         _tbm_bufmgr_mutex_unlock();
381                         return NULL;
382                         /* LCOV_EXCL_STOP */
383                 }
384                 bo->priv = bo_priv;
385         }
386
387         _tbm_bo_init(bufmgr, bo, flags);
388
389         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
390                         _tbm_flag_to_str(bo->flags));
391
392         _tbm_bufmgr_mutex_unlock();
393
394         return bo;
395 }
396
397 /* LCOV_EXCL_START */
398 tbm_bo
399 tbm_bo_alloc_with_format(tbm_bufmgr bufmgr, int format, int bo_idx, int width,
400                                                 int height, tbm_bo_memory_type flags, tbm_error_e *error)
401 {
402         tbm_bo bo;
403         tbm_backend_bo_data *bo_data;
404
405         _tbm_bufmgr_mutex_lock();
406         _tbm_set_last_result(TBM_ERROR_NONE);
407
408         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
409
410         bo = calloc(1, sizeof(struct _tbm_bo));
411         if (!bo) {
412                 TBM_ERR("error: fail to tbm_bo_alloc_with_format fmt(%s) idx(%d) w(%d) h(%d) mem_types(%s)\n",
413                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
414                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
415                 _tbm_bufmgr_mutex_unlock();
416                 return NULL;
417         }
418
419         _tbm_util_check_bo_cnt(bufmgr);
420
421         if (!bufmgr->backend_module_data || !bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
422                 /* LCOV_EXCL_START */
423                 TBM_ERR("error: not supported tbm_bo_alloc_with_format\n");
424                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
425                 free(bo);
426                 _tbm_bufmgr_mutex_unlock();
427                 return NULL;
428                 /* LCOV_EXCL_STOP */
429         }
430
431         bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format(bufmgr->bufmgr_data, format, bo_idx,
432                                                                                                                                 width, height, flags, error);
433         if (!bo_data) {
434                 TBM_ERR("error: fail to tbm_bo_alloc_with_format fmt(%s) idx(%d) w(%d) h(%d) mem_types(%s)\n",
435                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
436                 _tbm_set_last_result(*error);
437                 free(bo);
438                 _tbm_bufmgr_mutex_unlock();
439                 return NULL;
440         }
441
442         bo->bo_data = bo_data;
443         _tbm_bo_init(bufmgr, bo, flags);
444
445         _tbm_bufmgr_mutex_unlock();
446
447         return bo;
448 }
449
450 tbm_bo
451 tbm_bo_alloc_with_tiled_format(tbm_bufmgr bufmgr, int width, int height, int bpp, int format,
452                                                         tbm_bo_memory_type flags, int bo_idx, tbm_error_e *error)
453 {
454         tbm_bo bo;
455         tbm_backend_bo_data *bo_data;
456
457         _tbm_bufmgr_mutex_lock();
458         _tbm_set_last_result(TBM_ERROR_NONE);
459
460         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
461
462         bo = calloc(1, sizeof(struct _tbm_bo));
463         if (!bo) {
464                 TBM_ERR("error: fail to tbm_bo_alloc_with_tiled_format fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
465                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
466                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
467                 _tbm_bufmgr_mutex_unlock();
468                 return NULL;
469         }
470
471         _tbm_util_check_bo_cnt(bufmgr);
472
473         if (!bufmgr->backend_module_data || !bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format) {
474                 TBM_ERR("error: not supported tbm_bo_alloc_with_tiled_format\n");
475                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
476                 free(bo);
477                 _tbm_bufmgr_mutex_unlock();
478                 return NULL;
479         }
480
481         bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format(bufmgr->bufmgr_data, width, height,
482                                                                                                                                         bpp, format, flags, bo_idx, error);
483         if (!bo_data) {
484                 TBM_ERR("error: fail to tbm_bo_alloc_with_tiled_format fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
485                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
486                 _tbm_set_last_result(*error);
487                 free(bo);
488                 _tbm_bufmgr_mutex_unlock();
489                 return NULL;
490         }
491
492         bo->bo_data = bo_data;
493         _tbm_bo_init(bufmgr, bo, flags);
494
495         _tbm_bufmgr_mutex_unlock();
496
497         return bo;
498 }
499
500 tbm_bo
501 tbm_bo_alloc_with_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, int bo_idx)
502 {
503         tbm_bo bo;
504         void *bo_priv;
505
506         _tbm_bufmgr_mutex_lock();
507         _tbm_set_last_result(TBM_ERROR_NONE);
508
509         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
510
511         bo = calloc(1, sizeof(struct _tbm_bo));
512         if (!bo) {
513                 TBM_ERR("error: fail to tbm_bo_alloc_with_surface fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
514                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
515                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
516                 _tbm_bufmgr_mutex_unlock();
517                 return NULL;
518         }
519
520         _tbm_util_check_bo_cnt(bufmgr);
521
522         if (!bufmgr->backend->surface_bo_alloc) {
523                 TBM_ERR("error: not supported tbm_bo_alloc_with_surface\n");
524                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
525                 free(bo);
526                 _tbm_bufmgr_mutex_unlock();
527                 return NULL;
528         }
529
530         bo_priv = bufmgr->backend->surface_bo_alloc(bo, width, height, format, flags, bo_idx);
531         if (!bo_priv) {
532                 TBM_ERR("error: fail to tbm_bo_alloc_with_surface fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
533                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
534                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
535                 free(bo);
536                 _tbm_bufmgr_mutex_unlock();
537                 return NULL;
538         }
539
540         bo->priv = bo_priv;
541         _tbm_bo_init(bufmgr, bo, flags);
542
543         _tbm_bufmgr_mutex_unlock();
544
545         return bo;
546 }
547 /* LCOV_EXCL_STOP */
548
549 tbm_bo
550 tbm_bo_ref(tbm_bo bo)
551 {
552         _tbm_bufmgr_mutex_lock();
553         _tbm_set_last_result(TBM_ERROR_NONE);
554
555         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
556
557         bo->ref_cnt++;
558
559         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
560
561         _tbm_bufmgr_mutex_unlock();
562
563         return bo;
564 }
565
566 void
567 tbm_bo_unref(tbm_bo bo)
568 {
569         _tbm_bufmgr_mutex_lock();
570         _tbm_set_last_result(TBM_ERROR_NONE);
571
572         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
573
574         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
575
576         if (bo->ref_cnt <= 0) {
577                 _tbm_bufmgr_mutex_unlock();
578                 return;
579         }
580
581         bo->ref_cnt--;
582         if (bo->ref_cnt == 0)
583                 _tbm_bo_free(bo);
584
585         _tbm_bufmgr_mutex_unlock();
586 }
587
588 tbm_bo_handle
589 tbm_bo_map(tbm_bo bo, int device, int opt)
590 {
591         tbm_bo_handle bo_handle;
592         tbm_error_e error;
593
594         _tbm_bufmgr_mutex_lock();
595         _tbm_set_last_result(TBM_ERROR_NONE);
596
597         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
598
599         if (!_tbm_bo_lock(bo, device, opt)) {
600                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
601                 _tbm_bufmgr_mutex_unlock();
602                 return (tbm_bo_handle) NULL;
603         }
604
605         if (bo->bufmgr->backend_module_data) {
606                 bo_handle = bo->bufmgr->bo_func->bo_map(bo->bo_data, device, opt, &error);
607                 if (bo_handle.ptr == NULL) {
608                         /* LCOV_EXCL_START */
609                         _tbm_set_last_result(error);
610                         TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
611                         _tbm_bo_unlock(bo);
612                         _tbm_bufmgr_mutex_unlock();
613                         return (tbm_bo_handle) NULL;
614                         /* LCOV_EXCL_STOP */
615                 }
616         } else {
617                 bo_handle = bo->bufmgr->backend->bo_map(bo, device, opt);
618                 if (bo_handle.ptr == NULL) {
619                         /* LCOV_EXCL_START */
620                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
621                         TBM_ERR("error: fail to map bo:%p\n", bo);
622                         _tbm_bo_unlock(bo);
623                         _tbm_bufmgr_mutex_unlock();
624                         return (tbm_bo_handle) NULL;
625                         /* LCOV_EXCL_STOP */
626                 }
627         }
628
629         /* increase the map_count */
630         bo->map_cnt++;
631
632         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
633
634         _tbm_bufmgr_mutex_unlock();
635
636         return bo_handle;
637 }
638
639 int
640 tbm_bo_unmap(tbm_bo bo)
641 {
642         int ret = 1;
643         tbm_error_e error;
644
645         _tbm_bufmgr_mutex_lock();
646         _tbm_set_last_result(TBM_ERROR_NONE);
647
648         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
649         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
650
651         if (bo->bufmgr->backend_module_data) {
652                 error = bo->bufmgr->bo_func->bo_unmap(bo->bo_data);
653                 if (error != TBM_ERROR_NONE) {
654                         /* LCOV_EXCL_START */
655                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
656                         _tbm_set_last_result(error);
657                         ret = 0;
658                         _tbm_bufmgr_mutex_unlock();
659                         return ret;
660                         /* LCOV_EXCL_STOP */
661                 }
662         } else {
663                 ret = bo->bufmgr->backend->bo_unmap(bo);
664                 if (!ret) {
665                         /* LCOV_EXCL_START */
666                         TBM_ERR("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
667                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
668                         _tbm_bufmgr_mutex_unlock();
669                         return ret;
670                         /* LCOV_EXCL_STOP */
671                 }
672         }
673
674         /* decrease the map_count */
675         bo->map_cnt--;
676
677         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
678
679         _tbm_bo_unlock(bo);
680
681         _tbm_bufmgr_mutex_unlock();
682
683         return ret;
684 }
685
686 tbm_bo_handle
687 tbm_bo_get_handle(tbm_bo bo, int device)
688 {
689         tbm_bo_handle bo_handle;
690         tbm_error_e error;
691
692         _tbm_bufmgr_mutex_lock();
693         _tbm_set_last_result(TBM_ERROR_NONE);
694
695         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
696
697         if (bo->bufmgr->backend_module_data) {
698                 bo_handle = bo->bufmgr->bo_func->bo_get_handle(bo->bo_data, device, &error);
699                 if (bo_handle.ptr == NULL) {
700                         /* LCOV_EXCL_START */
701                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
702                         _tbm_set_last_result(error);
703                         _tbm_bufmgr_mutex_unlock();
704                         return (tbm_bo_handle) NULL;
705                         /* LCOV_EXCL_STOP */
706                 }
707         } else {
708                 bo_handle = bo->bufmgr->backend->bo_get_handle(bo, device);
709                 if (bo_handle.ptr == NULL) {
710                         /* LCOV_EXCL_START */
711                         TBM_ERR("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
712                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
713                         _tbm_bufmgr_mutex_unlock();
714                         return (tbm_bo_handle) NULL;
715                         /* LCOV_EXCL_STOP */
716                 }
717         }
718
719         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
720
721         _tbm_bufmgr_mutex_unlock();
722
723         return bo_handle;
724 }
725
726 tbm_key
727 tbm_bo_export(tbm_bo bo)
728 {
729         tbm_key ret;
730         tbm_error_e error;
731
732         _tbm_bufmgr_mutex_lock();
733         _tbm_set_last_result(TBM_ERROR_NONE);
734
735         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
736
737         if (bo->bufmgr->backend_module_data) {
738                 if (!bo->bufmgr->bo_func->bo_export_key) {
739                         /* LCOV_EXCL_START */
740                         _tbm_bufmgr_mutex_unlock();
741                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
742                         return 0;
743                         /* LCOV_EXCL_STOP */
744                 }
745
746                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
747                 if (!ret) {
748                         /* LCOV_EXCL_START */
749                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
750                         _tbm_set_last_result(error);
751                         _tbm_bufmgr_mutex_unlock();
752                         return ret;
753                         /* LCOV_EXCL_STOP */
754                 }
755         } else {
756                 if (!bo->bufmgr->backend->bo_export) {
757                         /* LCOV_EXCL_START */
758                         _tbm_bufmgr_mutex_unlock();
759                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
760                         return 0;
761                         /* LCOV_EXCL_STOP */
762                 }
763
764                 ret = bo->bufmgr->backend->bo_export(bo);
765                 if (!ret) {
766                         /* LCOV_EXCL_START */
767                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
768                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
769                         _tbm_bufmgr_mutex_unlock();
770                         return ret;
771                         /* LCOV_EXCL_STOP */
772                 }
773         }
774
775         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
776
777         _tbm_bufmgr_mutex_unlock();
778
779         return ret;
780 }
781
782 tbm_fd
783 tbm_bo_export_fd(tbm_bo bo)
784 {
785         tbm_fd ret;
786         tbm_error_e error;
787
788         _tbm_bufmgr_mutex_lock();
789         _tbm_set_last_result(TBM_ERROR_NONE);
790
791         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
792
793         if (bo->bufmgr->backend_module_data) {
794                 if (!bo->bufmgr->bo_func->bo_export_fd) {
795                         /* LCOV_EXCL_START */
796                         _tbm_bufmgr_mutex_unlock();
797                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
798                         return -1;
799                         /* LCOV_EXCL_STOP */
800                 }
801
802                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
803                 if (ret < 0) {
804                         /* LCOV_EXCL_START */
805                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
806                         _tbm_set_last_result(error);
807                         _tbm_bufmgr_mutex_unlock();
808                         return ret;
809                         /* LCOV_EXCL_STOP */
810                 }
811         } else {
812                 if (!bo->bufmgr->backend->bo_export_fd) {
813                         /* LCOV_EXCL_START */
814                         _tbm_bufmgr_mutex_unlock();
815                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
816                         return -1;
817                         /* LCOV_EXCL_STOP */
818                 }
819
820                 ret = bo->bufmgr->backend->bo_export_fd(bo);
821                 if (ret < 0) {
822                         /* LCOV_EXCL_START */
823                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
824                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
825                         _tbm_bufmgr_mutex_unlock();
826                         return ret;
827                         /* LCOV_EXCL_STOP */
828                 }
829         }
830
831         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
832
833         _tbm_bufmgr_mutex_unlock();
834
835         return ret;
836 }
837
838 tbm_bo
839 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
840 {
841         tbm_bo bo;
842         tbm_bo bo2 = NULL;
843         void *bo_priv;
844         tbm_error_e error;
845         tbm_backend_bo_data *bo_data;
846         int flags;
847
848         _tbm_bufmgr_mutex_lock();
849         _tbm_set_last_result(TBM_ERROR_NONE);
850
851         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
852
853         if (bufmgr->backend_module_data) {
854                 if (!bufmgr->bufmgr_func->bufmgr_import_key) {
855                         /* LCOV_EXCL_START */
856                         _tbm_bufmgr_mutex_unlock();
857                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
858                         return NULL;
859                         /* LCOV_EXCL_STOP */
860                 }
861         } else {
862                 if (!bufmgr->backend->bo_import) {
863                         /* LCOV_EXCL_START */
864                         _tbm_bufmgr_mutex_unlock();
865                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
866                         return NULL;
867                         /* LCOV_EXCL_STOP */
868                 }
869         }
870
871         _tbm_util_check_bo_cnt(bufmgr);
872
873         bo = calloc(1, sizeof(struct _tbm_bo));
874         if (!bo) {
875                 /* LCOV_EXCL_START */
876                 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
877                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
878                 _tbm_bufmgr_mutex_unlock();
879                 return NULL;
880                 /* LCOV_EXCL_STOP */
881         }
882
883         if (bufmgr->backend_module_data) {
884                 bo_data = bufmgr->bufmgr_func->bufmgr_import_key(bufmgr->bufmgr_data, key, &error);
885                 if (!bo_data) {
886                         /* LCOV_EXCL_START */
887                         TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
888                         _tbm_set_last_result(error);
889                         free(bo);
890                         _tbm_bufmgr_mutex_unlock();
891                         return NULL;
892                         /* LCOV_EXCL_STOP */
893                 }
894
895                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
896                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
897                                 if (bo2->bo_data == bo_data) {
898                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
899                                                         bo2, bo2->ref_cnt, key,
900                                                         _tbm_flag_to_str(bo2->flags));
901                                         bo2->ref_cnt++;
902                                         free(bo);
903                                         _tbm_bufmgr_mutex_unlock();
904                                         return bo2;
905                                 }
906                         }
907                 }
908                 bo->bo_data = bo_data;
909         } else {
910                 bo_priv = bufmgr->backend->bo_import(bo, key);
911                 if (!bo_priv) {
912                         /* LCOV_EXCL_START */
913                         TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
914                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
915                         free(bo);
916                         _tbm_bufmgr_mutex_unlock();
917                         return NULL;
918                         /* LCOV_EXCL_STOP */
919                 }
920
921                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
922                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
923                                 if (bo2->priv == bo_priv) {
924                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
925                                                         bo2, bo2->ref_cnt, key,
926                                                         _tbm_flag_to_str(bo2->flags));
927                                         bo2->ref_cnt++;
928                                         free(bo);
929                                         _tbm_bufmgr_mutex_unlock();
930                                         return bo2;
931                                 }
932                         }
933                 }
934                 bo->priv = bo_priv;
935         }
936
937         if (bufmgr->backend_module_data) {
938                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
939                 if (error != TBM_ERROR_NONE) {
940                         TBM_ERR("fail to get the bo flags(memory_types)");
941                         _tbm_set_last_result(error);
942                         flags = TBM_BO_DEFAULT;
943                 }
944         } else {
945                 if (bufmgr->backend->bo_get_flags)
946                         flags = bufmgr->backend->bo_get_flags(bo);
947                 else
948                         flags = TBM_BO_DEFAULT;
949         }
950
951         _tbm_bo_init(bufmgr, bo, flags);
952
953         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
954                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
955
956         _tbm_bufmgr_mutex_unlock();
957
958         return bo;
959 }
960
961 tbm_bo
962 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
963 {
964         tbm_bo bo;
965         tbm_bo bo2 = NULL;
966         void *bo_priv;
967         tbm_backend_bo_data *bo_data;
968         tbm_error_e error;
969         int flags;
970
971         _tbm_bufmgr_mutex_lock();
972         _tbm_set_last_result(TBM_ERROR_NONE);
973
974         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
975
976         if (bufmgr->backend_module_data) {
977                 if (!bufmgr->bufmgr_func->bufmgr_import_fd) {
978                         /* LCOV_EXCL_START */
979                         _tbm_bufmgr_mutex_unlock();
980                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
981                         return NULL;
982                         /* LCOV_EXCL_STOP */
983                 }
984         } else {
985                 if (!bufmgr->backend->bo_import_fd) {
986                         /* LCOV_EXCL_START */
987                         _tbm_bufmgr_mutex_unlock();
988                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
989                         return NULL;
990                         /* LCOV_EXCL_STOP */
991                 }
992         }
993
994         _tbm_util_check_bo_cnt(bufmgr);
995
996         bo = calloc(1, sizeof(struct _tbm_bo));
997         if (!bo) {
998                 /* LCOV_EXCL_START */
999                 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1000                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1001                 _tbm_bufmgr_mutex_unlock();
1002                 return NULL;
1003                 /* LCOV_EXCL_STOP */
1004         }
1005
1006         if (bufmgr->backend_module_data) {
1007                 bo_data = bufmgr->bufmgr_func->bufmgr_import_fd(bufmgr->bufmgr_data, fd, &error);
1008                 if (!bo_data) {
1009                         /* LCOV_EXCL_START */
1010                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
1011                         _tbm_set_last_result(error);
1012                         free(bo);
1013                         _tbm_bufmgr_mutex_unlock();
1014                         return NULL;
1015                         /* LCOV_EXCL_STOP */
1016                 }
1017
1018                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1019                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1020                                 if (bo2->bo_data == bo_data) {
1021                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1022                                                         bo2, bo2->ref_cnt, fd,
1023                                                         _tbm_flag_to_str(bo2->flags));
1024                                         bo2->ref_cnt++;
1025                                         free(bo);
1026                                         _tbm_bufmgr_mutex_unlock();
1027                                         return bo2;
1028                                 }
1029                         }
1030                 }
1031                 bo->bo_data = bo_data;
1032         } else {
1033                 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1034                 if (!bo_priv) {
1035                         /* LCOV_EXCL_START */
1036                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1037                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1038                         free(bo);
1039                         _tbm_bufmgr_mutex_unlock();
1040                         return NULL;
1041                         /* LCOV_EXCL_STOP */
1042                 }
1043
1044                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1045                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1046                                 if (bo2->priv == bo_priv) {
1047                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1048                                                         bo2, bo2->ref_cnt, fd,
1049                                                         _tbm_flag_to_str(bo2->flags));
1050                                         bo2->ref_cnt++;
1051                                         free(bo);
1052                                         _tbm_bufmgr_mutex_unlock();
1053                                         return bo2;
1054                                 }
1055                         }
1056                 }
1057                 bo->priv = bo_priv;
1058         }
1059
1060         if (bufmgr->backend_module_data) {
1061                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
1062                 if (error != TBM_ERROR_NONE) {
1063                         TBM_ERR("fail to get the bo flags(memory_types)");
1064                         _tbm_set_last_result(error);
1065                         flags = TBM_BO_DEFAULT;
1066                 }
1067         } else {
1068                 if (bufmgr->backend->bo_get_flags)
1069                         flags = bufmgr->backend->bo_get_flags(bo);
1070                 else
1071                         flags = TBM_BO_DEFAULT;
1072         }
1073
1074         _tbm_bo_init(bufmgr, bo, flags);
1075
1076         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
1077                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1078
1079         _tbm_bufmgr_mutex_unlock();
1080
1081         return bo;
1082 }
1083
1084 int
1085 tbm_bo_size(tbm_bo bo)
1086 {
1087         int size;
1088         tbm_error_e error;
1089
1090         _tbm_bufmgr_mutex_lock();
1091         _tbm_set_last_result(TBM_ERROR_NONE);
1092
1093         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1094
1095         if (bo->bufmgr->backend_module_data) {
1096                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
1097                 if (error != TBM_ERROR_NONE) {
1098                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
1099                         _tbm_set_last_result(TBM_ERROR_NONE);
1100                 }
1101         } else
1102                 size = bo->bufmgr->backend->bo_size(bo);
1103
1104         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
1105
1106         _tbm_bufmgr_mutex_unlock();
1107
1108         return size;
1109 }
1110
1111 int
1112 tbm_bo_locked(tbm_bo bo)
1113 {
1114         _tbm_bufmgr_mutex_lock();
1115         _tbm_set_last_result(TBM_ERROR_NONE);
1116
1117         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1118
1119         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
1120                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1121                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1122                 _tbm_bufmgr_mutex_unlock();
1123                 return 0;
1124         }
1125
1126         if (bo->lock_cnt > 0) {
1127                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1128                 _tbm_bufmgr_mutex_unlock();
1129                 return 1;
1130         }
1131
1132         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1133         _tbm_bufmgr_mutex_unlock();
1134
1135         return 0;
1136 }
1137
1138 int
1139 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1140 {
1141         tbm_error_e error1, error2;
1142         int size1 = -1, size2 = -2;
1143         void *temp;
1144
1145         _tbm_bufmgr_mutex_lock();
1146         _tbm_set_last_result(TBM_ERROR_NONE);
1147
1148         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1149         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1150
1151         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1152
1153         if (bo1->bufmgr->backend_module_data) {
1154                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
1155                 if (error1 != TBM_ERROR_NONE) {
1156                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1157                         _tbm_set_last_result(error1);
1158                         goto fail;
1159                 }
1160                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
1161                 if (error2 != TBM_ERROR_NONE) {
1162                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
1163                         _tbm_set_last_result(error2);
1164                         goto fail;
1165                 }
1166         } else {
1167                 size1 = bo1->bufmgr->backend->bo_size(bo1);
1168                 size2 = bo2->bufmgr->backend->bo_size(bo2);
1169         }
1170
1171         if (size1 != size2) {
1172                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
1173                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1174                 goto fail;
1175         }
1176
1177         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1178
1179         temp = bo1->priv;
1180         bo1->priv = bo2->priv;
1181         bo2->priv = temp;
1182
1183         _tbm_bufmgr_mutex_unlock();
1184
1185         return 1;
1186
1187 fail:
1188         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1189         _tbm_bufmgr_mutex_unlock();
1190
1191         return 0;
1192 }
1193
1194 int
1195 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1196                      tbm_data_free data_free_func)
1197 {
1198         tbm_user_data *data;
1199
1200         _tbm_bufmgr_mutex_lock();
1201         _tbm_set_last_result(TBM_ERROR_NONE);
1202
1203         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1204
1205         /* check if the data according to the key exist if so, return false. */
1206         data = user_data_lookup(&bo->user_data_list, key);
1207         if (data) {
1208                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
1209                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1210                 _tbm_bufmgr_mutex_unlock();
1211                 return 0;
1212         }
1213
1214         data = user_data_create(key, data_free_func);
1215         if (!data) {
1216                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
1217                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1218                 _tbm_bufmgr_mutex_unlock();
1219                 return 0;
1220         }
1221
1222         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1223
1224         LIST_ADD(&data->item_link, &bo->user_data_list);
1225
1226         _tbm_bufmgr_mutex_unlock();
1227
1228         return 1;
1229 }
1230
1231 int
1232 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1233 {
1234         tbm_user_data *old_data;
1235
1236         _tbm_bufmgr_mutex_lock();
1237         _tbm_set_last_result(TBM_ERROR_NONE);
1238
1239         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1240
1241         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1242                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1243                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1244                 _tbm_bufmgr_mutex_unlock();
1245                 return 0;
1246         }
1247
1248         old_data = user_data_lookup(&bo->user_data_list, key);
1249         if (!old_data) {
1250                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1251                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1252                 _tbm_bufmgr_mutex_unlock();
1253                 return 0;
1254         }
1255
1256         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1257
1258         user_data_delete(old_data);
1259
1260         _tbm_bufmgr_mutex_unlock();
1261
1262         return 1;
1263 }
1264
1265 int
1266 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1267 {
1268         tbm_user_data *old_data;
1269
1270         _tbm_bufmgr_mutex_lock();
1271         _tbm_set_last_result(TBM_ERROR_NONE);
1272
1273         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1274
1275         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1276                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1277                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1278                 _tbm_bufmgr_mutex_unlock();
1279                 return 0;
1280         }
1281
1282         old_data = user_data_lookup(&bo->user_data_list, key);
1283         if (!old_data) {
1284                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1285                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1286                 _tbm_bufmgr_mutex_unlock();
1287                 return 0;
1288         }
1289
1290         if (old_data->data && old_data->free_func)
1291                 old_data->free_func(old_data->data);
1292         old_data->data = data;
1293
1294         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1295
1296         _tbm_bufmgr_mutex_unlock();
1297
1298         return 1;
1299 }
1300
1301 int
1302 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1303 {
1304         tbm_user_data *old_data;
1305
1306         _tbm_bufmgr_mutex_lock();
1307         _tbm_set_last_result(TBM_ERROR_NONE);
1308
1309         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1310
1311         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1312                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1313                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1314                 _tbm_bufmgr_mutex_unlock();
1315                 return 0;
1316         }
1317
1318         old_data = user_data_lookup(&bo->user_data_list, key);
1319         if (!old_data) {
1320                 *data = NULL;
1321                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1322                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1323                 _tbm_bufmgr_mutex_unlock();
1324                 return 0;
1325         }
1326
1327         *data = old_data->data;
1328
1329         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1330
1331         _tbm_bufmgr_mutex_unlock();
1332
1333         return 1;
1334 }
1335
1336 int
1337 tbm_bo_get_flags(tbm_bo bo)
1338 {
1339         int flags;
1340
1341         _tbm_bufmgr_mutex_lock();
1342
1343         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1344
1345         flags = bo->flags;
1346
1347         TBM_TRACE_BO("bo(%p)\n", bo);
1348
1349         _tbm_bufmgr_mutex_unlock();
1350
1351         return flags;
1352 }
1353
1354 /* LCOV_EXCL_START */
1355 /* internal function */
1356 int
1357 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1358 {
1359         _tbm_bufmgr_mutex_lock();
1360
1361         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1362
1363         bo->surface = surface;
1364
1365         _tbm_bufmgr_mutex_unlock();
1366
1367         return 1;
1368 }
1369
1370 void
1371 _tbm_bo_free(tbm_bo bo)
1372 {
1373         /* destory the user_data_list */
1374         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1375                 tbm_user_data *old_data = NULL, *tmp;
1376
1377                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1378                                 &bo->user_data_list, item_link) {
1379                         TBM_DBG("free user_data\n");
1380                         user_data_delete(old_data);
1381                 }
1382         }
1383
1384         while (bo->lock_cnt > 0) {
1385                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1386                 _bo_unlock(bo);
1387                 bo->lock_cnt--;
1388         }
1389
1390         /* call the bo_free */
1391         if (bo->bufmgr->backend_module_data) {
1392                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1393                 bo->bo_data = NULL;
1394         } else {
1395                 bo->bufmgr->backend->bo_free(bo);
1396                 bo->priv = NULL;
1397         }
1398
1399         _tbm_bo_deinit(bo);
1400
1401         free(bo);
1402 }
1403 /* LCOV_EXCL_STOP */