+static void
+add_exec_bo(struct intel_batchbuffer *batch, struct brw_bo *bo)
+{
+ if (bo != batch->bo) {
+ for (int i = 0; i < batch->exec_count; i++) {
+ if (batch->exec_bos[i] == bo)
+ return;
+ }
+
+ brw_bo_reference(bo);
+ }
+
+ if (batch->exec_count == batch->exec_array_size) {
+ batch->exec_array_size *= 2;
+ batch->exec_bos =
+ realloc(batch->exec_bos,
+ batch->exec_array_size * sizeof(batch->exec_bos[0]));
+ batch->validation_list =
+ realloc(batch->validation_list,
+ batch->exec_array_size * sizeof(batch->validation_list[0]));
+ }
+
+ struct drm_i915_gem_exec_object2 *validation_entry =
+ &batch->validation_list[batch->exec_count];
+ validation_entry->handle = bo->gem_handle;
+ if (bo == batch->bo) {
+ validation_entry->relocation_count = batch->reloc_count;
+ validation_entry->relocs_ptr = (uintptr_t) batch->relocs;
+ } else {
+ validation_entry->relocation_count = 0;
+ validation_entry->relocs_ptr = 0;
+ }
+ validation_entry->alignment = bo->align;
+ validation_entry->offset = bo->offset64;
+ validation_entry->flags = bo->kflags;
+ validation_entry->rsvd1 = 0;
+ validation_entry->rsvd2 = 0;
+
+ batch->exec_bos[batch->exec_count] = bo;
+ batch->exec_count++;
+ batch->aperture_space += bo->size;
+}
+
+static int
+execbuffer(int fd,
+ struct intel_batchbuffer *batch,
+ uint32_t ctx_id,
+ int used,
+ int in_fence,
+ int *out_fence,
+ int flags)
+{
+ struct drm_i915_gem_execbuffer2 execbuf = {
+ .buffers_ptr = (uintptr_t) batch->validation_list,
+ .buffer_count = batch->exec_count,
+ .batch_start_offset = 0,
+ .batch_len = used,
+ .flags = flags,
+ .rsvd1 = ctx_id, /* rsvd1 is actually the context ID */
+ };
+
+ unsigned long cmd = DRM_IOCTL_I915_GEM_EXECBUFFER2;
+
+ if (in_fence != -1) {
+ execbuf.rsvd2 = in_fence;
+ execbuf.flags |= I915_EXEC_FENCE_IN;
+ }
+
+ if (out_fence != NULL) {
+ cmd = DRM_IOCTL_I915_GEM_EXECBUFFER2_WR;
+ *out_fence = -1;
+ execbuf.flags |= I915_EXEC_FENCE_OUT;
+ }
+
+ int ret = drmIoctl(fd, cmd, &execbuf);
+ if (ret != 0)
+ ret = -errno;
+
+ for (int i = 0; i < batch->exec_count; i++) {
+ struct brw_bo *bo = batch->exec_bos[i];
+
+ bo->idle = false;
+
+ /* Update brw_bo::offset64 */
+ if (batch->validation_list[i].offset != bo->offset64) {
+ DBG("BO %d migrated: 0x%" PRIx64 " -> 0x%llx\n",
+ bo->gem_handle, bo->offset64, batch->validation_list[i].offset);
+ bo->offset64 = batch->validation_list[i].offset;
+ }
+ }
+
+ if (ret == 0 && out_fence != NULL)
+ *out_fence = execbuf.rsvd2 >> 32;
+
+ return ret;
+}
+