upload tizen2.0 source
[framework/uifw/xorg/lib/libdrm.git] / slp / drm_slp_bufmgr.c
1 /**************************************************************************
2
3 xserver-xorg-video-sec
4
5 Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 #include "config.h"
32
33 #include <unistd.h>
34 #include <limits.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <dlfcn.h>
41 #include <dirent.h>
42 #include <string.h>
43 #include <errno.h>
44
45 #include "drm_slp_bufmgr.h"
46 #include "list.h"
47
48 #define PREFIX_LIB    "libdrm_slp_"
49 #define SUFFIX_LIB    ".so"
50 #define DEFAULT_LIB  PREFIX_LIB"default"SUFFIX_LIB
51
52 #define NUM_TRY_LOCK    10
53 #define SEM_NAME                "pixmap_1"
54 #define SEM_DEBUG 0
55
56 #define DRM_RETURN_IF_FAIL(cond)          {if (!(cond)) { fprintf (stderr, "[%s] : '%s' failed.\n", __FUNCTION__, #cond); return; }}
57 #define DRM_RETURN_VAL_IF_FAIL(cond, val) {if (!(cond)) { fprintf (stderr, "[%s] : '%s' failed.\n", __FUNCTION__, #cond); return val; }}
58
59 #define MGR_IS_VALID(mgr) (mgr && \
60                                                 mgr->link.next && \
61                                                 mgr->link.next->prev == &mgr->link)
62 #define BO_IS_VALID(bo) (bo && \
63                                             MGR_IS_VALID(bo->bufmgr) && \
64                                             bo->list.next && \
65                                             bo->list.next->prev == &bo->list)
66
67 typedef struct{
68         void* data;
69
70         int is_valid;
71         drm_data_free free_func ;
72 }drm_slp_user_data;
73
74 static struct list_head *gBufMgrs = NULL;
75
76 static int
77 _sem_wait_wrapper(sem_t* sem)
78 {
79         int res = 0;
80         int num_try = NUM_TRY_LOCK;
81
82         do
83         {
84                 res = sem_wait(sem);
85                 num_try--;
86         } while((res == -1) && (errno == EINTR) && (num_try >= 0));
87
88         if(res == -1)
89         {
90                 fprintf(stderr,
91                                 "[libdrm] error %s:%d(sem:%p, num_try:%d) PID:%04d\n",
92                                 __FUNCTION__,
93                                 __LINE__,
94                                 sem,
95                                 num_try,
96                                 getpid());
97                 return 0;
98         }
99 #if SEM_DEBUG
100         else
101         {
102                 fprintf(stderr,
103                                 "[libdrm]   LOCK >> %s:%d(sem:%p, num_try:%d) PID:%04d\n",
104                                 __FUNCTION__,
105                                 __LINE__,
106                                 sem,
107                                 num_try,
108                                 getpid());
109         }
110 #endif
111
112         return 1;
113 }
114
115 static int
116 _sem_post_wrapper(sem_t* sem)
117 {
118         int res = 0;
119         int num_try = NUM_TRY_LOCK;
120
121         do
122         {
123                 res = sem_post(sem);
124                 num_try--;
125
126         } while((res == -1) && (errno == EINTR) && (num_try >= 0));
127
128         if(res == -1)
129         {
130                 fprintf(stderr,
131                                 "[libdrm] error %s:%d(sem:%p, num_try:%d) PID:%04d\n",
132                                 __FUNCTION__,
133                                 __LINE__,
134                                 sem,
135                                 num_try,
136                                 getpid());
137                 return 0;
138         }
139 #if SEM_DEBUG
140         else
141         {
142                 fprintf(stderr,
143                                 "[libdrm] UNLOCK << %s:%d(sem:%p, num_try:%d) PID:%04d\n",
144                                 __FUNCTION__,
145                                 __LINE__,
146                                 sem,
147                                 num_try,
148                                 getpid());
149         }
150 #endif
151
152         return 1;
153 }
154
155 static int
156 _sem_open(drm_slp_bufmgr bufmgr)
157 {
158         bufmgr->semObj.handle = sem_open(SEM_NAME, O_CREAT, 0777, 1);
159         if(bufmgr->semObj.handle == SEM_FAILED)
160         {
161                 fprintf(stderr,
162                                 "[libdrm] error %s:%d(name:%s) PID:%04d\n",
163                                 __FUNCTION__,
164                                 __LINE__,
165                                 SEM_NAME,
166                                 getpid());
167                 bufmgr->semObj.handle = NULL;
168                 return 0;
169         }
170 #if SEM_DEBUG
171         else
172         {
173                 fprintf(stderr,
174                                 "[libdrm] OPEN %s:%d(sem:%p) PID:%04d\n",
175                                 __FUNCTION__,
176                                 __LINE__,
177                                 bufmgr->semObj.handle,
178                                 getpid());
179         }
180 #endif
181
182         bufmgr->semObj.status = STATUS_UNLOCK;
183
184         return 1;
185 }
186
187 static int
188 _sem_close(drm_slp_bufmgr bufmgr)
189 {
190         _sem_wait_wrapper(bufmgr->semObj.handle);
191         sem_unlink(SEM_NAME);
192         return 1;
193 }
194
195 static int
196 _sem_lock(drm_slp_bufmgr bufmgr)
197 {
198         if(bufmgr->semObj.status != STATUS_UNLOCK) return 0;
199
200         if(!_sem_wait_wrapper(bufmgr->semObj.handle)) return 0;
201         bufmgr->semObj.status = STATUS_LOCK;
202         return 1;
203 }
204
205 static int
206 _sem_unlock(drm_slp_bufmgr bufmgr)
207 {
208         if(bufmgr->semObj.status != STATUS_LOCK) return 0;
209
210         _sem_post_wrapper(bufmgr->semObj.handle);
211         bufmgr->semObj.status = STATUS_UNLOCK;
212         return 1;
213 }
214
215 static drm_slp_bufmgr
216 _load_bufmgr(int fd, const char *file, void *arg)
217 {
218         char path[PATH_MAX] = {0,};
219         drm_slp_bufmgr bufmgr = NULL;
220         int (*bufmgr_init)(drm_slp_bufmgr bufmgr, int fd, void *arg);
221         void *module;
222
223         snprintf(path, sizeof(path), BUFMGR_DIR "/%s", file);
224
225         module = dlopen(path, RTLD_LAZY);
226         if (!module) {
227                 fprintf(stderr,
228                         "[libdrm] failed to load module: %s(%s)\n",
229                         dlerror(), file);
230                 return NULL;
231         }
232
233         bufmgr_init = dlsym(module, "init_slp_bufmgr");
234         if (!bufmgr_init) {
235                 fprintf(stderr,
236                         "[libdrm] failed to lookup init function: %s(%s)\n",
237                         dlerror(), file);
238                 return NULL;
239         }
240
241         bufmgr = calloc(sizeof(struct _drm_slp_bufmgr), 1);
242         if(!bufmgr)
243         {
244                 return NULL;
245         }
246
247         if(!bufmgr_init(bufmgr, fd, arg))
248         {
249                 fprintf(stderr,"[libdrm] Fail to init module(%s)\n", file);
250                 free(bufmgr);
251                 bufmgr = NULL;
252                 return NULL;
253         }
254
255         fprintf(stderr,"[libdrm] Success to load module(%s)\n", file);
256
257         return bufmgr;
258 }
259
260 drm_slp_bufmgr
261 drm_slp_bufmgr_init(int fd, void *arg)
262 {
263     drm_slp_bufmgr bufmgr = NULL;
264     const char *p = NULL;
265
266     if (fd < 0)
267         return NULL;
268
269     if(gBufMgrs == NULL)
270     {
271         gBufMgrs = malloc(sizeof(struct list_head));
272         LIST_INITHEAD(gBufMgrs);
273     }
274     else
275     {
276         LIST_FOR_EACH_ENTRY(bufmgr, gBufMgrs, link)
277         {
278             if(bufmgr->drm_fd == fd)
279             {
280                 bufmgr->ref_count++;
281                 fprintf(stderr, "[libdrm] bufmgr ref: fd=%d, ref_count:%d\n", fd, bufmgr->ref_count);
282                 return bufmgr;
283             }
284         }
285         bufmgr = NULL;
286     }
287     fprintf(stderr, "[libdrm] bufmgr init: fd=%d\n", fd);
288
289     p = getenv ("SLP_BUFMGR_MODULE");
290     if (p)
291     {
292         char file[PATH_MAX] = {0,};
293         snprintf(file, sizeof(file), PREFIX_LIB"%s"SUFFIX_LIB, p);
294         bufmgr = _load_bufmgr (fd, file, arg);
295     }
296
297     if (!bufmgr)
298         bufmgr = _load_bufmgr (fd, DEFAULT_LIB, arg);
299
300     if (!bufmgr)
301     {
302         struct dirent **namelist;
303         int found = 0;
304         int n;
305
306         n = scandir(BUFMGR_DIR, &namelist, 0, alphasort);
307         if (n < 0)
308             fprintf(stderr,"[libdrm] no files : %s\n", BUFMGR_DIR);
309         else
310         {
311             while(n--)
312             {
313                 if (!found && strstr (namelist[n]->d_name, PREFIX_LIB))
314                 {
315                     char *p = strstr (namelist[n]->d_name, SUFFIX_LIB);
316                     if (!strcmp (p, SUFFIX_LIB))
317                     {
318                         bufmgr = _load_bufmgr (fd, namelist[n]->d_name, arg);
319                         if (bufmgr)
320                             found = 1;
321                     }
322                 }
323                 free(namelist[n]);
324             }
325             free(namelist);
326         }
327     }
328
329     if (!bufmgr)
330     {
331         fprintf(stderr,"[libdrm] backend is NULL.\n");
332         return NULL;
333     }
334
335     if (pthread_mutex_init(&bufmgr->lock, NULL) != 0)
336     {
337         bufmgr->bufmgr_destroy(bufmgr);
338         free(bufmgr);
339         return NULL;
340     }
341
342     bufmgr->ref_count = 1;
343     bufmgr->drm_fd = fd;
344
345     LIST_INITHEAD(&bufmgr->bos);
346     LIST_ADD(&bufmgr->link, gBufMgrs);
347
348     return bufmgr;
349 }
350
351 void
352 drm_slp_bufmgr_destroy(drm_slp_bufmgr bufmgr)
353 {
354     DRM_RETURN_IF_FAIL(MGR_IS_VALID(bufmgr));
355
356     fprintf(stderr, "[DRM] bufmgr destroy: bufmgr:%p, drm_fd:%d\n",
357                 bufmgr, bufmgr->drm_fd);
358
359     /*Check and Free bos*/
360     if(!LIST_IS_EMPTY(&bufmgr->bos))
361     {
362         drm_slp_bo bo, tmp;
363
364         LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bos,  list)
365         {
366             fprintf(stderr, "[libdrm] Un-freed bo(%p, ref:%d) \n", bo, bo->ref_cnt);
367             bo->ref_cnt = 1;
368             drm_slp_bo_unref(bo);
369         }
370     }
371
372     LIST_DEL(&bufmgr->link);
373     bufmgr->bufmgr_destroy(bufmgr);
374
375     if(bufmgr->semObj.isOpened)
376     {
377         _sem_close(bufmgr);
378     }
379
380     pthread_mutex_destroy(&bufmgr->lock);
381     free(bufmgr);
382 }
383
384 int
385 drm_slp_bufmgr_lock(drm_slp_bufmgr bufmgr)
386 {
387     DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), 0);
388
389     pthread_mutex_lock(&bufmgr->lock);
390
391     if(bufmgr->bufmgr_lock)
392     {
393         int ret;
394         ret = bufmgr->bufmgr_lock(bufmgr);
395         pthread_mutex_unlock(&bufmgr->lock);
396         return ret;
397     }
398
399     if(!bufmgr->semObj.isOpened)
400     {
401         if(_sem_open(bufmgr) != 1)
402         {
403             pthread_mutex_unlock(&bufmgr->lock);
404             return 0;
405         }
406         bufmgr->semObj.isOpened = 1;
407     }
408
409     if(_sem_lock(bufmgr) != 1)
410     {
411         pthread_mutex_unlock(&bufmgr->lock);
412         return 0;
413     }
414
415     pthread_mutex_unlock(&bufmgr->lock);
416
417     return 1;
418 }
419
420 int
421 drm_slp_bufmgr_unlock(drm_slp_bufmgr bufmgr)
422 {
423     DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), 0);
424
425     pthread_mutex_lock(&bufmgr->lock);
426
427     if(bufmgr->bufmgr_unlock)
428     {
429         int ret;
430         ret = bufmgr->bufmgr_unlock(bufmgr);
431         pthread_mutex_unlock(&bufmgr->lock);
432         return ret;
433     }
434
435     if(_sem_unlock(bufmgr) != 1)
436     {
437         pthread_mutex_unlock(&bufmgr->lock);
438         return 0;
439     }
440
441     pthread_mutex_unlock(&bufmgr->lock);
442
443     return 1;
444 }
445
446 int
447 drm_slp_bufmgr_cache_flush(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags)
448 {
449     int ret;
450
451     DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr) || BO_IS_VALID(bo), 0);
452
453     if (!bo)
454         flags |= DRM_SLP_CACHE_ALL;
455
456     if (bo)
457     {
458         DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
459
460         if(!bo->bufmgr)
461             return 0;
462
463         pthread_mutex_lock(&bo->bufmgr->lock);
464         ret = bo->bufmgr->bufmgr_cache_flush(bufmgr, bo, flags);
465         pthread_mutex_unlock(&bo->bufmgr->lock);
466     }
467     else
468     {
469         pthread_mutex_lock(&bufmgr->lock);
470         ret = bufmgr->bufmgr_cache_flush(bufmgr, NULL, flags);
471         pthread_mutex_unlock(&bufmgr->lock);
472     }
473
474     return ret;
475 }
476
477 int
478 drm_slp_bo_size(drm_slp_bo bo)
479 {
480     int size;
481     drm_slp_bufmgr bufmgr;
482
483     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
484
485     bufmgr = bo->bufmgr;
486
487     pthread_mutex_lock(&bufmgr->lock);
488     size = bo->bufmgr->bo_size(bo);
489     pthread_mutex_unlock(&bufmgr->lock);
490
491     return size;
492 }
493
494 drm_slp_bo
495 drm_slp_bo_ref(drm_slp_bo bo)
496 {
497     drm_slp_bufmgr bufmgr;
498
499     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), NULL);
500
501     bufmgr = bo->bufmgr;
502
503     pthread_mutex_lock(&bufmgr->lock);
504
505     bo->ref_cnt++;
506
507     pthread_mutex_unlock(&bufmgr->lock);
508
509     return bo;
510 }
511
512 void
513 drm_slp_bo_unref(drm_slp_bo bo)
514 {
515     drm_slp_bufmgr bufmgr;
516
517     DRM_RETURN_IF_FAIL(BO_IS_VALID(bo));
518
519     bufmgr = bo->bufmgr;
520
521     if(0 >= bo->ref_cnt)
522         return;
523
524     pthread_mutex_lock(&bufmgr->lock);
525
526     bo->ref_cnt--;
527     if(bo->ref_cnt == 0)
528     {
529         if(bo->user_data)
530         {
531             void* rd;
532             drm_slp_user_data* old_data;
533             unsigned long key;
534
535             while(1==drmSLFirst(bo->user_data, &key, &rd))
536             {
537                 old_data = (drm_slp_user_data*)rd;
538
539                 if(old_data->is_valid && old_data->free_func)
540                 {
541                     if(old_data->data)
542                         old_data->free_func(old_data->data);
543                     old_data->data = NULL;
544                     free(old_data);
545                 }
546                 drmSLDelete(bo->user_data, key);
547             }
548
549             drmSLDestroy(bo->user_data);
550             bo->user_data = (void*)0;
551         }
552
553         LIST_DEL(&bo->list);
554         bufmgr->bo_free(bo);
555
556         free(bo);
557     }
558
559     pthread_mutex_unlock(&bufmgr->lock);
560 }
561
562 drm_slp_bo
563 drm_slp_bo_alloc(drm_slp_bufmgr bufmgr, const char * name, int size, int flags)
564 {
565     drm_slp_bo bo=NULL;
566
567     DRM_RETURN_VAL_IF_FAIL( MGR_IS_VALID(bufmgr) && (size > 0), NULL);
568
569     bo = calloc(sizeof(struct _drm_slp_bo), 1);
570     if(!bo)
571         return NULL;
572
573     bo->bufmgr = bufmgr;
574
575     pthread_mutex_lock(&bufmgr->lock);
576     if(!bufmgr->bo_alloc(bo, name, size, flags))
577     {
578         free(bo);
579         pthread_mutex_unlock(&bufmgr->lock);
580         return NULL;
581     }
582     bo->ref_cnt = 1;
583     LIST_ADD(&bo->list, &bufmgr->bos);
584     pthread_mutex_unlock(&bufmgr->lock);
585
586     return bo;
587 }
588
589 drm_slp_bo
590 drm_slp_bo_attach(drm_slp_bufmgr bufmgr,
591                              const char*    name,
592                              int type,
593                              int size,
594                              unsigned int handle)
595 {
596     drm_slp_bo bo;
597
598     DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), NULL);
599
600     bo = calloc(sizeof(struct _drm_slp_bo), 1);
601     if(!bo)
602         return NULL;
603
604     bo->bufmgr = bufmgr;
605
606     pthread_mutex_lock(&bufmgr->lock);
607     if(!bufmgr->bo_attach(bo, name, type, size, handle))
608     {
609         free(bo);
610         pthread_mutex_unlock(&bufmgr->lock);
611         return NULL;
612     }
613     bo->ref_cnt = 1;
614     LIST_ADD(&bo->list, &bufmgr->bos);
615     pthread_mutex_unlock(&bufmgr->lock);
616
617     return bo;
618 }
619
620 drm_slp_bo
621 drm_slp_bo_import(drm_slp_bufmgr bufmgr, unsigned int key)
622 {
623     drm_slp_bo bo;
624
625     DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), NULL);
626
627     bo = calloc(sizeof(struct _drm_slp_bo), 1);
628     if(!bo)
629         return NULL;
630
631     bo->bufmgr = bufmgr;
632
633     pthread_mutex_lock(&bufmgr->lock);
634     if(!bufmgr->bo_import(bo, key))
635     {
636         free(bo);
637         pthread_mutex_unlock(&bufmgr->lock);
638         return NULL;
639     }
640     bo->ref_cnt = 1;
641     LIST_ADD(&bo->list, &bufmgr->bos);
642     pthread_mutex_unlock(&bufmgr->lock);
643
644     return bo;
645 }
646
647 unsigned int
648 drm_slp_bo_export(drm_slp_bo bo)
649 {
650     int ret;
651
652     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
653
654     pthread_mutex_lock(&bo->bufmgr->lock);
655     ret = bo->bufmgr->bo_export(bo);
656     pthread_mutex_unlock(&bo->bufmgr->lock);
657
658     return ret;
659 }
660
661 unsigned int
662 drm_slp_bo_get_handle(drm_slp_bo bo, int device)
663 {
664     unsigned int ret;
665
666     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
667
668     pthread_mutex_lock(&bo->bufmgr->lock);
669     ret = bo->bufmgr->bo_get_handle(bo, device);
670     pthread_mutex_unlock(&bo->bufmgr->lock);
671
672     return ret;
673 }
674
675 unsigned int
676 drm_slp_bo_map(drm_slp_bo bo, int device, int opt)
677 {
678     unsigned int ret;
679
680     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
681
682     pthread_mutex_lock(&bo->bufmgr->lock);
683     if(bo->bufmgr->bo_lock)
684     {
685         bo->bufmgr->bo_lock(bo, 0, (void*)0);
686     }
687
688     ret = bo->bufmgr->bo_map(bo, device, opt);
689     pthread_mutex_unlock(&bo->bufmgr->lock);
690
691     return ret;
692 }
693
694 int
695 drm_slp_bo_unmap(drm_slp_bo bo, int device)
696 {
697     int ret;
698
699     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
700
701     pthread_mutex_lock(&bo->bufmgr->lock);
702     ret = bo->bufmgr->bo_unmap(bo, device);
703
704     if(bo->bufmgr->bo_unlock)
705     {
706         bo->bufmgr->bo_unlock(bo);
707     }
708     pthread_mutex_unlock(&bo->bufmgr->lock);
709
710     return 0;
711 }
712
713 int
714 drm_slp_bo_swap(drm_slp_bo bo1, drm_slp_bo bo2)
715 {
716     void* temp;
717
718     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo1), 0);
719     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo2), 0);
720
721     if(bo1->bufmgr->bo_size(bo1) != bo2->bufmgr->bo_size(bo2))
722         return 0;
723
724     pthread_mutex_lock(&bo1->bufmgr->lock);
725     temp = bo1->priv;
726     bo1->priv = bo2->priv;
727     bo2->priv = temp;
728     pthread_mutex_unlock(&bo1->bufmgr->lock);
729
730     return 1;
731 }
732
733 int
734 drm_slp_bo_add_user_data(drm_slp_bo bo, unsigned long key, drm_data_free data_free_func)
735 {
736     int ret;
737     drm_slp_user_data* data;
738
739     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
740
741     if(!bo->user_data)
742         bo->user_data = drmSLCreate();
743
744     data = calloc(1, sizeof(drm_slp_user_data));
745     if(!data)
746         return 0;
747
748     data->free_func = data_free_func;
749     data->data = (void*)0;
750     data->is_valid = 0;
751
752     ret = drmSLInsert(bo->user_data, key, data);
753     if(ret == 1) /* Already in list */
754     {
755         free(data);
756         return 0;
757     }
758
759     return 1;
760 }
761
762 int
763 drm_slp_bo_set_user_data(drm_slp_bo bo, unsigned long key, void* data)
764 {
765     void *rd;
766     drm_slp_user_data* old_data;
767
768     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
769
770     if(!bo->user_data)
771         return 0;
772
773     if(drmSLLookup(bo->user_data, key, &rd))
774         return 0;
775
776     old_data = (drm_slp_user_data*)rd;
777     if (!old_data)
778         return 0;
779
780     if(old_data->is_valid)
781     {
782         if(old_data->free_func)
783         {
784             if(old_data->data)
785                 old_data->free_func(old_data->data);
786                 old_data->data = NULL;
787         }
788     }
789     else
790         old_data->is_valid = 1;
791
792     old_data->data = data;
793
794     return 1;
795 }
796
797 int
798 drm_slp_bo_get_user_data(drm_slp_bo bo, unsigned long key, void** data)
799 {
800     void *rd;
801     drm_slp_user_data* old_data;
802
803     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo) && data && bo->user_data, 0);
804
805     if(drmSLLookup(bo->user_data, key, &rd))
806     {
807         *data = NULL;
808         return 0;
809     }
810
811     old_data = (drm_slp_user_data*)rd;
812     if (!old_data)
813     {
814         *data = NULL;
815         return 0;
816     }
817
818     *data = old_data->data;
819
820     return 1;
821 }
822
823 int
824 drm_slp_bo_delete_user_data(drm_slp_bo bo, unsigned long key)
825 {
826     void *rd;
827     drm_slp_user_data* old_data=(void*)0;
828
829     DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo) && bo->user_data, 0);
830
831     if(drmSLLookup(bo->user_data, key, &rd))
832         return 0;
833
834     old_data = (drm_slp_user_data*)rd;
835     if (!old_data)
836         return 0;
837
838     if(old_data->is_valid && old_data->free_func)
839     {
840         if(old_data->data)
841             old_data->free_func(old_data->data);
842         free(old_data);
843     }
844     drmSLDelete(bo->user_data, key);
845
846     return 1;
847 }