From: Thomas Hellstrom Date: Wed, 30 Aug 2006 13:08:40 +0000 (+0200) Subject: Buffer object mapping and mapping synchronization for multiple clients. X-Git-Tag: android-x86-1.6~852^2~95 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=14a835be616183e733a2d6a7dcc697b8a6f46caf;p=android-x86%2Fexternal-libdrm.git Buffer object mapping and mapping synchronization for multiple clients. --- diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index c9005c41..f592ff2a 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -2606,10 +2606,10 @@ int drmBOCreate(int fd, drmTTM *ttm, unsigned long start, unsigned long size, buf->flags = rep->flags; buf->size = rep->size; buf->offset = rep->offset; - buf->map_handle = rep->arg_handle; - buf->map_flags = rep->map_flags; - buf->map_virtual = NULL; - buf->map_count = 0; + buf->mapHandle = rep->arg_handle; + buf->mapFlags = rep->map_flags; + buf->mapVirtual = NULL; + buf->mapCount = 0; buf->virtual = NULL; buf->mask = rep->mask; buf->hint = rep->hint; @@ -2666,13 +2666,14 @@ int drmBOReference(int fd, unsigned handle, drmBO *buf) buf->flags = rep->flags; buf->size = rep->size; buf->offset = rep->offset; - buf->map_handle = rep->arg_handle; - buf->map_flags = rep->map_flags; - buf->map_virtual = NULL; - buf->map_count = 0; + buf->mapHandle = rep->arg_handle; + buf->mapFlags = rep->map_flags; + buf->mapVirtual = NULL; + buf->mapCount = 0; buf->virtual = NULL; buf->mask = rep->mask; buf->hint = rep->hint; + buf->start = rep->buffer_start; return 0; } @@ -2699,6 +2700,92 @@ int drmBOUnReference(int fd, drmBO *buf) return 0; } +/* + * + */ + +int drmBOMap(int fd, drmBO *buf, unsigned map_flags, void **address) +{ + + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.req; + drm_bo_arg_reply_t *rep = &arg.rep; + int ret = 0; + + /* + * Make sure we have a virtual address of the buffer. + */ + + if (!buf->mapVirtual) { + if (buf->mapCount == 0) { + drmAddress virtual; + ret = drmMap(fd, buf->mapHandle, buf->size + buf->start, &virtual); + if (ret) + return ret; + ++buf->mapCount; + buf->mapVirtual = virtual; + buf->virtual = ((char *) virtual) + buf->start; + fprintf(stderr,"Mapvirtual, virtual: 0x%08x 0x%08x\n", + buf->mapVirtual, buf->virtual); + } + } + + req->handle = buf->handle; + req->mask = map_flags; + req->op = drm_bo_map; + req->next = 0; + + /* + * May hang if the buffer object is busy. + * This IOCTL synchronizes the buffer. + */ + + do { + ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg); + } while (ret != 0 && errno == EAGAIN); + + if (ret || !rep->handled || rep->ret) { + if (--buf->mapCount == 0) { + (void )drmUnmap(buf->mapVirtual, buf->start + buf->size); + } + } + if (ret) + return ret; + if (!rep->handled) + return -EFAULT; + if (rep->ret) + return rep->ret; + + *address = buf->virtual; + + return 0; +} + +int drmBOUnmap(int fd, drmBO *buf) +{ + drm_bo_arg_t arg; + drm_bo_arg_request_t *req = &arg.req; + + if (buf->mapCount == 0) { + return -EINVAL; + } + + if (--buf->mapCount == 0) { + (void) drmUnmap(buf->mapVirtual, buf->start + buf->size); + } + + req->handle = buf->handle; + req->op = drm_bo_unmap; + req->next = 0; + + if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) { + return -errno; + } + + return 0; +} + + int drmMMInit(int fd, unsigned long vramPOffset, unsigned long vramPSize, unsigned long ttPOffset, unsigned long ttPSize) { diff --git a/libdrm/xf86mm.h b/libdrm/xf86mm.h index 8711a144..c811892f 100644 --- a/libdrm/xf86mm.h +++ b/libdrm/xf86mm.h @@ -85,17 +85,17 @@ typedef struct _drmMMListHead typedef struct _drmBO{ drm_bo_type_t type; unsigned handle; - drm_handle_t map_handle; + drm_handle_t mapHandle; unsigned flags; unsigned mask; unsigned hint; - unsigned map_flags; + unsigned mapFlags; unsigned long size; unsigned long offset; unsigned long start; void *virtual; - void *map_virtual; - int map_count; + void *mapVirtual; + int mapCount; drmTTM *ttm; } drmBO; diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 5f557d55..aa59238f 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -513,8 +513,11 @@ static int drm_buffer_object_unmap(drm_file_t * priv, uint32_t handle) goto out; } + DRM_ERROR("Removing ref object\n"); drm_remove_ref_object(priv, ro); + DRM_ERROR("Deregistering usage\n"); drm_bo_usage_deref_locked(dev, bo); + DRM_ERROR("Done\n"); out: mutex_unlock(&dev->struct_mutex); return ret; diff --git a/linux-core/drm_object.c b/linux-core/drm_object.c index b928c01e..e1b79101 100644 --- a/linux-core/drm_object.c +++ b/linux-core/drm_object.c @@ -108,9 +108,6 @@ static int drm_object_ref_action(drm_file_t * priv, drm_user_object_t * ro, break; default: if (!ro->ref_struct_locked) { - DRM_ERROR("Register object called without register" - " capabilities\n"); - ret = -EINVAL; break; } else { ro->ref_struct_locked(priv, ro, action); @@ -164,6 +161,7 @@ int drm_add_ref_object(drm_file_t * priv, drm_user_object_t * referenced_object, atomic_set(&item->refcount, 1); item->hash.key = (unsigned long)referenced_object; ret = drm_ht_insert_item(ht, &item->hash); + item->unref_action = ref_action; if (ret) goto out; diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index 7163341d..69391058 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -713,6 +713,7 @@ static void drm_vm_ttm_close(struct vm_area_struct *vma) dev = ttm->dev; mutex_lock(&dev->struct_mutex); drm_ttm_delete_mm(ttm, vma->vm_mm); + list_del(&ttm_vma->head); drm_free(ttm_vma, sizeof(*ttm_vma), DRM_MEM_VMAS); if (atomic_dec_and_test(&ttm->vma_count)) { if (ttm->destroy) {