virtgpu_virgl: use blobs NV12 encoder input

Use blob buffers for encoder NV12 input, even when software access is
required. This is helpful for ARCVM, since the v4l2_codec2 stack
sometimes needs to do a format conversion in the guest as the
virtio-video encoder only supports NV12/I420 input.

Supporting this requires knowing the host buffer layout before creating
the blob resource. This is done by creating a temporary resource to
query the layout. To avoid the overhead of querying the host every time
a buffer is created, the allocator process keeps a cache of the most
recently used buffer formats and their host layout.

Creating temporary resources to discover host buffer parameters is a bit
of a cludge. However, since virtgpu_virgl will eventually be deprecated
in favor of virtgpu_cross_domain, a self-contained and simple approach
like this gives some nice performance gains on low end devices.

TEST=decode-edit-encode workflows
TEST=Cts{NativeHardware,Camera,Graphics,Video}TestCases on volteer
BUG=b:203380807, b:232531771

Change-Id: Ibda500862b42680ba898ba689e1600ebe5d258bd
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/3256451
Auto-Submit: David Stevens <stevensd@chromium.org>
Reviewed-by: Lepton Wu <lepton@chromium.org>
Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
Commit-Queue: Yiwei Zhang <zzyiwei@chromium.org>
Tested-by: David Stevens <stevensd@chromium.org>
This commit is contained in:
David Stevens 2022-10-24 17:51:46 +09:00 committed by Chromeos LUCI
parent fc3146f5b7
commit 7eb9e826a7
3 changed files with 229 additions and 22 deletions

View file

@ -601,3 +601,49 @@ void drv_resolve_format_and_use_flags_helper(struct driver *drv, uint32_t format
break;
}
}
static void lru_remove_entry(struct lru_entry *entry) {
entry->prev->next = entry->next;
entry->next->prev = entry->prev;
}
static void lru_link_entry(struct lru *lru, struct lru_entry *entry) {
struct lru_entry *head = &lru->head;
entry->prev = head;
entry->next = head->next;
head->next->prev = entry;
head->next = entry;
}
struct lru_entry *lru_find(struct lru *lru, bool (*eq)(struct lru_entry *e, void *data), void *data) {
struct lru_entry *head = &lru->head;
struct lru_entry *cur = head->next;
while (cur != head) {
if (eq(cur, data)) {
lru_remove_entry(cur);
lru_link_entry(lru, cur);
return cur;
}
cur = cur->next;
}
return NULL;
}
void lru_insert(struct lru *lru, struct lru_entry *entry) {
if (lru->count == lru->max) {
lru_remove_entry(lru->head.prev);
} else {
lru->count++;
}
lru_link_entry(lru, entry);
}
void lru_init(struct lru *lru, int max) {
lru->head.next = &lru->head;
lru->head.prev = &lru->head;
lru->count = 0;
lru->max = max;
}