Add an accelerated buffer copy cleanup helper.
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Thu, 8 Feb 2007 20:28:33 +0000 (21:28 +0100)
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Thu, 8 Feb 2007 20:28:33 +0000 (21:28 +0100)
Export helper functions and make some important buffer-object functions non-static.
Add an i915 accelerated blit buffer move for pci memory buffers.

linux-core/drmP.h
linux-core/drm_bo.c
linux-core/drm_bo_move.c
linux-core/i915_buffer.c

index 5503521..86dcd79 100644 (file)
@@ -1509,6 +1509,15 @@ extern int drm_fence_buffer_objects(drm_file_t * priv,
                                    uint32_t fence_flags,
                                    drm_fence_object_t *fence,
                                    drm_fence_object_t **used_fence);
+extern void drm_bo_add_to_lru(drm_buffer_object_t * bo,
+                             drm_buffer_manager_t * bm);
+extern int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
+                      int no_wait);
+extern int drm_bo_mem_space(drm_device_t *dev,
+                           drm_bo_mem_reg_t *mem,
+                           int no_wait);
+
+
 /*
  * Buffer object memory move helpers.
  * drm_bo_move.c
@@ -1522,6 +1531,13 @@ extern int drm_bo_move_memcpy(drm_buffer_object_t *bo,
                              int evict,
                              int no_wait,
                              drm_bo_mem_reg_t *new_mem);
+extern int drm_bo_move_accel_cleanup(drm_buffer_object_t *bo,
+                                    int evict,
+                                    int no_wait,
+                                    uint32_t fence_type,
+                                    uint32_t fence_flags,
+                                    drm_bo_mem_reg_t *new_mem);
+
 extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
 extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
 
index e3ecaf4..67e7d37 100644 (file)
@@ -56,8 +56,6 @@ static void drm_bo_destroy_locked(drm_buffer_object_t *bo);
 static int drm_bo_setup_vm_locked(drm_buffer_object_t *bo);
 static void drm_bo_takedown_vm_locked(drm_buffer_object_t *bo);
 static void drm_bo_unmap_virtual(drm_buffer_object_t *bo);
-static int drm_bo_mem_space(drm_device_t *dev, drm_bo_mem_reg_t *mem,
-                           int no_wait);
 
 static inline uint32_t drm_bo_type_flags(unsigned type)
 {
@@ -68,8 +66,8 @@ static inline uint32_t drm_bo_type_flags(unsigned type)
  * bo locked. dev->struct_mutex locked.
  */
 
-static void drm_bo_add_to_lru(drm_buffer_object_t * bo,
-                             drm_buffer_manager_t * bm)
+void drm_bo_add_to_lru(drm_buffer_object_t * bo,
+                      drm_buffer_manager_t * bm)
 {
        struct list_head *list;
        drm_mem_type_manager_t *man;
@@ -206,8 +204,8 @@ static int drm_bo_handle_move_mem(drm_buffer_object_t *bo,
  * Wait until the buffer is idle.
  */
 
-static int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
-                      int no_wait)
+int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
+               int no_wait)
 {
 
        drm_fence_object_t *fence = bo->fence;
@@ -697,9 +695,9 @@ static int drm_bo_mt_compatible(drm_mem_type_manager_t *man,
 }
        
 
-static int drm_bo_mem_space(drm_device_t *dev,
-                           drm_bo_mem_reg_t *mem,
-                           int no_wait)
+int drm_bo_mem_space(drm_device_t *dev,
+                    drm_bo_mem_reg_t *mem,
+                    int no_wait)
 {
        drm_buffer_manager_t *bm= &dev->bm;
        drm_mem_type_manager_t *man; 
@@ -777,6 +775,8 @@ static int drm_bo_mem_space(drm_device_t *dev,
        ret = (has_eagain) ? -EAGAIN : -ENOMEM;
        return ret;
 }
+EXPORT_SYMBOL(drm_bo_mem_space);
+
 
 static int drm_bo_new_mask(drm_buffer_object_t *bo,
                           uint32_t new_mask, uint32_t hint)
@@ -1439,50 +1439,6 @@ static int drm_bo_handle_wait(drm_file_t * priv, uint32_t handle,
        return ret;
 }
 
-/*
- * Transfer a buffer object's memory and LRU status to a newly
- * created object. User-space references remains with the old
- * object. Call bo->mutex locked.
- */
-
-int drm_buffer_object_transfer(drm_buffer_object_t *bo,
-                              drm_buffer_object_t **new_obj)
-{
-       drm_buffer_object_t *fbo;
-       drm_device_t *dev = bo->dev;
-       drm_buffer_manager_t *bm = &dev->bm;
-
-       fbo = drm_ctl_calloc(1, sizeof(*bo), DRM_MEM_BUFOBJ);
-       if (!fbo)
-               return -ENOMEM;
-       
-       *fbo = *bo;
-       mutex_init(&fbo->mutex);
-       mutex_lock(&fbo->mutex);
-       mutex_lock(&dev->struct_mutex);
-
-       INIT_LIST_HEAD(&fbo->ddestroy);
-       INIT_LIST_HEAD(&fbo->lru);
-       list_splice_init(&bo->lru, &fbo->lru);
-
-       bo->mem.mm_node = NULL;
-       bo->ttm = NULL;
-       bo->fence = NULL;
-       bo->mem.flags = 0;
-
-       fbo->mem.mm_node->private = (void *)fbo;
-       atomic_set(&fbo->usage, 1);
-       atomic_inc(&bm->count);
-       mutex_unlock(&dev->struct_mutex);
-       mutex_unlock(&fbo->mutex);
-
-       *new_obj = fbo;
-       return 0;
-}
-
-
-               
-
 int drm_buffer_object_create(drm_file_t * priv,
                             unsigned long size,
                             drm_bo_type_t type,
index 9bfb3ef..d2c4450 100644 (file)
@@ -73,6 +73,7 @@ int drm_bo_move_ttm(drm_buffer_object_t *bo,
        DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE);
        return 0;
 }
+EXPORT_SYMBOL(drm_bo_move_ttm);
 
 
 /**
@@ -267,3 +268,121 @@ out:
        drm_mem_reg_iounmap(dev, &old_copy, old_iomap);
        return ret;
 }
+EXPORT_SYMBOL(drm_bo_move_memcpy);
+
+/*
+ * Transfer a buffer object's memory and LRU status to a newly
+ * created object. User-space references remains with the old
+ * object. Call bo->mutex locked.
+ */
+
+int drm_buffer_object_transfer(drm_buffer_object_t *bo,
+                              drm_buffer_object_t **new_obj)
+{
+       drm_buffer_object_t *fbo;
+       drm_device_t *dev = bo->dev;
+       drm_buffer_manager_t *bm = &dev->bm;
+
+       fbo = drm_ctl_calloc(1, sizeof(*bo), DRM_MEM_BUFOBJ);
+       if (!fbo)
+               return -ENOMEM;
+       
+       *fbo = *bo;
+       mutex_init(&fbo->mutex);
+       mutex_lock(&fbo->mutex);
+       mutex_lock(&dev->struct_mutex);
+
+       INIT_LIST_HEAD(&fbo->ddestroy);
+       INIT_LIST_HEAD(&fbo->lru);
+
+       bo->mem.mm_node = NULL;
+       bo->ttm = NULL;
+       atomic_inc(&bo->fence->usage);
+       bo->mem.flags = 0;
+
+       fbo->mem.mm_node->private = (void *)fbo;
+       atomic_set(&fbo->usage, 1);
+       atomic_inc(&bm->count);
+       mutex_unlock(&dev->struct_mutex);
+       mutex_unlock(&fbo->mutex);
+
+       *new_obj = fbo;
+       return 0;
+}
+
+int drm_bo_move_accel_cleanup(drm_buffer_object_t *bo,
+                             int evict,
+                             int no_wait,
+                             uint32_t fence_type,
+                             uint32_t fence_flags,
+                             drm_bo_mem_reg_t *new_mem)
+{
+       drm_device_t *dev = bo->dev;
+       drm_mem_type_manager_t *man = &dev->bm.man[new_mem->mem_type];
+       drm_bo_mem_reg_t *old_mem = &bo->mem;
+       int ret;
+       uint32_t save_flags = old_mem->flags;
+       uint32_t save_mask = old_mem->mask;
+       drm_buffer_object_t *old_obj;
+       
+       if (bo->fence)
+               drm_fence_usage_deref_unlocked(dev, bo->fence);
+       
+       ret = drm_fence_object_create(dev, fence_type,
+                                     fence_flags | DRM_FENCE_FLAG_EMIT,
+                                     &bo->fence);
+       if (ret)
+               return ret;
+
+       if (evict) {
+               ret = drm_bo_wait(bo, 0, 1, 0);
+               if (ret)
+                       return ret;
+               if (old_mem->mm_node) {
+                       mutex_lock(&dev->struct_mutex);
+                       drm_mm_put_block(old_mem->mm_node);
+                       old_mem->mm_node = NULL;
+                       mutex_unlock(&dev->struct_mutex);
+               }
+               if ((man->flags & _DRM_FLAG_MEMTYPE_FIXED) && 
+                   (bo->ttm != NULL)) {
+                       drm_ttm_unbind(bo->ttm);
+                       drm_destroy_ttm(bo->ttm);
+                       bo->ttm = NULL;
+               }
+       } else {
+
+               /* This should help pipeline ordinary buffer moves.
+                *
+                * Hang old buffer memory on a new buffer object,
+                * and leave it to be released when the blit
+                * operation has completed.
+                */
+
+               ret = drm_buffer_object_transfer(bo, &old_obj);
+               if (ret)
+                       return ret;
+
+               if (!(man->flags & _DRM_FLAG_MEMTYPE_FIXED))
+                       old_obj->ttm = NULL;
+               else
+                       bo->ttm = NULL;
+
+               atomic_inc(&old_obj->fence->usage);
+               mutex_lock(&dev->struct_mutex);
+               list_del(&old_obj->lru);
+               drm_bo_add_to_lru(old_obj, &old_obj->dev->bm);
+               drm_bo_usage_deref_locked(old_obj);
+               mutex_unlock(&dev->struct_mutex);
+
+       }
+
+       *old_mem = *new_mem;
+       new_mem->mm_node = NULL;
+       old_mem->mask = save_mask;
+       DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE);
+       return 0;
+}
+EXPORT_SYMBOL(drm_bo_move_accel_cleanup);
+               
+
index 5d1c39b..41f05b7 100644 (file)
@@ -118,7 +118,7 @@ uint32_t i915_evict_flags(drm_device_t *dev, uint32_t type)
        }
 }
 
-void i915_emit_copy_blit(drm_device_t *dev,
+static void i915_emit_copy_blit(drm_device_t *dev,
                         uint32_t src_offset,
                         uint32_t dst_offset,
                         uint32_t pages,
@@ -161,3 +161,35 @@ void i915_emit_copy_blit(drm_device_t *dev,
        }
        return;
 }
+
+static int drm_bo_move_blit(drm_buffer_object_t *bo,
+                           int evict,
+                           int no_wait,
+                           drm_bo_mem_reg_t *new_mem)
+{
+       drm_bo_mem_reg_t *old_mem = &bo->mem;
+       int dir = 0;
+
+       if ((old_mem->mem_type == new_mem->mem_type) && 
+           (new_mem->mm_node->start < 
+            old_mem->mm_node->start +  old_mem->mm_node->size)) {
+               dir = 1;
+       }
+
+       i915_emit_copy_blit(bo->dev,
+                           old_mem->mm_node->start << PAGE_SHIFT,
+                           new_mem->mm_node->start << PAGE_SHIFT,
+                           new_mem->num_pages,
+                           dir);
+
+       i915_emit_mi_flush(bo->dev, MI_READ_FLUSH | MI_EXE_FLUSH);
+
+       return drm_bo_move_accel_cleanup(bo, evict, no_wait,
+                                        DRM_FENCE_TYPE_EXE |
+                                        DRM_I915_FENCE_TYPE_RW, 
+                                        DRM_I915_FENCE_FLAG_FLUSHED, 
+                                        new_mem);
+}
+
+       
+