diff options
-rw-r--r-- | shared-core/drm.h | 2 | ||||
-rw-r--r-- | shared-core/i915_dma.c | 62 |
2 files changed, 50 insertions, 14 deletions
diff --git a/shared-core/drm.h b/shared-core/drm.h index ec07b895..70a25b24 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -753,6 +753,7 @@ struct drm_fence_arg { /* Don't place this buffer on the unfenced list.*/ #define DRM_BO_HINT_DONT_FENCE 0x00000004 #define DRM_BO_HINT_WAIT_LAZY 0x00000008 +#define DRM_BO_HINT_PRESUMED_OFFSET 0x00000010 #define DRM_BO_INIT_MAGIC 0xfe769812 #define DRM_BO_INIT_MAJOR 1 @@ -769,6 +770,7 @@ struct drm_bo_info_req { unsigned int desired_tile_stride; unsigned int tile_info; unsigned int pad64; + uint64_t presumed_offset; }; struct drm_bo_create_req { diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 42114beb..090ac80a 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -712,15 +712,20 @@ struct i915_relocatee_info { int is_iomem; }; -static void i915_dereference_buffers_locked(struct drm_buffer_object **buffers, +struct drm_i915_validate_buffer { + struct drm_buffer_object *buffer; + int presumed_offset_correct; +}; + +static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer *buffers, unsigned num_buffers) { while (num_buffers--) - drm_bo_usage_deref_locked(&buffers[num_buffers]); + drm_bo_usage_deref_locked(&buffers[num_buffers].buffer); } int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, - struct drm_buffer_object **buffers, + struct drm_i915_validate_buffer *buffers, struct i915_relocatee_info *relocatee, uint32_t *reloc) { @@ -734,6 +739,13 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, return -EINVAL; } + /* + * Short-circuit relocations that were correctly + * guessed by the client + */ + if (buffers[reloc[2]].presumed_offset_correct) + return 0; + new_cmd_offset = reloc[0]; if (!relocatee->data_page || !drm_bo_same_page(relocatee->offset, new_cmd_offset)) { @@ -751,7 +763,7 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, relocatee->page_offset = (relocatee->offset & PAGE_MASK); } - val = buffers[reloc[2]]->offset; + val = buffers[reloc[2]].buffer->offset; index = (reloc[0] - relocatee->page_offset) >> 2; /* add in validate */ @@ -765,7 +777,7 @@ int i915_process_relocs(struct drm_file *file_priv, uint32_t buf_handle, uint32_t *reloc_buf_handle, struct i915_relocatee_info *relocatee, - struct drm_buffer_object **buffers, + struct drm_i915_validate_buffer *buffers, uint32_t num_buffers) { struct drm_device *dev = file_priv->head->dev; @@ -851,12 +863,25 @@ out: static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, drm_handle_t buf_reloc_handle, - struct drm_buffer_object **buffers, + struct drm_i915_validate_buffer *buffers, uint32_t buf_count) { struct drm_device *dev = file_priv->head->dev; struct i915_relocatee_info relocatee; int ret = 0; + int b; + + /* + * Short circuit relocations when all previous + * buffers offsets were correctly guessed by + * the client + */ + for (b = 0; b < buf_count; b++) + if (!buffers[b].presumed_offset_correct) + break; + + if (b == buf_count) + return 0; memset(&relocatee, 0, sizeof(relocatee)); @@ -890,7 +915,7 @@ out_err: */ int i915_validate_buffer_list(struct drm_file *file_priv, unsigned int fence_class, uint64_t data, - struct drm_buffer_object **buffers, + struct drm_i915_validate_buffer *buffers, uint32_t *num_buffers) { struct drm_i915_op_arg arg; @@ -910,7 +935,8 @@ int i915_validate_buffer_list(struct drm_file *file_priv, goto out_err; } - buffers[buf_count] = NULL; + buffers[buf_count].buffer = NULL; + buffers[buf_count].presumed_offset_correct = 0; if (copy_from_user(&arg, (void __user *)(unsigned long)data, sizeof(arg))) { ret = -EFAULT; @@ -920,7 +946,7 @@ int i915_validate_buffer_list(struct drm_file *file_priv, if (arg.handled) { data = arg.next; mutex_lock(&dev->struct_mutex); - buffers[buf_count] = drm_lookup_buffer_object(file_priv, req->arg_handle, 1); + buffers[buf_count].buffer = drm_lookup_buffer_object(file_priv, req->arg_handle, 1); mutex_unlock(&dev->struct_mutex); buf_count++; continue; @@ -951,13 +977,21 @@ int i915_validate_buffer_list(struct drm_file *file_priv, req->bo_req.hint, 0, &rep.bo_info, - &buffers[buf_count]); + &buffers[buf_count].buffer); if (rep.ret) { DRM_ERROR("error on handle validate %d\n", rep.ret); goto out_err; } - + /* + * If the user provided a presumed offset hint, check whether + * the buffer is in the same place, if so, relocations relative to + * this buffer need not be performed + */ + if ((req->bo_req.hint & DRM_BO_HINT_PRESUMED_OFFSET) && + buffers[buf_count].buffer->offset == req->bo_req.presumed_offset) { + buffers[buf_count].presumed_offset_correct = 1; + } next = arg.next; arg.handled = 1; @@ -991,7 +1025,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data, struct drm_fence_arg *fence_arg = &exec_buf->fence_arg; int num_buffers; int ret; - struct drm_buffer_object **buffers; + struct drm_i915_validate_buffer *buffers; struct drm_fence_object *fence; if (!dev_priv->allow_batchbuffer) { @@ -1026,7 +1060,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data, num_buffers = exec_buf->num_buffers; - buffers = drm_calloc(num_buffers, sizeof(struct drm_buffer_object *), DRM_MEM_DRIVER); + buffers = drm_calloc(num_buffers, sizeof(struct drm_i915_validate_buffer), DRM_MEM_DRIVER); if (!buffers) { drm_bo_read_unlock(&dev->bm.bm_lock); mutex_unlock(&dev_priv->cmdbuf_mutex); @@ -1044,7 +1078,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data, drm_agp_chipset_flush(dev); /* submit buffer */ - batch->start = buffers[num_buffers-1]->offset; + batch->start = buffers[num_buffers-1].buffer->offset; DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n", batch->start, batch->used, batch->num_cliprects); |