1 /**************************************************************************
5 Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
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:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
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.
29 **************************************************************************/
37 #include <sys/types.h>
45 #include "drm_slp_bufmgr.h"
48 #define PREFIX_LIB "libdrm_slp_"
49 #define SUFFIX_LIB ".so"
50 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
52 #define NUM_TRY_LOCK 10
53 #define SEM_NAME "pixmap_1"
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; }}
59 #define MGR_IS_VALID(mgr) (mgr && \
61 mgr->link.next->prev == &mgr->link)
62 #define BO_IS_VALID(bo) (bo && \
63 MGR_IS_VALID(bo->bufmgr) && \
65 bo->list.next->prev == &bo->list)
71 drm_data_free free_func ;
74 static struct list_head *gBufMgrs = NULL;
77 _sem_wait_wrapper(sem_t* sem)
80 int num_try = NUM_TRY_LOCK;
86 } while((res == -1) && (errno == EINTR) && (num_try >= 0));
91 "[libdrm] error %s:%d(sem:%p, num_try:%d) PID:%04d\n",
103 "[libdrm] LOCK >> %s:%d(sem:%p, num_try:%d) PID:%04d\n",
116 _sem_post_wrapper(sem_t* sem)
119 int num_try = NUM_TRY_LOCK;
126 } while((res == -1) && (errno == EINTR) && (num_try >= 0));
131 "[libdrm] error %s:%d(sem:%p, num_try:%d) PID:%04d\n",
143 "[libdrm] UNLOCK << %s:%d(sem:%p, num_try:%d) PID:%04d\n",
156 _sem_open(drm_slp_bufmgr bufmgr)
158 bufmgr->semObj.handle = sem_open(SEM_NAME, O_CREAT, 0777, 1);
159 if(bufmgr->semObj.handle == SEM_FAILED)
162 "[libdrm] error %s:%d(name:%s) PID:%04d\n",
167 bufmgr->semObj.handle = NULL;
174 "[libdrm] OPEN %s:%d(sem:%p) PID:%04d\n",
177 bufmgr->semObj.handle,
182 bufmgr->semObj.status = STATUS_UNLOCK;
188 _sem_close(drm_slp_bufmgr bufmgr)
190 _sem_wait_wrapper(bufmgr->semObj.handle);
191 sem_unlink(SEM_NAME);
196 _sem_lock(drm_slp_bufmgr bufmgr)
198 if(bufmgr->semObj.status != STATUS_UNLOCK) return 0;
200 if(!_sem_wait_wrapper(bufmgr->semObj.handle)) return 0;
201 bufmgr->semObj.status = STATUS_LOCK;
206 _sem_unlock(drm_slp_bufmgr bufmgr)
208 if(bufmgr->semObj.status != STATUS_LOCK) return 0;
210 _sem_post_wrapper(bufmgr->semObj.handle);
211 bufmgr->semObj.status = STATUS_UNLOCK;
215 static drm_slp_bufmgr
216 _load_bufmgr(int fd, const char *file, void *arg)
218 char path[PATH_MAX] = {0,};
219 drm_slp_bufmgr bufmgr = NULL;
220 int (*bufmgr_init)(drm_slp_bufmgr bufmgr, int fd, void *arg);
223 snprintf(path, sizeof(path), BUFMGR_DIR "/%s", file);
225 module = dlopen(path, RTLD_LAZY);
228 "[libdrm] failed to load module: %s(%s)\n",
233 bufmgr_init = dlsym(module, "init_slp_bufmgr");
236 "[libdrm] failed to lookup init function: %s(%s)\n",
241 bufmgr = calloc(sizeof(struct _drm_slp_bufmgr), 1);
247 if(!bufmgr_init(bufmgr, fd, arg))
249 fprintf(stderr,"[libdrm] Fail to init module(%s)\n", file);
255 fprintf(stderr,"[libdrm] Success to load module(%s)\n", file);
261 drm_slp_bufmgr_init(int fd, void *arg)
263 drm_slp_bufmgr bufmgr = NULL;
264 const char *p = NULL;
271 gBufMgrs = malloc(sizeof(struct list_head));
272 LIST_INITHEAD(gBufMgrs);
276 LIST_FOR_EACH_ENTRY(bufmgr, gBufMgrs, link)
278 if(bufmgr->drm_fd == fd)
281 fprintf(stderr, "[libdrm] bufmgr ref: fd=%d, ref_count:%d\n", fd, bufmgr->ref_count);
287 fprintf(stderr, "[libdrm] bufmgr init: fd=%d\n", fd);
289 p = getenv ("SLP_BUFMGR_MODULE");
292 char file[PATH_MAX] = {0,};
293 snprintf(file, sizeof(file), PREFIX_LIB"%s"SUFFIX_LIB, p);
294 bufmgr = _load_bufmgr (fd, file, arg);
298 bufmgr = _load_bufmgr (fd, DEFAULT_LIB, arg);
302 struct dirent **namelist;
306 n = scandir(BUFMGR_DIR, &namelist, 0, alphasort);
308 fprintf(stderr,"[libdrm] no files : %s\n", BUFMGR_DIR);
313 if (!found && strstr (namelist[n]->d_name, PREFIX_LIB))
315 char *p = strstr (namelist[n]->d_name, SUFFIX_LIB);
316 if (!strcmp (p, SUFFIX_LIB))
318 bufmgr = _load_bufmgr (fd, namelist[n]->d_name, arg);
331 fprintf(stderr,"[libdrm] backend is NULL.\n");
335 if (pthread_mutex_init(&bufmgr->lock, NULL) != 0)
337 bufmgr->bufmgr_destroy(bufmgr);
342 bufmgr->ref_count = 1;
345 LIST_INITHEAD(&bufmgr->bos);
346 LIST_ADD(&bufmgr->link, gBufMgrs);
352 drm_slp_bufmgr_destroy(drm_slp_bufmgr bufmgr)
354 DRM_RETURN_IF_FAIL(MGR_IS_VALID(bufmgr));
356 fprintf(stderr, "[DRM] bufmgr destroy: bufmgr:%p, drm_fd:%d\n",
357 bufmgr, bufmgr->drm_fd);
359 /*Check and Free bos*/
360 if(!LIST_IS_EMPTY(&bufmgr->bos))
364 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bos, list)
366 fprintf(stderr, "[libdrm] Un-freed bo(%p, ref:%d) \n", bo, bo->ref_cnt);
368 drm_slp_bo_unref(bo);
372 LIST_DEL(&bufmgr->link);
373 bufmgr->bufmgr_destroy(bufmgr);
375 if(bufmgr->semObj.isOpened)
380 pthread_mutex_destroy(&bufmgr->lock);
385 drm_slp_bufmgr_lock(drm_slp_bufmgr bufmgr)
387 DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), 0);
389 pthread_mutex_lock(&bufmgr->lock);
391 if(bufmgr->bufmgr_lock)
394 ret = bufmgr->bufmgr_lock(bufmgr);
395 pthread_mutex_unlock(&bufmgr->lock);
399 if(!bufmgr->semObj.isOpened)
401 if(_sem_open(bufmgr) != 1)
403 pthread_mutex_unlock(&bufmgr->lock);
406 bufmgr->semObj.isOpened = 1;
409 if(_sem_lock(bufmgr) != 1)
411 pthread_mutex_unlock(&bufmgr->lock);
415 pthread_mutex_unlock(&bufmgr->lock);
421 drm_slp_bufmgr_unlock(drm_slp_bufmgr bufmgr)
423 DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), 0);
425 pthread_mutex_lock(&bufmgr->lock);
427 if(bufmgr->bufmgr_unlock)
430 ret = bufmgr->bufmgr_unlock(bufmgr);
431 pthread_mutex_unlock(&bufmgr->lock);
435 if(_sem_unlock(bufmgr) != 1)
437 pthread_mutex_unlock(&bufmgr->lock);
441 pthread_mutex_unlock(&bufmgr->lock);
447 drm_slp_bufmgr_cache_flush(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags)
451 DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr) || BO_IS_VALID(bo), 0);
454 flags |= DRM_SLP_CACHE_ALL;
458 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
463 pthread_mutex_lock(&bo->bufmgr->lock);
464 ret = bo->bufmgr->bufmgr_cache_flush(bufmgr, bo, flags);
465 pthread_mutex_unlock(&bo->bufmgr->lock);
469 pthread_mutex_lock(&bufmgr->lock);
470 ret = bufmgr->bufmgr_cache_flush(bufmgr, NULL, flags);
471 pthread_mutex_unlock(&bufmgr->lock);
478 drm_slp_bo_size(drm_slp_bo bo)
481 drm_slp_bufmgr bufmgr;
483 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
487 pthread_mutex_lock(&bufmgr->lock);
488 size = bo->bufmgr->bo_size(bo);
489 pthread_mutex_unlock(&bufmgr->lock);
495 drm_slp_bo_ref(drm_slp_bo bo)
497 drm_slp_bufmgr bufmgr;
499 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), NULL);
503 pthread_mutex_lock(&bufmgr->lock);
507 pthread_mutex_unlock(&bufmgr->lock);
513 drm_slp_bo_unref(drm_slp_bo bo)
515 drm_slp_bufmgr bufmgr;
517 DRM_RETURN_IF_FAIL(BO_IS_VALID(bo));
524 pthread_mutex_lock(&bufmgr->lock);
532 drm_slp_user_data* old_data;
535 while(1==drmSLFirst(bo->user_data, &key, &rd))
537 old_data = (drm_slp_user_data*)rd;
539 if(old_data->is_valid && old_data->free_func)
542 old_data->free_func(old_data->data);
543 old_data->data = NULL;
546 drmSLDelete(bo->user_data, key);
549 drmSLDestroy(bo->user_data);
550 bo->user_data = (void*)0;
559 pthread_mutex_unlock(&bufmgr->lock);
563 drm_slp_bo_alloc(drm_slp_bufmgr bufmgr, const char * name, int size, int flags)
567 DRM_RETURN_VAL_IF_FAIL( MGR_IS_VALID(bufmgr) && (size > 0), NULL);
569 bo = calloc(sizeof(struct _drm_slp_bo), 1);
575 pthread_mutex_lock(&bufmgr->lock);
576 if(!bufmgr->bo_alloc(bo, name, size, flags))
579 pthread_mutex_unlock(&bufmgr->lock);
583 LIST_ADD(&bo->list, &bufmgr->bos);
584 pthread_mutex_unlock(&bufmgr->lock);
590 drm_slp_bo_attach(drm_slp_bufmgr bufmgr,
598 DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), NULL);
600 bo = calloc(sizeof(struct _drm_slp_bo), 1);
606 pthread_mutex_lock(&bufmgr->lock);
607 if(!bufmgr->bo_attach(bo, name, type, size, handle))
610 pthread_mutex_unlock(&bufmgr->lock);
614 LIST_ADD(&bo->list, &bufmgr->bos);
615 pthread_mutex_unlock(&bufmgr->lock);
621 drm_slp_bo_import(drm_slp_bufmgr bufmgr, unsigned int key)
625 DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), NULL);
627 bo = calloc(sizeof(struct _drm_slp_bo), 1);
633 pthread_mutex_lock(&bufmgr->lock);
634 if(!bufmgr->bo_import(bo, key))
637 pthread_mutex_unlock(&bufmgr->lock);
641 LIST_ADD(&bo->list, &bufmgr->bos);
642 pthread_mutex_unlock(&bufmgr->lock);
648 drm_slp_bo_export(drm_slp_bo bo)
652 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
654 pthread_mutex_lock(&bo->bufmgr->lock);
655 ret = bo->bufmgr->bo_export(bo);
656 pthread_mutex_unlock(&bo->bufmgr->lock);
662 drm_slp_bo_get_handle(drm_slp_bo bo, int device)
666 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
668 pthread_mutex_lock(&bo->bufmgr->lock);
669 ret = bo->bufmgr->bo_get_handle(bo, device);
670 pthread_mutex_unlock(&bo->bufmgr->lock);
676 drm_slp_bo_map(drm_slp_bo bo, int device, int opt)
680 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
682 pthread_mutex_lock(&bo->bufmgr->lock);
683 if(bo->bufmgr->bo_lock)
685 bo->bufmgr->bo_lock(bo, 0, (void*)0);
688 ret = bo->bufmgr->bo_map(bo, device, opt);
689 pthread_mutex_unlock(&bo->bufmgr->lock);
695 drm_slp_bo_unmap(drm_slp_bo bo, int device)
699 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
701 pthread_mutex_lock(&bo->bufmgr->lock);
702 ret = bo->bufmgr->bo_unmap(bo, device);
704 if(bo->bufmgr->bo_unlock)
706 bo->bufmgr->bo_unlock(bo);
708 pthread_mutex_unlock(&bo->bufmgr->lock);
714 drm_slp_bo_swap(drm_slp_bo bo1, drm_slp_bo bo2)
718 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo1), 0);
719 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo2), 0);
721 if(bo1->bufmgr->bo_size(bo1) != bo2->bufmgr->bo_size(bo2))
724 pthread_mutex_lock(&bo1->bufmgr->lock);
726 bo1->priv = bo2->priv;
728 pthread_mutex_unlock(&bo1->bufmgr->lock);
734 drm_slp_bo_add_user_data(drm_slp_bo bo, unsigned long key, drm_data_free data_free_func)
737 drm_slp_user_data* data;
739 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
742 bo->user_data = drmSLCreate();
744 data = calloc(1, sizeof(drm_slp_user_data));
748 data->free_func = data_free_func;
749 data->data = (void*)0;
752 ret = drmSLInsert(bo->user_data, key, data);
753 if(ret == 1) /* Already in list */
763 drm_slp_bo_set_user_data(drm_slp_bo bo, unsigned long key, void* data)
766 drm_slp_user_data* old_data;
768 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
773 if(drmSLLookup(bo->user_data, key, &rd))
776 old_data = (drm_slp_user_data*)rd;
780 if(old_data->is_valid)
782 if(old_data->free_func)
785 old_data->free_func(old_data->data);
786 old_data->data = NULL;
790 old_data->is_valid = 1;
792 old_data->data = data;
798 drm_slp_bo_get_user_data(drm_slp_bo bo, unsigned long key, void** data)
801 drm_slp_user_data* old_data;
803 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo) && data && bo->user_data, 0);
805 if(drmSLLookup(bo->user_data, key, &rd))
811 old_data = (drm_slp_user_data*)rd;
818 *data = old_data->data;
824 drm_slp_bo_delete_user_data(drm_slp_bo bo, unsigned long key)
827 drm_slp_user_data* old_data=(void*)0;
829 DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo) && bo->user_data, 0);
831 if(drmSLLookup(bo->user_data, key, &rd))
834 old_data = (drm_slp_user_data*)rd;
838 if(old_data->is_valid && old_data->free_func)
841 old_data->free_func(old_data->data);
844 drmSLDelete(bo->user_data, key);