minigbm: virtgpu/cross_domain: next generation virtgpu backend
This change provides a route to the host side "cross domain" allocator, which is specialized for resource sharing across domain boundaries. It uses the upcoming CONTEXT_INIT ioctl to initialize the backend when available, and multiple timelines to perform metadata queries. While it would be awesome to use the revolutionary Address Space Graphics (ASG) algorithm for metadata queries, it would be non-trivial to pull off in minigbm. Key aspects of the cross-domain allocator are: * Intelligently falls back to OpenGL texture allocation host-side when external memory is not available. The fallback path is named "virgl", even though it encompasses gfxstream and 2D mode. More refactorings will be added in the future for further clarity. * Uses host Vulkan or minigbm to perform metadata query, and uses a cache to minimize vmexits. * No shadow memory. Only zero-copy blobs will be supported if the blob is mappable. Shareable blobs may be compressed or tiled if not mappable. * A commitment to sharing code across Google projects and cross-platform GPU virtualization. The main goal here is to enable faster interation/testing, so this code is just a prototype. It should be fine to merge via minigbm, since the project has a very chill philosophy and even proudly accepts code that doesn't make any sense (crrev.com/c/2583188) [so long as existing users are not broken]. BUG=b:173630595 TEST=launch virtual machine with 2D mode TEST=launch virtual machine with 3D mode Change-Id: Ie33a46f19e5cdd82a2ac03bcf2351f4a8f294970 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/2691716 Reviewed-by: Lingfeng Yang <lfy@google.com> Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org> Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org> Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
This commit is contained in:
parent
6e200eae35
commit
73c141e48e
9 changed files with 722 additions and 195 deletions
16
drv.c
16
drv.c
|
|
@ -58,7 +58,7 @@ extern const struct backend backend_nouveau;
|
|||
extern const struct backend backend_komeda;
|
||||
extern const struct backend backend_radeon;
|
||||
extern const struct backend backend_synaptics;
|
||||
extern const struct backend backend_virtio_gpu;
|
||||
extern const struct backend backend_virtgpu;
|
||||
extern const struct backend backend_udl;
|
||||
extern const struct backend backend_vkms;
|
||||
|
||||
|
|
@ -94,21 +94,13 @@ static const struct backend *drv_get_backend(int fd)
|
|||
#ifdef DRV_VC4
|
||||
&backend_vc4,
|
||||
#endif
|
||||
&backend_evdi, &backend_marvell, &backend_meson, &backend_nouveau,
|
||||
&backend_komeda, &backend_radeon, &backend_synaptics, &backend_virtio_gpu,
|
||||
&backend_udl, &backend_virtio_gpu, &backend_vkms
|
||||
&backend_evdi, &backend_marvell, &backend_meson, &backend_nouveau,
|
||||
&backend_komeda, &backend_radeon, &backend_synaptics, &backend_virtgpu,
|
||||
&backend_udl, &backend_virtgpu, &backend_vkms
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(backend_list); i++) {
|
||||
const struct backend *b = backend_list[i];
|
||||
// Exactly one of the main create functions must be defined.
|
||||
assert((b->bo_create != NULL) ^ (b->bo_create_from_metadata != NULL));
|
||||
// Either both or neither must be implemented.
|
||||
assert((b->bo_compute_metadata != NULL) == (b->bo_create_from_metadata != NULL));
|
||||
// Both can't be defined, but it's okay for neither to be (i.e. only bo_create).
|
||||
assert((b->bo_create_with_modifiers == NULL) ||
|
||||
(b->bo_create_from_metadata == NULL));
|
||||
|
||||
if (!strcmp(drm_version->name, b->name)) {
|
||||
drmFreeVersion(drm_version);
|
||||
return b;
|
||||
|
|
|
|||
11
drv_priv.h
11
drv_priv.h
|
|
@ -27,6 +27,17 @@ struct bo_metadata {
|
|||
uint64_t format_modifier;
|
||||
uint64_t use_flags;
|
||||
size_t total_size;
|
||||
|
||||
/*
|
||||
* Most of the following metadata is virtgpu cross_domain specific. However, that backend
|
||||
* needs to know traditional metadata (strides, offsets) in addition to this backend
|
||||
* specific metadata. It's easiest just to stuff all the metadata here rather than
|
||||
* having two metadata structs.
|
||||
*/
|
||||
uint64_t blob_id;
|
||||
uint32_t map_info;
|
||||
int32_t memory_idx;
|
||||
int32_t physical_device_idx;
|
||||
};
|
||||
|
||||
struct bo {
|
||||
|
|
|
|||
58
external/virtgpu_cross_domain_protocol.h
vendored
Normal file
58
external/virtgpu_cross_domain_protocol.h
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2021 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef VIRTGPU_CROSS_DOMAIN_PROTOCOL_H
|
||||
#define VIRTGPU_CROSS_DOMAIN_PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Cross-domain commands (only a maximum of 255 supported)
|
||||
#define CROSS_DOMAIN_CMD_INIT 1
|
||||
#define CROSS_DOMAIN_CMD_GET_IMAGE_REQUIREMENTS 2
|
||||
|
||||
// Channel types (must match rutabaga channel types)
|
||||
#define CROSS_DOMAIN_CHANNEL_TYPE_WAYLAND 0x0001
|
||||
#define CROSS_DOMAIN_CHANNEL_TYPE_CAMERA 0x0002
|
||||
|
||||
struct CrossDomainCapabilities {
|
||||
uint32_t version;
|
||||
uint32_t supported_channels;
|
||||
uint32_t supports_dmabuf;
|
||||
uint32_t supports_external_gpu_memory;
|
||||
};
|
||||
|
||||
struct CrossDomainImageRequirements {
|
||||
uint32_t strides[4];
|
||||
uint32_t offsets[4];
|
||||
uint64_t modifier;
|
||||
uint64_t size;
|
||||
uint64_t blob_id;
|
||||
uint32_t map_info;
|
||||
uint32_t pad;
|
||||
int32_t memory_idx;
|
||||
int32_t physical_device_idx;
|
||||
};
|
||||
|
||||
struct CrossDomainHeader {
|
||||
uint8_t cmd;
|
||||
uint8_t fence_ctx_idx;
|
||||
uint16_t cmd_size;
|
||||
uint32_t pad;
|
||||
};
|
||||
|
||||
struct CrossDomainInit {
|
||||
struct CrossDomainHeader hdr;
|
||||
uint32_t ring_id;
|
||||
uint32_t channel_type;
|
||||
};
|
||||
|
||||
struct CrossDomainGetImageRequirements {
|
||||
struct CrossDomainHeader hdr;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t drm_format;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
#endif
|
||||
40
external/virtgpu_drm.h
vendored
40
external/virtgpu_drm.h
vendored
|
|
@ -47,12 +47,15 @@ extern "C" {
|
|||
#define DRM_VIRTGPU_WAIT 0x08
|
||||
#define DRM_VIRTGPU_GET_CAPS 0x09
|
||||
#define DRM_VIRTGPU_RESOURCE_CREATE_BLOB 0x0a
|
||||
#define DRM_VIRTGPU_CONTEXT_INIT 0x0b
|
||||
|
||||
#define VIRTGPU_EXECBUF_FENCE_FD_IN 0x01
|
||||
#define VIRTGPU_EXECBUF_FENCE_FD_OUT 0x02
|
||||
#define VIRTGPU_EXECBUF_FENCE_CONTEXT 0x04
|
||||
#define VIRTGPU_EXECBUF_FLAGS (\
|
||||
VIRTGPU_EXECBUF_FENCE_FD_IN |\
|
||||
VIRTGPU_EXECBUF_FENCE_FD_OUT |\
|
||||
VIRTGPU_EXECBUF_FENCE_CONTEXT |\
|
||||
0)
|
||||
|
||||
struct drm_virtgpu_map {
|
||||
|
|
@ -68,6 +71,8 @@ struct drm_virtgpu_execbuffer {
|
|||
__u64 bo_handles;
|
||||
__u32 num_bo_handles;
|
||||
__s32 fence_fd; /* in/out fence fd (see VIRTGPU_EXECBUF_FENCE_FD_IN/OUT) */
|
||||
__u32 fence_ctx_idx; /* which fence timeline to use */
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
#define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */
|
||||
|
|
@ -75,6 +80,8 @@ struct drm_virtgpu_execbuffer {
|
|||
#define VIRTGPU_PARAM_RESOURCE_BLOB 3 /* DRM_VIRTGPU_RESOURCE_CREATE_BLOB */
|
||||
#define VIRTGPU_PARAM_HOST_VISIBLE 4 /* Host blob resources are mappable */
|
||||
#define VIRTGPU_PARAM_CROSS_DEVICE 5 /* Cross virtio-device resource sharing */
|
||||
#define VIRTGPU_PARAM_CONTEXT_INIT 6 /* DRM_VIRTGPU_CONTEXT_INIT */
|
||||
#define VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs 7 /* Bitmask of supported capability set ids */
|
||||
|
||||
struct drm_virtgpu_getparam {
|
||||
__u64 param;
|
||||
|
|
@ -104,7 +111,7 @@ struct drm_virtgpu_resource_info {
|
|||
__u32 bo_handle;
|
||||
__u32 res_handle;
|
||||
__u32 size;
|
||||
__u32 stride;
|
||||
__u32 blob_mem;
|
||||
};
|
||||
|
||||
/* CHROMIUM */
|
||||
|
|
@ -172,13 +179,13 @@ struct drm_virtgpu_get_caps {
|
|||
};
|
||||
|
||||
struct drm_virtgpu_resource_create_blob {
|
||||
#define VIRTGPU_BLOB_MEM_GUEST 0x0001
|
||||
#define VIRTGPU_BLOB_MEM_HOST3D 0x0002
|
||||
#define VIRTGPU_BLOB_MEM_HOST3D_GUEST 0x0003
|
||||
#define VIRTGPU_BLOB_MEM_GUEST 0x0001
|
||||
#define VIRTGPU_BLOB_MEM_HOST3D 0x0002
|
||||
#define VIRTGPU_BLOB_MEM_HOST3D_GUEST 0x0003
|
||||
|
||||
#define VIRTGPU_BLOB_FLAG_USE_MAPPABLE 0x0001
|
||||
#define VIRTGPU_BLOB_FLAG_USE_SHAREABLE 0x0002
|
||||
#define VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
|
||||
#define VIRTGPU_BLOB_FLAG_USE_MAPPABLE 0x0001
|
||||
#define VIRTGPU_BLOB_FLAG_USE_SHAREABLE 0x0002
|
||||
#define VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
|
||||
/* zero is invalid blob_mem */
|
||||
__u32 blob_mem;
|
||||
__u32 blob_flags;
|
||||
|
|
@ -196,6 +203,21 @@ struct drm_virtgpu_resource_create_blob {
|
|||
__u64 blob_id;
|
||||
};
|
||||
|
||||
#define VIRTGPU_CONTEXT_PARAM_CAPSET_ID 0x0001
|
||||
#define VIRTGPU_CONTEXT_PARAM_NUM_FENCE_CONTEXTS 0x0002
|
||||
struct drm_virtgpu_context_set_param {
|
||||
__u64 param;
|
||||
__u64 value;
|
||||
};
|
||||
|
||||
struct drm_virtgpu_context_init {
|
||||
__u32 num_params;
|
||||
__u32 pad;
|
||||
|
||||
/* pointer to drm_virtgpu_context_set_param array */
|
||||
__u64 ctx_set_params;
|
||||
};
|
||||
|
||||
#define DRM_IOCTL_VIRTGPU_MAP \
|
||||
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map)
|
||||
|
||||
|
|
@ -240,6 +262,10 @@ struct drm_virtgpu_resource_create_blob {
|
|||
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE_BLOB, \
|
||||
struct drm_virtgpu_resource_create_blob)
|
||||
|
||||
#define DRM_IOCTL_VIRTGPU_CONTEXT_INIT \
|
||||
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_CONTEXT_INIT, \
|
||||
struct drm_virtgpu_context_init)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ extern "C" {
|
|||
#include "drv.h"
|
||||
#include "helpers_array.h"
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 0x1000
|
||||
#endif
|
||||
|
||||
uint32_t drv_height_from_format(uint32_t format, uint32_t height, size_t plane);
|
||||
uint32_t drv_vertical_subsampling_from_format(uint32_t format, size_t plane);
|
||||
uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane);
|
||||
|
|
|
|||
70
virtgpu.c
Normal file
70
virtgpu.c
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2021 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include "drv_priv.h"
|
||||
#include "external/virtgpu_drm.h"
|
||||
#include "helpers.h"
|
||||
#include "util.h"
|
||||
#include "virtgpu.h"
|
||||
|
||||
#define PARAM(x) \
|
||||
(struct virtgpu_param) \
|
||||
{ \
|
||||
x, #x, 0 \
|
||||
}
|
||||
|
||||
struct virtgpu_param params[] = {
|
||||
PARAM(VIRTGPU_PARAM_3D_FEATURES), PARAM(VIRTGPU_PARAM_CAPSET_QUERY_FIX),
|
||||
PARAM(VIRTGPU_PARAM_RESOURCE_BLOB), PARAM(VIRTGPU_PARAM_HOST_VISIBLE),
|
||||
PARAM(VIRTGPU_PARAM_CROSS_DEVICE), PARAM(VIRTGPU_PARAM_CONTEXT_INIT),
|
||||
PARAM(VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs),
|
||||
};
|
||||
|
||||
extern const struct backend virtgpu_virgl;
|
||||
extern const struct backend virtgpu_cross_domain;
|
||||
|
||||
static int virtgpu_init(struct driver *drv)
|
||||
{
|
||||
int ret = 0;
|
||||
const struct backend *virtgpu_backends[2] = {
|
||||
&virtgpu_cross_domain,
|
||||
&virtgpu_virgl,
|
||||
};
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(params); i++) {
|
||||
struct drm_virtgpu_getparam get_param = { 0 };
|
||||
|
||||
get_param.param = params[i].param;
|
||||
get_param.value = (uint64_t)(uintptr_t)¶ms[i].value;
|
||||
int ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, &get_param);
|
||||
if (ret)
|
||||
drv_log("DRM_IOCTL_VIRTGPU_GET_PARAM failed with %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(virtgpu_backends); i++) {
|
||||
const struct backend *backend = virtgpu_backends[i];
|
||||
ret = backend->init(drv);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
drv->backend = backend;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct backend backend_virtgpu = {
|
||||
.name = "virtio_gpu",
|
||||
.init = virtgpu_init,
|
||||
};
|
||||
22
virtgpu.h
Normal file
22
virtgpu.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright 2021 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
struct virtgpu_param {
|
||||
uint64_t param;
|
||||
const char *name;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
enum virtgpu_param_id {
|
||||
param_3d,
|
||||
param_capset_fix,
|
||||
param_resource_blob,
|
||||
param_host_visible,
|
||||
param_cross_device,
|
||||
param_context_init,
|
||||
param_supported_capset_ids,
|
||||
param_max,
|
||||
};
|
||||
390
virtgpu_cross_domain.c
Normal file
390
virtgpu_cross_domain.c
Normal file
|
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* Copyright 2021 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include "drv_priv.h"
|
||||
#include "external/virtgpu_cross_domain_protocol.h"
|
||||
#include "external/virtgpu_drm.h"
|
||||
#include "helpers.h"
|
||||
#include "util.h"
|
||||
#include "virtgpu.h"
|
||||
|
||||
#define CAPSET_CROSS_DOMAIN 5
|
||||
#define CAPSET_CROSS_FAKE 30
|
||||
|
||||
static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR8888,
|
||||
DRM_FORMAT_ARGB2101010, DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_XBGR2101010,
|
||||
DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB2101010,
|
||||
DRM_FORMAT_XRGB8888 };
|
||||
|
||||
static const uint32_t render_formats[] = { DRM_FORMAT_ABGR16161616F };
|
||||
|
||||
static const uint32_t texture_only_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12, DRM_FORMAT_P010,
|
||||
DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID };
|
||||
|
||||
extern struct virtgpu_param params[];
|
||||
|
||||
struct cross_domain_private {
|
||||
uint32_t ring_handle;
|
||||
void *ring_addr;
|
||||
struct drv_array *metadata_cache;
|
||||
};
|
||||
|
||||
static void cross_domain_release_private(struct driver *drv)
|
||||
{
|
||||
int ret;
|
||||
struct cross_domain_private *priv = drv->priv;
|
||||
struct drm_gem_close gem_close = { 0 };
|
||||
|
||||
if (priv->ring_addr != MAP_FAILED)
|
||||
munmap(priv->ring_addr, PAGE_SIZE);
|
||||
|
||||
if (priv->ring_handle) {
|
||||
gem_close.handle = priv->ring_handle;
|
||||
|
||||
ret = drmIoctl(drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
|
||||
if (ret) {
|
||||
drv_log("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n",
|
||||
priv->ring_handle, ret);
|
||||
}
|
||||
}
|
||||
|
||||
drv_array_destroy(priv->metadata_cache);
|
||||
free(priv);
|
||||
}
|
||||
|
||||
static void add_combinations(struct driver *drv)
|
||||
{
|
||||
struct format_metadata metadata;
|
||||
|
||||
// Linear metadata always supported.
|
||||
metadata.tiling = 0;
|
||||
metadata.priority = 1;
|
||||
metadata.modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
|
||||
drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats),
|
||||
&metadata, BO_USE_RENDER_MASK | BO_USE_SCANOUT);
|
||||
|
||||
drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), &metadata,
|
||||
BO_USE_RENDER_MASK);
|
||||
|
||||
drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats), &metadata,
|
||||
BO_USE_TEXTURE_MASK);
|
||||
|
||||
/* Android CTS tests require this. */
|
||||
drv_add_combination(drv, DRM_FORMAT_BGR888, &metadata, BO_USE_SW_MASK);
|
||||
|
||||
drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_ENCODER);
|
||||
drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata,
|
||||
BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER);
|
||||
|
||||
/*
|
||||
* R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots
|
||||
* from camera and input/output from hardware decoder/encoder.
|
||||
*/
|
||||
drv_modify_combination(drv, DRM_FORMAT_R8, &metadata,
|
||||
BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
|
||||
BO_USE_HW_VIDEO_ENCODER);
|
||||
|
||||
drv_modify_linear_combinations(drv);
|
||||
}
|
||||
|
||||
static int cross_domain_submit_cmd(struct driver *drv, uint32_t *cmd, uint32_t cmd_size, bool wait)
|
||||
{
|
||||
int ret;
|
||||
struct drm_virtgpu_3d_wait wait_3d = { 0 };
|
||||
struct drm_virtgpu_execbuffer exec = { 0 };
|
||||
struct cross_domain_private *priv = drv->priv;
|
||||
|
||||
exec.command = (uint64_t)&cmd[0];
|
||||
exec.size = cmd_size;
|
||||
if (wait) {
|
||||
exec.flags = VIRTGPU_EXECBUF_FENCE_CONTEXT;
|
||||
exec.bo_handles = (uint64_t)&priv->ring_handle;
|
||||
exec.num_bo_handles = 1;
|
||||
}
|
||||
|
||||
ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &exec);
|
||||
if (ret < 0) {
|
||||
drv_log("DRM_IOCTL_VIRTGPU_EXECBUFFER failed with %s\n", strerror(errno));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = -EAGAIN;
|
||||
while (ret == -EAGAIN) {
|
||||
wait_3d.handle = priv->ring_handle;
|
||||
ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &wait_3d);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
drv_log("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool metadata_equal(struct bo_metadata *current, struct bo_metadata *cached)
|
||||
{
|
||||
if ((current->width == cached->width) && (current->height == cached->height) &&
|
||||
(current->format == cached->format) && (current->use_flags == cached->use_flags))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int cross_domain_metadata_query(struct driver *drv, struct bo_metadata *metadata)
|
||||
{
|
||||
int ret = 0;
|
||||
struct bo_metadata *cached_data = NULL;
|
||||
struct cross_domain_private *priv = drv->priv;
|
||||
struct CrossDomainGetImageRequirements cmd_get_reqs;
|
||||
uint32_t *addr = (uint32_t *)priv->ring_addr;
|
||||
uint32_t plane, remaining_size;
|
||||
|
||||
memset(&cmd_get_reqs, 0, sizeof(cmd_get_reqs));
|
||||
pthread_mutex_lock(&drv->driver_lock);
|
||||
for (uint32_t i = 0; i < drv_array_size(priv->metadata_cache); i++) {
|
||||
cached_data = (struct bo_metadata *)drv_array_at_idx(priv->metadata_cache, i);
|
||||
if (!metadata_equal(metadata, cached_data))
|
||||
continue;
|
||||
|
||||
memcpy(metadata, cached_data, sizeof(*cached_data));
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
cmd_get_reqs.hdr.cmd = CROSS_DOMAIN_CMD_GET_IMAGE_REQUIREMENTS;
|
||||
cmd_get_reqs.hdr.cmd_size = sizeof(struct CrossDomainGetImageRequirements);
|
||||
|
||||
cmd_get_reqs.width = metadata->width;
|
||||
cmd_get_reqs.height = metadata->height;
|
||||
cmd_get_reqs.drm_format =
|
||||
(metadata->format == DRM_FORMAT_YVU420_ANDROID) ? DRM_FORMAT_YVU420 : metadata->format;
|
||||
cmd_get_reqs.flags = metadata->use_flags;
|
||||
|
||||
/*
|
||||
* It is possible to avoid blocking other bo_create() calls by unlocking before
|
||||
* cross_domain_submit_cmd() and re-locking afterwards. However, that would require
|
||||
* another scan of the metadata cache before drv_array_append in case two bo_create() calls
|
||||
* do the same metadata query. Until cross_domain functionality is more widely tested,
|
||||
* leave this optimization out for now.
|
||||
*/
|
||||
ret = cross_domain_submit_cmd(drv, (uint32_t *)&cmd_get_reqs, cmd_get_reqs.hdr.cmd_size,
|
||||
true);
|
||||
if (ret < 0)
|
||||
goto out_unlock;
|
||||
|
||||
memcpy(&metadata->strides, &addr[0], 4 * sizeof(uint32_t));
|
||||
memcpy(&metadata->offsets, &addr[4], 4 * sizeof(uint32_t));
|
||||
memcpy(&metadata->format_modifier, &addr[8], sizeof(uint64_t));
|
||||
memcpy(&metadata->total_size, &addr[10], sizeof(uint64_t));
|
||||
memcpy(&metadata->blob_id, &addr[12], sizeof(uint64_t));
|
||||
|
||||
metadata->map_info = addr[14];
|
||||
metadata->memory_idx = addr[16];
|
||||
metadata->physical_device_idx = addr[17];
|
||||
|
||||
remaining_size = metadata->total_size;
|
||||
for (plane = 0; plane < metadata->num_planes; plane++) {
|
||||
if (plane != 0) {
|
||||
metadata->sizes[plane - 1] = metadata->offsets[plane];
|
||||
remaining_size -= metadata->offsets[plane];
|
||||
}
|
||||
}
|
||||
|
||||
metadata->sizes[plane - 1] = remaining_size;
|
||||
drv_array_append(priv->metadata_cache, metadata);
|
||||
|
||||
out_unlock:
|
||||
pthread_mutex_unlock(&drv->driver_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cross_domain_init(struct driver *drv)
|
||||
{
|
||||
int ret;
|
||||
struct cross_domain_private *priv;
|
||||
struct drm_virtgpu_map map = { 0 };
|
||||
struct drm_virtgpu_get_caps args = { 0 };
|
||||
struct drm_virtgpu_context_init init = { 0 };
|
||||
struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
|
||||
struct drm_virtgpu_context_set_param ctx_set_params[2] = { { 0 } };
|
||||
|
||||
struct CrossDomainInit cmd_init;
|
||||
struct CrossDomainCapabilities cross_domain_caps;
|
||||
|
||||
memset(&cmd_init, 0, sizeof(cmd_init));
|
||||
if (!params[param_context_init].value)
|
||||
return -ENOTSUP;
|
||||
|
||||
if ((params[param_supported_capset_ids].value & (1 << CAPSET_CROSS_DOMAIN)) == 0)
|
||||
return -ENOTSUP;
|
||||
|
||||
/*
|
||||
* crosvm never reports the fake capset. This is just an extra check to make sure we
|
||||
* don't use the cross-domain context by accident. Developers may remove this for
|
||||
* testing purposes.
|
||||
*/
|
||||
if ((params[param_supported_capset_ids].value & (1 << CAPSET_CROSS_FAKE)) == 0)
|
||||
return -ENOTSUP;
|
||||
|
||||
priv = calloc(1, sizeof(*priv));
|
||||
priv->metadata_cache = drv_array_init(sizeof(struct bo_metadata));
|
||||
priv->ring_addr = MAP_FAILED;
|
||||
drv->priv = priv;
|
||||
|
||||
args.cap_set_id = CAPSET_CROSS_DOMAIN;
|
||||
args.size = sizeof(struct CrossDomainCapabilities);
|
||||
args.addr = (unsigned long long)&cross_domain_caps;
|
||||
|
||||
ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &args);
|
||||
if (ret) {
|
||||
drv_log("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno));
|
||||
goto free_private;
|
||||
}
|
||||
|
||||
// When 3D features are avilable, but the host does not support external memory, fall back
|
||||
// to the virgl minigbm backend. This typically means the guest side minigbm resource will
|
||||
// be backed by a host OpenGL texture.
|
||||
if (!cross_domain_caps.supports_external_gpu_memory && params[param_3d].value) {
|
||||
ret = -ENOTSUP;
|
||||
goto free_private;
|
||||
}
|
||||
|
||||
// Intialize the cross domain context. Create one fence context to wait for metadata
|
||||
// queries.
|
||||
ctx_set_params[0].param = VIRTGPU_CONTEXT_PARAM_CAPSET_ID;
|
||||
ctx_set_params[0].value = CAPSET_CROSS_DOMAIN;
|
||||
ctx_set_params[1].param = VIRTGPU_CONTEXT_PARAM_NUM_FENCE_CONTEXTS;
|
||||
ctx_set_params[1].value = 1;
|
||||
|
||||
init.ctx_set_params = (unsigned long long)&ctx_set_params[0];
|
||||
init.num_params = 2;
|
||||
ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_CONTEXT_INIT, &init);
|
||||
if (ret) {
|
||||
drv_log("DRM_IOCTL_VIRTGPU_CONTEXT_INIT failed with %s\n", strerror(errno));
|
||||
goto free_private;
|
||||
}
|
||||
|
||||
// Create a shared ring buffer to read metadata queries.
|
||||
drm_rc_blob.size = PAGE_SIZE;
|
||||
drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_GUEST;
|
||||
drm_rc_blob.blob_flags = VIRTGPU_BLOB_FLAG_USE_MAPPABLE;
|
||||
|
||||
ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob);
|
||||
if (ret < 0) {
|
||||
drv_log("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno));
|
||||
goto free_private;
|
||||
}
|
||||
|
||||
priv->ring_handle = drm_rc_blob.bo_handle;
|
||||
|
||||
// Map shared ring buffer.
|
||||
map.handle = priv->ring_handle;
|
||||
ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_MAP, &map);
|
||||
if (ret < 0) {
|
||||
drv_log("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno));
|
||||
goto free_private;
|
||||
}
|
||||
|
||||
priv->ring_addr =
|
||||
mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, drv->fd, map.offset);
|
||||
|
||||
if (priv->ring_addr == MAP_FAILED) {
|
||||
drv_log("mmap failed with %s\n", strerror(errno));
|
||||
goto free_private;
|
||||
}
|
||||
|
||||
// Notify host about ring buffer
|
||||
cmd_init.hdr.cmd = CROSS_DOMAIN_CMD_INIT;
|
||||
cmd_init.hdr.cmd_size = sizeof(struct CrossDomainInit);
|
||||
cmd_init.ring_id = drm_rc_blob.res_handle;
|
||||
ret = cross_domain_submit_cmd(drv, (uint32_t *)&cmd_init, cmd_init.hdr.cmd_size, false);
|
||||
if (ret < 0)
|
||||
goto free_private;
|
||||
|
||||
// minigbm bookkeeping
|
||||
add_combinations(drv);
|
||||
return 0;
|
||||
|
||||
free_private:
|
||||
cross_domain_release_private(drv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cross_domain_close(struct driver *drv)
|
||||
{
|
||||
cross_domain_release_private(drv);
|
||||
}
|
||||
|
||||
static int cross_domain_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
|
||||
uint64_t use_flags)
|
||||
{
|
||||
int ret;
|
||||
uint32_t blob_flags = VIRTGPU_BLOB_FLAG_USE_SHAREABLE;
|
||||
struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
|
||||
|
||||
ret = cross_domain_metadata_query(bo->drv, &bo->meta);
|
||||
if (ret < 0) {
|
||||
drv_log("Metadata query failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (use_flags & BO_USE_SW_MASK)
|
||||
blob_flags |= VIRTGPU_BLOB_FLAG_USE_MAPPABLE;
|
||||
|
||||
if (params[param_cross_device].value && (use_flags & BO_USE_NON_GPU_HW))
|
||||
blob_flags |= VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE;
|
||||
|
||||
drm_rc_blob.size = bo->meta.total_size;
|
||||
drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST3D;
|
||||
drm_rc_blob.blob_flags = blob_flags;
|
||||
drm_rc_blob.blob_id = bo->meta.blob_id;
|
||||
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob);
|
||||
if (ret < 0) {
|
||||
drv_log("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++)
|
||||
bo->handles[plane].u32 = drm_rc_blob.bo_handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *cross_domain_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
|
||||
{
|
||||
int ret;
|
||||
struct drm_virtgpu_map gem_map = { 0 };
|
||||
|
||||
gem_map.handle = bo->handles[0].u32;
|
||||
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_MAP, &gem_map);
|
||||
if (ret) {
|
||||
drv_log("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno));
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
vma->length = bo->meta.total_size;
|
||||
return mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
|
||||
gem_map.offset);
|
||||
}
|
||||
|
||||
const struct backend virtgpu_cross_domain = {
|
||||
.name = "virtgpu_cross_domain",
|
||||
.init = cross_domain_init,
|
||||
.close = cross_domain_close,
|
||||
.bo_create = cross_domain_bo_create,
|
||||
.bo_import = drv_prime_bo_import,
|
||||
.bo_destroy = drv_gem_bo_destroy,
|
||||
.bo_map = cross_domain_bo_map,
|
||||
.bo_unmap = drv_bo_munmap,
|
||||
.resolve_format = drv_resolve_format_helper,
|
||||
};
|
||||
|
|
@ -8,7 +8,6 @@
|
|||
#include <errno.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <xf86drm.h>
|
||||
|
|
@ -19,42 +18,13 @@
|
|||
#include "external/virtgpu_drm.h"
|
||||
#include "helpers.h"
|
||||
#include "util.h"
|
||||
#include "virtgpu.h"
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 0x1000
|
||||
#endif
|
||||
#define PIPE_TEXTURE_2D 2
|
||||
|
||||
#define MESA_LLVMPIPE_TILE_ORDER 6
|
||||
#define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER)
|
||||
|
||||
struct feature {
|
||||
uint64_t feature;
|
||||
const char *name;
|
||||
uint32_t enabled;
|
||||
};
|
||||
|
||||
enum feature_id {
|
||||
feat_3d,
|
||||
feat_capset_fix,
|
||||
feat_resource_blob,
|
||||
feat_host_visible,
|
||||
feat_host_cross_device,
|
||||
feat_max,
|
||||
};
|
||||
|
||||
#define FEATURE(x) \
|
||||
(struct feature) \
|
||||
{ \
|
||||
x, #x, 0 \
|
||||
}
|
||||
|
||||
static struct feature features[] = {
|
||||
FEATURE(VIRTGPU_PARAM_3D_FEATURES), FEATURE(VIRTGPU_PARAM_CAPSET_QUERY_FIX),
|
||||
FEATURE(VIRTGPU_PARAM_RESOURCE_BLOB), FEATURE(VIRTGPU_PARAM_HOST_VISIBLE),
|
||||
FEATURE(VIRTGPU_PARAM_CROSS_DEVICE),
|
||||
};
|
||||
|
||||
static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888,
|
||||
DRM_FORMAT_XRGB8888 };
|
||||
|
|
@ -68,7 +38,9 @@ static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_N
|
|||
DRM_FORMAT_R8, DRM_FORMAT_R16,
|
||||
DRM_FORMAT_RG88, DRM_FORMAT_YVU420_ANDROID };
|
||||
|
||||
struct virtio_gpu_priv {
|
||||
extern struct virtgpu_param params[];
|
||||
|
||||
struct virgl_priv {
|
||||
int caps_is_v2;
|
||||
union virgl_caps caps;
|
||||
int host_gbm_enabled;
|
||||
|
|
@ -112,8 +84,8 @@ static uint32_t translate_format(uint32_t drm_fourcc)
|
|||
}
|
||||
}
|
||||
|
||||
static bool virtio_gpu_bitmask_supports_format(struct virgl_supported_format_mask *supported,
|
||||
uint32_t drm_format)
|
||||
static bool virgl_bitmask_supports_format(struct virgl_supported_format_mask *supported,
|
||||
uint32_t drm_format)
|
||||
{
|
||||
uint32_t virgl_format = translate_format(drm_format);
|
||||
if (!virgl_format)
|
||||
|
|
@ -165,7 +137,7 @@ static bool virtio_gpu_bitmask_supports_format(struct virgl_supported_format_mas
|
|||
// Additional note: the V-plane is not placed to the right of the U-plane due to some
|
||||
// observed failures in media framework code which assumes the V-plane is not
|
||||
// "row-interlaced" with the U-plane.
|
||||
static void virtio_gpu_get_emulated_metadata(const struct bo *bo, struct bo_metadata *metadata)
|
||||
static void virgl_get_emulated_metadata(const struct bo *bo, struct bo_metadata *metadata)
|
||||
{
|
||||
uint32_t y_plane_height;
|
||||
uint32_t c_plane_height;
|
||||
|
|
@ -235,9 +207,9 @@ struct virtio_transfers_params {
|
|||
struct rectangle xfer_boxes[DRV_MAX_PLANES];
|
||||
};
|
||||
|
||||
static void virtio_gpu_get_emulated_transfers_params(const struct bo *bo,
|
||||
const struct rectangle *transfer_box,
|
||||
struct virtio_transfers_params *xfer_params)
|
||||
static void virgl_get_emulated_transfers_params(const struct bo *bo,
|
||||
const struct rectangle *transfer_box,
|
||||
struct virtio_transfers_params *xfer_params)
|
||||
{
|
||||
uint32_t y_plane_height;
|
||||
uint32_t c_plane_height;
|
||||
|
|
@ -245,7 +217,7 @@ static void virtio_gpu_get_emulated_transfers_params(const struct bo *bo,
|
|||
|
||||
if (transfer_box->x == 0 && transfer_box->y == 0 && transfer_box->width == bo->meta.width &&
|
||||
transfer_box->height == bo->meta.height) {
|
||||
virtio_gpu_get_emulated_metadata(bo, &emulated_metadata);
|
||||
virgl_get_emulated_metadata(bo, &emulated_metadata);
|
||||
|
||||
xfer_params->xfers_needed = 1;
|
||||
xfer_params->xfer_boxes[0].x = 0;
|
||||
|
|
@ -308,24 +280,24 @@ static void virtio_gpu_get_emulated_transfers_params(const struct bo *bo,
|
|||
}
|
||||
}
|
||||
|
||||
static bool virtio_gpu_supports_combination_natively(struct driver *drv, uint32_t drm_format,
|
||||
uint64_t use_flags)
|
||||
static bool virgl_supports_combination_natively(struct driver *drv, uint32_t drm_format,
|
||||
uint64_t use_flags)
|
||||
{
|
||||
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
|
||||
struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
|
||||
|
||||
if (priv->caps.max_version == 0)
|
||||
return true;
|
||||
|
||||
if ((use_flags & BO_USE_RENDERING) &&
|
||||
!virtio_gpu_bitmask_supports_format(&priv->caps.v1.render, drm_format))
|
||||
!virgl_bitmask_supports_format(&priv->caps.v1.render, drm_format))
|
||||
return false;
|
||||
|
||||
if ((use_flags & BO_USE_TEXTURE) &&
|
||||
!virtio_gpu_bitmask_supports_format(&priv->caps.v1.sampler, drm_format))
|
||||
!virgl_bitmask_supports_format(&priv->caps.v1.sampler, drm_format))
|
||||
return false;
|
||||
|
||||
if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 &&
|
||||
!virtio_gpu_bitmask_supports_format(&priv->caps.v2.scanout, drm_format))
|
||||
!virgl_bitmask_supports_format(&priv->caps.v2.scanout, drm_format))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
@ -334,11 +306,10 @@ static bool virtio_gpu_supports_combination_natively(struct driver *drv, uint32_
|
|||
// For virtio backends that do not support formats natively (e.g. multi-planar formats are not
|
||||
// supported in virglrenderer when gbm is unavailable on the host machine), whether or not the
|
||||
// format and usage combination can be handled as a blob (byte buffer).
|
||||
static bool virtio_gpu_supports_combination_through_emulation(struct driver *drv,
|
||||
uint32_t drm_format,
|
||||
uint64_t use_flags)
|
||||
static bool virgl_supports_combination_through_emulation(struct driver *drv, uint32_t drm_format,
|
||||
uint64_t use_flags)
|
||||
{
|
||||
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
|
||||
struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
|
||||
|
||||
// Only enable emulation on non-gbm virtio backends.
|
||||
if (priv->host_gbm_enabled)
|
||||
|
|
@ -347,7 +318,7 @@ static bool virtio_gpu_supports_combination_through_emulation(struct driver *drv
|
|||
if (use_flags & (BO_USE_RENDERING | BO_USE_SCANOUT))
|
||||
return false;
|
||||
|
||||
if (!virtio_gpu_supports_combination_natively(drv, DRM_FORMAT_R8, use_flags))
|
||||
if (!virgl_supports_combination_natively(drv, DRM_FORMAT_R8, use_flags))
|
||||
return false;
|
||||
|
||||
return drm_format == DRM_FORMAT_NV12 || drm_format == DRM_FORMAT_NV21 ||
|
||||
|
|
@ -356,21 +327,20 @@ static bool virtio_gpu_supports_combination_through_emulation(struct driver *drv
|
|||
|
||||
// Adds the given buffer combination to the list of supported buffer combinations if the
|
||||
// combination is supported by the virtio backend.
|
||||
static void virtio_gpu_add_combination(struct driver *drv, uint32_t drm_format,
|
||||
struct format_metadata *metadata, uint64_t use_flags)
|
||||
static void virgl_add_combination(struct driver *drv, uint32_t drm_format,
|
||||
struct format_metadata *metadata, uint64_t use_flags)
|
||||
{
|
||||
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
|
||||
struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
|
||||
|
||||
if (features[feat_3d].enabled && priv->caps.max_version >= 1) {
|
||||
if (params[param_3d].value && priv->caps.max_version >= 1) {
|
||||
if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 &&
|
||||
!virtio_gpu_supports_combination_natively(drv, drm_format, use_flags)) {
|
||||
!virgl_supports_combination_natively(drv, drm_format, use_flags)) {
|
||||
drv_log("Scanout format: %d\n", drm_format);
|
||||
use_flags &= ~BO_USE_SCANOUT;
|
||||
}
|
||||
|
||||
if (!virtio_gpu_supports_combination_natively(drv, drm_format, use_flags) &&
|
||||
!virtio_gpu_supports_combination_through_emulation(drv, drm_format,
|
||||
use_flags)) {
|
||||
if (!virgl_supports_combination_natively(drv, drm_format, use_flags) &&
|
||||
!virgl_supports_combination_through_emulation(drv, drm_format, use_flags)) {
|
||||
drv_log("Skipping unsupported combination format:%d\n", drm_format);
|
||||
return;
|
||||
}
|
||||
|
|
@ -381,14 +351,14 @@ static void virtio_gpu_add_combination(struct driver *drv, uint32_t drm_format,
|
|||
|
||||
// Adds each given buffer combination to the list of supported buffer combinations if the
|
||||
// combination supported by the virtio backend.
|
||||
static void virtio_gpu_add_combinations(struct driver *drv, const uint32_t *drm_formats,
|
||||
uint32_t num_formats, struct format_metadata *metadata,
|
||||
uint64_t use_flags)
|
||||
static void virgl_add_combinations(struct driver *drv, const uint32_t *drm_formats,
|
||||
uint32_t num_formats, struct format_metadata *metadata,
|
||||
uint64_t use_flags)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < num_formats; i++)
|
||||
virtio_gpu_add_combination(drv, drm_formats[i], metadata, use_flags);
|
||||
virgl_add_combination(drv, drm_formats[i], metadata, use_flags);
|
||||
}
|
||||
|
||||
static int virtio_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
|
||||
|
|
@ -464,8 +434,8 @@ static uint32_t compute_virgl_bind_flags(uint64_t use_flags, uint32_t format)
|
|||
return bind;
|
||||
}
|
||||
|
||||
static int virtio_virgl_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
|
||||
uint64_t use_flags)
|
||||
static int virgl_3d_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
|
||||
uint64_t use_flags)
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
|
|
@ -473,14 +443,13 @@ static int virtio_virgl_bo_create(struct bo *bo, uint32_t width, uint32_t height
|
|||
struct drm_virtgpu_resource_create res_create = { 0 };
|
||||
struct bo_metadata emulated_metadata;
|
||||
|
||||
if (virtio_gpu_supports_combination_natively(bo->drv, format, use_flags)) {
|
||||
if (virgl_supports_combination_natively(bo->drv, format, use_flags)) {
|
||||
stride = drv_stride_from_format(format, width, 0);
|
||||
drv_bo_from_format(bo, stride, height, format);
|
||||
} else {
|
||||
assert(
|
||||
virtio_gpu_supports_combination_through_emulation(bo->drv, format, use_flags));
|
||||
assert(virgl_supports_combination_through_emulation(bo->drv, format, use_flags));
|
||||
|
||||
virtio_gpu_get_emulated_metadata(bo, &emulated_metadata);
|
||||
virgl_get_emulated_metadata(bo, &emulated_metadata);
|
||||
|
||||
format = emulated_metadata.format;
|
||||
width = emulated_metadata.width;
|
||||
|
|
@ -526,7 +495,7 @@ static int virtio_virgl_bo_create(struct bo *bo, uint32_t width, uint32_t height
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void *virtio_virgl_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
|
||||
static void *virgl_3d_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
|
||||
{
|
||||
int ret;
|
||||
struct drm_virtgpu_map gem_map = { 0 };
|
||||
|
|
@ -543,14 +512,14 @@ static void *virtio_virgl_bo_map(struct bo *bo, struct vma *vma, size_t plane, u
|
|||
gem_map.offset);
|
||||
}
|
||||
|
||||
static int virtio_gpu_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_is_v2)
|
||||
static int virgl_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_is_v2)
|
||||
{
|
||||
int ret;
|
||||
struct drm_virtgpu_get_caps cap_args = { 0 };
|
||||
|
||||
*caps_is_v2 = 0;
|
||||
cap_args.addr = (unsigned long long)caps;
|
||||
if (features[feat_capset_fix].enabled) {
|
||||
if (params[param_capset_fix].value) {
|
||||
*caps_is_v2 = 1;
|
||||
cap_args.cap_set_id = 2;
|
||||
cap_args.size = sizeof(union virgl_caps);
|
||||
|
|
@ -576,79 +545,69 @@ static int virtio_gpu_get_caps(struct driver *drv, union virgl_caps *caps, int *
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void virtio_gpu_init_features_and_caps(struct driver *drv)
|
||||
static void virgl_init_params_and_caps(struct driver *drv)
|
||||
{
|
||||
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
|
||||
struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
|
||||
if (params[param_3d].value) {
|
||||
virgl_get_caps(drv, &priv->caps, &priv->caps_is_v2);
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(features); i++) {
|
||||
struct drm_virtgpu_getparam params = { 0 };
|
||||
|
||||
params.param = features[i].feature;
|
||||
params.value = (uint64_t)(uintptr_t)&features[i].enabled;
|
||||
int ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, ¶ms);
|
||||
if (ret)
|
||||
drv_log("DRM_IOCTL_VIRTGPU_GET_PARAM failed with %s\n", strerror(errno));
|
||||
// We use two criteria to determine whether host minigbm is used on the host for
|
||||
// swapchain allocations.
|
||||
//
|
||||
// (1) Host minigbmgbm is only available via virglrenderer, and only virglrenderer
|
||||
// advertises capabilities.
|
||||
// (2) Only host minigbm doesn't emulate YUV formats. Checking this is a bit of a
|
||||
// proxy, but it works.
|
||||
priv->host_gbm_enabled = priv->caps.max_version > 0 &&
|
||||
virgl_supports_combination_natively(drv, DRM_FORMAT_NV12, BO_USE_TEXTURE);
|
||||
}
|
||||
|
||||
if (features[feat_3d].enabled)
|
||||
virtio_gpu_get_caps(drv, &priv->caps, &priv->caps_is_v2);
|
||||
|
||||
priv->host_gbm_enabled =
|
||||
// 2D mode does not create resources on the host so it does not enable host gbm.
|
||||
features[feat_3d].enabled &&
|
||||
// Gfxstream does not enable host gbm. Virglrenderer sets caps while Gfxstream does not
|
||||
// so filter out if we are running with Gfxstream.
|
||||
priv->caps.max_version > 0 &&
|
||||
// Virglrenderer only supports multi-planar formats through host gbm.
|
||||
virtio_gpu_supports_combination_natively(drv, DRM_FORMAT_NV12, BO_USE_TEXTURE);
|
||||
}
|
||||
|
||||
static int virtio_gpu_init(struct driver *drv)
|
||||
static int virgl_init(struct driver *drv)
|
||||
{
|
||||
struct virtio_gpu_priv *priv;
|
||||
struct virgl_priv *priv;
|
||||
|
||||
priv = calloc(1, sizeof(*priv));
|
||||
drv->priv = priv;
|
||||
|
||||
virtio_gpu_init_features_and_caps(drv);
|
||||
virgl_init_params_and_caps(drv);
|
||||
|
||||
if (features[feat_3d].enabled) {
|
||||
if (params[param_3d].value) {
|
||||
/* This doesn't mean host can scanout everything, it just means host
|
||||
* hypervisor can show it. */
|
||||
virtio_gpu_add_combinations(drv, render_target_formats,
|
||||
ARRAY_SIZE(render_target_formats), &LINEAR_METADATA,
|
||||
BO_USE_RENDER_MASK | BO_USE_SCANOUT);
|
||||
virtio_gpu_add_combinations(drv, texture_source_formats,
|
||||
ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA,
|
||||
BO_USE_TEXTURE_MASK);
|
||||
virgl_add_combinations(drv, render_target_formats,
|
||||
ARRAY_SIZE(render_target_formats), &LINEAR_METADATA,
|
||||
BO_USE_RENDER_MASK | BO_USE_SCANOUT);
|
||||
virgl_add_combinations(drv, texture_source_formats,
|
||||
ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA,
|
||||
BO_USE_TEXTURE_MASK);
|
||||
} else {
|
||||
/* Virtio primary plane only allows this format. */
|
||||
virtio_gpu_add_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA,
|
||||
BO_USE_RENDER_MASK | BO_USE_SCANOUT);
|
||||
virgl_add_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA,
|
||||
BO_USE_RENDER_MASK | BO_USE_SCANOUT);
|
||||
/* Virtio cursor plane only allows this format and Chrome cannot live without
|
||||
* ARGB888 renderable format. */
|
||||
virtio_gpu_add_combination(drv, DRM_FORMAT_ARGB8888, &LINEAR_METADATA,
|
||||
BO_USE_RENDER_MASK | BO_USE_CURSOR);
|
||||
virgl_add_combination(drv, DRM_FORMAT_ARGB8888, &LINEAR_METADATA,
|
||||
BO_USE_RENDER_MASK | BO_USE_CURSOR);
|
||||
/* Android needs more, but they cannot be bound as scanouts anymore after
|
||||
* "drm/virtio: fix DRM_FORMAT_* handling" */
|
||||
virtio_gpu_add_combinations(drv, render_target_formats,
|
||||
ARRAY_SIZE(render_target_formats), &LINEAR_METADATA,
|
||||
BO_USE_RENDER_MASK);
|
||||
virtio_gpu_add_combinations(drv, dumb_texture_source_formats,
|
||||
ARRAY_SIZE(dumb_texture_source_formats),
|
||||
&LINEAR_METADATA, BO_USE_TEXTURE_MASK);
|
||||
virtio_gpu_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
|
||||
BO_USE_SW_MASK | BO_USE_LINEAR);
|
||||
virtio_gpu_add_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA,
|
||||
BO_USE_SW_MASK | BO_USE_LINEAR);
|
||||
virgl_add_combinations(drv, render_target_formats,
|
||||
ARRAY_SIZE(render_target_formats), &LINEAR_METADATA,
|
||||
BO_USE_RENDER_MASK);
|
||||
virgl_add_combinations(drv, dumb_texture_source_formats,
|
||||
ARRAY_SIZE(dumb_texture_source_formats), &LINEAR_METADATA,
|
||||
BO_USE_TEXTURE_MASK);
|
||||
virgl_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
|
||||
BO_USE_SW_MASK | BO_USE_LINEAR);
|
||||
virgl_add_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA,
|
||||
BO_USE_SW_MASK | BO_USE_LINEAR);
|
||||
}
|
||||
|
||||
/* Android CTS tests require this. */
|
||||
virtio_gpu_add_combination(drv, DRM_FORMAT_RGB888, &LINEAR_METADATA, BO_USE_SW_MASK);
|
||||
virtio_gpu_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
|
||||
virtio_gpu_add_combination(drv, DRM_FORMAT_ABGR16161616F, &LINEAR_METADATA,
|
||||
BO_USE_SW_MASK | BO_USE_TEXTURE_MASK);
|
||||
|
||||
virgl_add_combination(drv, DRM_FORMAT_RGB888, &LINEAR_METADATA, BO_USE_SW_MASK);
|
||||
virgl_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK);
|
||||
virgl_add_combination(drv, DRM_FORMAT_ABGR16161616F, &LINEAR_METADATA,
|
||||
BO_USE_SW_MASK | BO_USE_TEXTURE_MASK);
|
||||
drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
|
||||
BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER |
|
||||
BO_USE_HW_VIDEO_ENCODER);
|
||||
|
|
@ -680,20 +639,20 @@ static int virtio_gpu_init(struct driver *drv)
|
|||
return drv_modify_linear_combinations(drv);
|
||||
}
|
||||
|
||||
static void virtio_gpu_close(struct driver *drv)
|
||||
static void virgl_close(struct driver *drv)
|
||||
{
|
||||
free(drv->priv);
|
||||
drv->priv = NULL;
|
||||
}
|
||||
|
||||
static int virtio_gpu_bo_create_blob(struct driver *drv, struct bo *bo)
|
||||
static int virgl_bo_create_blob(struct driver *drv, struct bo *bo)
|
||||
{
|
||||
int ret;
|
||||
uint32_t stride;
|
||||
uint32_t cur_blob_id;
|
||||
uint32_t cmd[VIRGL_PIPE_RES_CREATE_SIZE + 1] = { 0 };
|
||||
struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 };
|
||||
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
|
||||
struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
|
||||
|
||||
uint32_t blob_flags = VIRTGPU_BLOB_FLAG_USE_SHAREABLE;
|
||||
if (bo->meta.use_flags & BO_USE_SW_MASK)
|
||||
|
|
@ -738,7 +697,7 @@ static int virtio_gpu_bo_create_blob(struct driver *drv, struct bo *bo)
|
|||
|
||||
static bool should_use_blob(struct driver *drv, uint32_t format, uint64_t use_flags)
|
||||
{
|
||||
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv;
|
||||
struct virgl_priv *priv = (struct virgl_priv *)drv->priv;
|
||||
|
||||
// TODO(gurchetansingh): remove once all minigbm users are blob-safe
|
||||
#ifndef VIRTIO_GPU_NEXT
|
||||
|
|
@ -768,46 +727,46 @@ static bool should_use_blob(struct driver *drv, uint32_t format, uint64_t use_fl
|
|||
}
|
||||
}
|
||||
|
||||
static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
|
||||
uint64_t use_flags)
|
||||
static int virgl_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
|
||||
uint64_t use_flags)
|
||||
{
|
||||
if (features[feat_resource_blob].enabled && features[feat_host_visible].enabled &&
|
||||
if (params[param_resource_blob].value && params[param_host_visible].value &&
|
||||
should_use_blob(bo->drv, format, use_flags))
|
||||
return virtio_gpu_bo_create_blob(bo->drv, bo);
|
||||
return virgl_bo_create_blob(bo->drv, bo);
|
||||
|
||||
if (features[feat_3d].enabled)
|
||||
return virtio_virgl_bo_create(bo, width, height, format, use_flags);
|
||||
if (params[param_3d].value)
|
||||
return virgl_3d_bo_create(bo, width, height, format, use_flags);
|
||||
else
|
||||
return virtio_dumb_bo_create(bo, width, height, format, use_flags);
|
||||
}
|
||||
|
||||
static int virtio_gpu_bo_destroy(struct bo *bo)
|
||||
static int virgl_bo_destroy(struct bo *bo)
|
||||
{
|
||||
if (features[feat_3d].enabled)
|
||||
if (params[param_3d].value)
|
||||
return drv_gem_bo_destroy(bo);
|
||||
else
|
||||
return drv_dumb_bo_destroy(bo);
|
||||
}
|
||||
|
||||
static void *virtio_gpu_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
|
||||
static void *virgl_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags)
|
||||
{
|
||||
if (features[feat_3d].enabled)
|
||||
return virtio_virgl_bo_map(bo, vma, plane, map_flags);
|
||||
if (params[param_3d].value)
|
||||
return virgl_3d_bo_map(bo, vma, plane, map_flags);
|
||||
else
|
||||
return drv_dumb_bo_map(bo, vma, plane, map_flags);
|
||||
}
|
||||
|
||||
static int virtio_gpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
|
||||
static int virgl_bo_invalidate(struct bo *bo, struct mapping *mapping)
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
struct drm_virtgpu_3d_transfer_from_host xfer = { 0 };
|
||||
struct drm_virtgpu_3d_wait waitcmd = { 0 };
|
||||
struct virtio_transfers_params xfer_params;
|
||||
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
|
||||
struct virgl_priv *priv = (struct virgl_priv *)bo->drv->priv;
|
||||
uint64_t host_write_flags;
|
||||
|
||||
if (!features[feat_3d].enabled)
|
||||
if (!params[param_3d].value)
|
||||
return 0;
|
||||
|
||||
// Invalidate is only necessary if the host writes to the buffer. The encoder and
|
||||
|
|
@ -822,8 +781,7 @@ static int virtio_gpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
|
|||
if ((bo->meta.use_flags & host_write_flags) == 0)
|
||||
return 0;
|
||||
|
||||
if (features[feat_resource_blob].enabled &&
|
||||
(bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
|
||||
if (params[param_resource_blob].value && (bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
|
||||
return 0;
|
||||
|
||||
xfer.bo_handle = mapping->vma->handle;
|
||||
|
|
@ -842,7 +800,7 @@ static int virtio_gpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
|
|||
|
||||
if ((bo->meta.use_flags & BO_USE_RENDERING) == 0) {
|
||||
// Unfortunately, the kernel doesn't actually pass the guest layer_stride
|
||||
// and guest stride to the host (compare virtio_gpu.h and virtgpu_drm.h).
|
||||
// and guest stride to the host (compare virgl.h and virtgpu_drm.h).
|
||||
// For gbm based resources, we can work around this by using the level field
|
||||
// to pass the stride to virglrenderer's gbm transfer code. However, we need
|
||||
// to avoid doing this for resources which don't rely on that transfer code,
|
||||
|
|
@ -852,15 +810,14 @@ static int virtio_gpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
|
|||
xfer.level = bo->meta.strides[0];
|
||||
}
|
||||
|
||||
if (virtio_gpu_supports_combination_natively(bo->drv, bo->meta.format,
|
||||
bo->meta.use_flags)) {
|
||||
if (virgl_supports_combination_natively(bo->drv, bo->meta.format, bo->meta.use_flags)) {
|
||||
xfer_params.xfers_needed = 1;
|
||||
xfer_params.xfer_boxes[0] = mapping->rect;
|
||||
} else {
|
||||
assert(virtio_gpu_supports_combination_through_emulation(bo->drv, bo->meta.format,
|
||||
bo->meta.use_flags));
|
||||
assert(virgl_supports_combination_through_emulation(bo->drv, bo->meta.format,
|
||||
bo->meta.use_flags));
|
||||
|
||||
virtio_gpu_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
|
||||
virgl_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
|
||||
}
|
||||
|
||||
for (i = 0; i < xfer_params.xfers_needed; i++) {
|
||||
|
|
@ -891,23 +848,22 @@ static int virtio_gpu_bo_invalidate(struct bo *bo, struct mapping *mapping)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int virtio_gpu_bo_flush(struct bo *bo, struct mapping *mapping)
|
||||
static int virgl_bo_flush(struct bo *bo, struct mapping *mapping)
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
struct drm_virtgpu_3d_transfer_to_host xfer = { 0 };
|
||||
struct drm_virtgpu_3d_wait waitcmd = { 0 };
|
||||
struct virtio_transfers_params xfer_params;
|
||||
struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)bo->drv->priv;
|
||||
struct virgl_priv *priv = (struct virgl_priv *)bo->drv->priv;
|
||||
|
||||
if (!features[feat_3d].enabled)
|
||||
if (!params[param_3d].value)
|
||||
return 0;
|
||||
|
||||
if (!(mapping->vma->map_flags & BO_MAP_WRITE))
|
||||
return 0;
|
||||
|
||||
if (features[feat_resource_blob].enabled &&
|
||||
(bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
|
||||
if (params[param_resource_blob].value && (bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE))
|
||||
return 0;
|
||||
|
||||
xfer.bo_handle = mapping->vma->handle;
|
||||
|
|
@ -925,20 +881,19 @@ static int virtio_gpu_bo_flush(struct bo *bo, struct mapping *mapping)
|
|||
}
|
||||
|
||||
// Unfortunately, the kernel doesn't actually pass the guest layer_stride and
|
||||
// guest stride to the host (compare virtio_gpu.h and virtgpu_drm.h). We can use
|
||||
// guest stride to the host (compare virgl.h and virtgpu_drm.h). We can use
|
||||
// the level to work around this.
|
||||
if (priv->host_gbm_enabled)
|
||||
xfer.level = bo->meta.strides[0];
|
||||
|
||||
if (virtio_gpu_supports_combination_natively(bo->drv, bo->meta.format,
|
||||
bo->meta.use_flags)) {
|
||||
if (virgl_supports_combination_natively(bo->drv, bo->meta.format, bo->meta.use_flags)) {
|
||||
xfer_params.xfers_needed = 1;
|
||||
xfer_params.xfer_boxes[0] = mapping->rect;
|
||||
} else {
|
||||
assert(virtio_gpu_supports_combination_through_emulation(bo->drv, bo->meta.format,
|
||||
bo->meta.use_flags));
|
||||
assert(virgl_supports_combination_through_emulation(bo->drv, bo->meta.format,
|
||||
bo->meta.use_flags));
|
||||
|
||||
virtio_gpu_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
|
||||
virgl_get_emulated_transfers_params(bo, &mapping->rect, &xfer_params);
|
||||
}
|
||||
|
||||
for (i = 0; i < xfer_params.xfers_needed; i++) {
|
||||
|
|
@ -973,7 +928,7 @@ static int virtio_gpu_bo_flush(struct bo *bo, struct mapping *mapping)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t virtio_gpu_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
|
||||
static uint32_t virgl_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
|
||||
{
|
||||
switch (format) {
|
||||
case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
|
||||
|
|
@ -987,7 +942,7 @@ static uint32_t virtio_gpu_resolve_format(struct driver *drv, uint32_t format, u
|
|||
* All of our host drivers prefer NV12 as their flexible media format.
|
||||
* If that changes, this will need to be modified.
|
||||
*/
|
||||
if (features[feat_3d].enabled)
|
||||
if (params[param_3d].value)
|
||||
return DRM_FORMAT_NV12;
|
||||
else
|
||||
return DRM_FORMAT_YVU420_ANDROID;
|
||||
|
|
@ -995,14 +950,13 @@ static uint32_t virtio_gpu_resolve_format(struct driver *drv, uint32_t format, u
|
|||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
static int virtio_gpu_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
|
||||
uint32_t offsets[DRV_MAX_PLANES])
|
||||
static int virgl_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES],
|
||||
uint32_t offsets[DRV_MAX_PLANES])
|
||||
{
|
||||
int ret;
|
||||
struct drm_virtgpu_resource_info_cros res_info = { 0 };
|
||||
|
||||
if (!features[feat_3d].enabled)
|
||||
if (!params[param_3d].value)
|
||||
return 0;
|
||||
|
||||
res_info.bo_handle = bo->handles[0].u32;
|
||||
|
|
@ -1027,17 +981,17 @@ static int virtio_gpu_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLAN
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct backend backend_virtio_gpu = {
|
||||
.name = "virtio_gpu",
|
||||
.init = virtio_gpu_init,
|
||||
.close = virtio_gpu_close,
|
||||
.bo_create = virtio_gpu_bo_create,
|
||||
.bo_destroy = virtio_gpu_bo_destroy,
|
||||
const struct backend virtgpu_virgl = {
|
||||
.name = "virtgpu_virgl",
|
||||
.init = virgl_init,
|
||||
.close = virgl_close,
|
||||
.bo_create = virgl_bo_create,
|
||||
.bo_destroy = virgl_bo_destroy,
|
||||
.bo_import = drv_prime_bo_import,
|
||||
.bo_map = virtio_gpu_bo_map,
|
||||
.bo_map = virgl_bo_map,
|
||||
.bo_unmap = drv_bo_munmap,
|
||||
.bo_invalidate = virtio_gpu_bo_invalidate,
|
||||
.bo_flush = virtio_gpu_bo_flush,
|
||||
.resolve_format = virtio_gpu_resolve_format,
|
||||
.resource_info = virtio_gpu_resource_info,
|
||||
.bo_invalidate = virgl_bo_invalidate,
|
||||
.bo_flush = virgl_bo_flush,
|
||||
.resolve_format = virgl_resolve_format,
|
||||
.resource_info = virgl_resource_info
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue