virgl: Allow transfer queue entries to be found and extended.
authorDavid Riley <davidriley@chromium.org>
Wed, 24 Apr 2019 23:11:37 +0000 (16:11 -0700)
committerGurchetan Singh <gurchetansingh@chromium.org>
Wed, 1 May 2019 22:48:46 +0000 (15:48 -0700)
Intersecting transfer queue entries allow for the possibility of
extending an existing transfer instead of creating a new one (and all
the associated mappign/unmapping).

Signed-off-by: David Riley <davidriley@chromium.org>
Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org>
src/gallium/drivers/virgl/virgl_transfer_queue.c
src/gallium/drivers/virgl/virgl_transfer_queue.h

index 6551d6a2cdbef592bb373dc6bcb1cf57f8f351eb..4831cbd235c3185e702eaa645cd6070055e92a59 100644 (file)
@@ -106,6 +106,14 @@ static void set_true(UNUSED struct virgl_transfer_queue *queue,
    *val = true;
 }
 
+static void set_queued(UNUSED struct virgl_transfer_queue *queue,
+                       struct list_action_args *args)
+{
+   struct virgl_transfer *queued = args->queued;
+   struct virgl_transfer **val = args->data;
+   *val = queued;
+}
+
 static void remove_transfer(struct virgl_transfer_queue *queue,
                             struct list_action_args *args)
 {
@@ -175,6 +183,26 @@ static void compare_and_perform_action(struct virgl_transfer_queue *queue,
    }
 }
 
+static void intersect_and_set_queued_once(struct virgl_transfer_queue *queue,
+                                          struct list_iteration_args *iter)
+{
+   struct list_action_args args;
+   struct virgl_transfer *queued, *tmp;
+   enum virgl_transfer_queue_lists type = iter->type;
+
+   memset(&args, 0, sizeof(args));
+   args.current = iter->current;
+   args.data = iter->data;
+
+   LIST_FOR_EACH_ENTRY_SAFE(queued, tmp, &queue->lists[type], queue_link) {
+      if (transfers_intersect(queued, iter->current)) {
+         args.queued = queued;
+         set_queued(queue, &args);
+         return;
+      }
+   }
+}
+
 static void perform_action(struct virgl_transfer_queue *queue,
                            struct list_iteration_args *iter)
 {
@@ -331,3 +359,26 @@ bool virgl_transfer_queue_is_queued(struct virgl_transfer_queue *queue,
 
    return queued;
 }
+
+struct virgl_transfer *
+virgl_transfer_queue_extend(struct virgl_transfer_queue *queue,
+                            struct virgl_transfer *transfer)
+{
+   struct virgl_transfer *queued = NULL;
+   struct list_iteration_args iter;
+
+   if (transfer->base.resource->target == PIPE_BUFFER) {
+      memset(&iter, 0, sizeof(iter));
+      iter.current = transfer;
+      iter.data = &queued;
+      iter.type = PENDING_LIST;
+      intersect_and_set_queued_once(queue, &iter);
+   }
+
+   if (queued) {
+      u_box_union_2d(&queued->base.box, &queued->base.box, &transfer->base.box);
+      queued->offset = queued->base.box.x;
+   }
+
+   return queued;
+}
index 3aebae0620b7253b583a81a75c8f8521b265f10a..403a0f1f4d7b4404f955aafad8a57f7e1608ae6e 100644 (file)
@@ -51,3 +51,10 @@ int virgl_transfer_queue_clear(struct virgl_transfer_queue *queue,
 
 bool virgl_transfer_queue_is_queued(struct virgl_transfer_queue *queue,
                                     struct virgl_transfer *transfer);
+
+/*
+ * Search the transfer queue for a transfer suitable for extension and
+ * extend it to include the new transfer.
+ */
+struct virgl_transfer * virgl_transfer_queue_extend(
+   struct virgl_transfer_queue *queue, struct virgl_transfer *transfer);