OSDN Git Service

Buffer object mapping and mapping synchronization for multiple clients.
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Wed, 30 Aug 2006 13:08:40 +0000 (15:08 +0200)
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Wed, 30 Aug 2006 13:08:40 +0000 (15:08 +0200)
libdrm/xf86drm.c
libdrm/xf86mm.h
linux-core/drm_bo.c
linux-core/drm_object.c
linux-core/drm_vm.c

index c9005c4..f592ff2 100644 (file)
@@ -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)
 {
index 8711a14..c811892 100644 (file)
@@ -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;
 
index 5f557d5..aa59238 100644 (file)
@@ -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;
index b928c01..e1b7910 100644 (file)
@@ -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;
index 7163341..6939105 100644 (file)
@@ -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) {