summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shared-core/drm.h2
-rw-r--r--shared-core/i915_dma.c62
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);