From 76281b0faac65dbb5e786085b013ffc31b0f4d26 Mon Sep 17 00:00:00 2001 From: HeYue Date: Wed, 24 Jan 2024 09:57:05 +0800 Subject: [PATCH 1/2] Use virtio ivshmem to allocate scanout buffer with certain resolution Add function to detact the render node hotplug. signed-off-by: HeYue --- cros_gralloc/cros_gralloc_driver.cc | 220 ++++++++++++++++++++++++++-- cros_gralloc/cros_gralloc_driver.h | 5 + cros_gralloc/cros_gralloc_handle.h | 1 - drv_priv.h | 3 +- 4 files changed, 213 insertions(+), 16 deletions(-) diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc index 84893c86..94825ffd 100644 --- a/cros_gralloc/cros_gralloc_driver.cc +++ b/cros_gralloc/cros_gralloc_driver.cc @@ -19,8 +19,11 @@ #include "i915_private_android.h" #endif +#define IVSH_WIDTH 1920 +#define IVSH_HEIGHT 1080 + // drv_render_ aim to open the render node -cros_gralloc_driver::cros_gralloc_driver() : drv_render_(nullptr) +cros_gralloc_driver::cros_gralloc_driver() : drv_render_(nullptr), drv_ivshmem_(nullptr) { } @@ -35,6 +38,106 @@ cros_gralloc_driver::~cros_gralloc_driver() drv_render_ = nullptr; close(fd); } + + if (drv_ivshmem_) { + int fd = drv_get_fd(drv_ivshmem_); + drv_destroy(drv_ivshmem_); + drv_ivshmem_ = nullptr; + close(fd); + } +} + +int32_t cros_gralloc_driver::reload() +{ + int fd; + drmVersionPtr version; + char const *str = "%s/renderD%d"; + const char *undesired[2] = { "vgem", nullptr }; + uint32_t min_node = 128; + uint32_t max_node = (min_node + drv_num + 2); + uint32_t j; + char *node; + + const int render_num = 10; + const int name_length = 50; + int availabe_node = 0; + uint32_t gpu_grp_type = 0; + + availabe_node = 0; + for (uint32_t i = min_node; i < max_node; i++) { + if (asprintf(&node, str, DRM_DIR_NAME, i) < 0) + continue; + + fd = open(node, O_RDWR, 0); + free(node); + if (fd < 0) + continue; + + version = drmGetVersion(fd); + if (!version) { + close(fd); + continue; + } + + for (j = 0; j < ARRAY_SIZE(undesired); j++) { + if (undesired[j] && !strcmp(version->name, undesired[j])) { + drmFreeVersion(version); + close(fd); + break; + } + } + + // hit any of undesired render node + if (j < ARRAY_SIZE(undesired)) + continue; + + availabe_node++; + close(fd); + drmFreeVersion(version); + } + + // have the ivshemem node + if ((availabe_node > drv_num) && !drv_ivshmem_) { + drv_num = availabe_node; + if (asprintf(&node, str, DRM_DIR_NAME, (min_node + availabe_node - 1)) < 0) + drv_log("Open ivshmem node fail\n"); + fd = open(node, O_RDWR, 0); + free(node); + + if (fd < 0) { + return -ENODEV; + } + + version = drmGetVersion(fd); + if (!version) { + close(fd); + return -ENODEV; + } + + if (strcmp(version->name, "virtio_gpu")) { + drv_log("New added node is not ivshmem node\n"); + close(fd); + drmFreeVersion(version); + return -ENODEV; + } + + drv_ivshmem_ = drv_create(fd); + if (!drv_ivshmem_) { + drv_log("Failed to create driver for ivshmem device\n"); + close(fd); + return -ENODEV; + } + gpu_grp_type = THREE_GPU_IGPU_VIRTIO_IVSHMEM; + + if (drv_ivshmem_) { + if (drv_init(drv_ivshmem_, gpu_grp_type)) { + drv_log("Failed to init ivshmem driver\n"); + return -ENODEV; + } + } + } + + return 0; } int32_t cros_gralloc_driver::init() @@ -72,6 +175,13 @@ int32_t cros_gralloc_driver::init() close(fd); } + if (drv_ivshmem_) { + int fd = drv_get_fd(drv_ivshmem_); + drv_destroy(drv_ivshmem_); + drv_ivshmem_ = nullptr; + close(fd); + } + for (uint32_t i = min_node; i < max_node; i++) { if (asprintf(&node, str, DRM_DIR_NAME, i) < 0) continue; @@ -111,6 +221,7 @@ int32_t cros_gralloc_driver::init() } // open the first render node + drv_num = availabe_node; if (availabe_node > 0) { drv_render_ = drv_create(node_fd[0]); if (!drv_render_) { @@ -124,12 +235,13 @@ int32_t cros_gralloc_driver::init() case 1: if (!drv_render_) goto fail; - gpu_grp_type = (virtio_node_idx != -1)? ONE_GPU_VIRTIO: ONE_GPU_INTEL; + gpu_grp_type = (virtio_node_idx != -1) ? ONE_GPU_VIRTIO : ONE_GPU_INTEL; break; // is SR-IOV or iGPU + dGPU case 2: close(node_fd[1]); if (virtio_node_idx != -1) { + is_sriov_mode = true; gpu_grp_type = TWO_GPU_IGPU_VIRTIO; } else { gpu_grp_type = TWO_GPU_IGPU_DGPU; @@ -137,13 +249,19 @@ int32_t cros_gralloc_driver::init() break; // is SR-IOV + dGPU case 3: + close(node_fd[1]); + is_sriov_mode = true; if (!strcmp(node_name[1], "i915")) { - close(node_fd[1]); - } - if (virtio_node_idx != -1) { - close(node_fd[virtio_node_idx]); + gpu_grp_type = THREE_GPU_IGPU_VIRTIO_DGPU; + } else { + drv_ivshmem_ = drv_create(node_fd[2]); + if (!drv_ivshmem_) { + drv_log("Failed to create driver for ivshmem device\n"); + close(node_fd[2]); + goto fail; + } + gpu_grp_type = THREE_GPU_IGPU_VIRTIO_IVSHMEM; } - gpu_grp_type = THREE_GPU_IGPU_VIRTIO_DGPU; // TO-DO: the 3rd node is i915 or others. break; } @@ -154,6 +272,13 @@ int32_t cros_gralloc_driver::init() goto fail; } } + + if (drv_ivshmem_) { + if (drv_init(drv_ivshmem_, gpu_grp_type)) { + drv_log("Failed to init ivshmem driver\n"); + goto fail; + } + } } if (!drv_render_) @@ -169,6 +294,13 @@ int32_t cros_gralloc_driver::init() drv_render_ = nullptr; } + if (drv_ivshmem_) { + fd = drv_get_fd(drv_ivshmem_); + drv_destroy(drv_ivshmem_); + close(fd); + drv_ivshmem_ = nullptr; + } + return -ENODEV; } @@ -177,7 +309,19 @@ bool cros_gralloc_driver::is_supported(struct cros_gralloc_buffer_descriptor *de struct combination *combo; uint32_t resolved_format; bool supported; - struct driver *drv = drv_render_; + struct driver *drv; + if (!drv_ivshmem_) { + if (reload()) { + } + } + + if (drv_ivshmem_ && (descriptor->use_flags & BO_USE_SCANOUT) && + (descriptor->width == IVSH_WIDTH) && (descriptor->height == IVSH_HEIGHT)) { + drv = drv_ivshmem_; + use_ivshmem = true; + } else { + drv = drv_render_; + } resolved_format = drv_resolve_format(drv, descriptor->drm_format, descriptor->use_flags); combo = drv_get_combination(drv, resolved_format, descriptor->use_flags); @@ -185,9 +329,26 @@ bool cros_gralloc_driver::is_supported(struct cros_gralloc_buffer_descriptor *de supported = (combo != nullptr); if (!supported && (descriptor->use_flags & BO_USE_SCANOUT)) { - descriptor->use_flags &= ~BO_USE_SCANOUT; - combo = drv_get_combination(drv, resolved_format, descriptor->use_flags); + if (is_sriov_mode) { + /* if kmsro is enabled, it is scanout buffer and not used for video, + * don't need remove scanout flag */ + if (!IsSupportedYUVFormat(descriptor->droid_format)) { + combo = drv_get_combination(drv, resolved_format, + (descriptor->use_flags) & + (~BO_USE_SCANOUT)); + supported = (combo != nullptr); + } else { + drv = drv_render_; + descriptor->use_flags &= ~BO_USE_SCANOUT; + combo = drv_get_combination(drv, resolved_format, + descriptor->use_flags); supported = (combo != nullptr); + } + } else { + descriptor->use_flags &= ~BO_USE_SCANOUT; + combo = drv_get_combination(drv, resolved_format, descriptor->use_flags); + supported = (combo != nullptr); + } } return supported; } @@ -232,7 +393,19 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto struct cros_gralloc_handle *hnd; struct driver *drv; - drv = drv_render_; + + if (!drv_ivshmem_) { + if (reload()) { + } + } + + if (drv_ivshmem_ && (descriptor->use_flags & BO_USE_SCANOUT) && + (descriptor->width == IVSH_WIDTH) && (descriptor->height == IVSH_HEIGHT)) { + use_ivshmem = true; + drv = drv_ivshmem_; + } else { + drv = drv_render_; + } resolved_format = drv_resolve_format(drv, descriptor->drm_format, descriptor->use_flags); use_flags = descriptor->use_flags; @@ -309,7 +482,6 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto * native_handle_delete(). */ hnd = static_cast(malloc(num_bytes)); - hnd->from_kms = false; // not used, just set a default value. keep this member to be backward compatible. hnd->base.version = sizeof(hnd->base); hnd->base.numFds = num_fds; hnd->base.numInts = num_ints; @@ -373,13 +545,22 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle) std::lock_guard lock(mutex_); struct driver *drv; + if (!drv_ivshmem_) { + if (reload()) { + } + } + auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { drv_log("Invalid handle.\n"); return -EINVAL; } - drv = drv_render_; + if (drv_ivshmem_ && use_ivshmem) { + drv = drv_ivshmem_; + } else { + drv = drv_render_; + } auto buffer = get_buffer(hnd); if (buffer) { @@ -641,7 +822,18 @@ int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle, uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t usage) { - struct driver *drv = drv_render_; + struct driver *drv; + + if (!drv_ivshmem_) { + if (reload()) { + } + } + + if (drv_ivshmem_ && use_ivshmem) { + drv = drv_ivshmem_; + } else { + drv = drv_render_; + } return drv_resolve_format(drv, drm_format, usage); } diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h index bcd3ba20..1d1bdba6 100644 --- a/cros_gralloc/cros_gralloc_driver.h +++ b/cros_gralloc/cros_gralloc_driver.h @@ -53,6 +53,7 @@ class cros_gralloc_driver void for_each_handle(const std::function &function); bool IsSupportedYUVFormat(uint32_t droid_format); + int32_t reload(); private: cros_gralloc_driver(cros_gralloc_driver const &); @@ -60,6 +61,10 @@ class cros_gralloc_driver cros_gralloc_buffer *get_buffer(cros_gralloc_handle_t hnd); struct driver *drv_render_; + struct driver *drv_ivshmem_; + bool use_ivshmem = false; + int32_t drv_num = 0; + bool is_sriov_mode = false; std::mutex mutex_; std::unordered_map buffers_; std::unordered_map> diff --git a/cros_gralloc/cros_gralloc_handle.h b/cros_gralloc/cros_gralloc_handle.h index ae8e6793..4c538996 100644 --- a/cros_gralloc/cros_gralloc_handle.h +++ b/cros_gralloc/cros_gralloc_handle.h @@ -27,7 +27,6 @@ struct cros_gralloc_handle { uint32_t strides[DRV_MAX_PLANES]; uint32_t offsets[DRV_MAX_PLANES]; uint32_t sizes[DRV_MAX_PLANES]; - bool from_kms; uint32_t id; uint32_t width; uint32_t height; diff --git a/drv_priv.h b/drv_priv.h index 5f500906..523f2eeb 100644 --- a/drv_priv.h +++ b/drv_priv.h @@ -54,7 +54,8 @@ enum CIV_GPU_TYPE { ONE_GPU_VIRTIO, TWO_GPU_IGPU_VIRTIO, TWO_GPU_IGPU_DGPU, - THREE_GPU_IGPU_VIRTIO_DGPU + THREE_GPU_IGPU_VIRTIO_DGPU, + THREE_GPU_IGPU_VIRTIO_IVSHMEM }; struct driver { From 366ec927ca8cb5796090e3c7a71a332e5ccfd57e Mon Sep 17 00:00:00 2001 From: HeYue Date: Wed, 24 Jan 2024 12:56:58 +0800 Subject: [PATCH 2/2] Add the virtio tiling Y support Signed-off-by: HeYue --- virtio_gpu.c | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/virtio_gpu.c b/virtio_gpu.c index f338e0f1..dc5d0eb2 100644 --- a/virtio_gpu.c +++ b/virtio_gpu.c @@ -17,6 +17,7 @@ #include "util.h" #include "virgl_hw.h" #include "virtgpu_drm.h" +#include #ifndef PAGE_SIZE #define PAGE_SIZE 0x1000 @@ -585,6 +586,11 @@ static int virtio_gpu_init(struct driver *drv) virtio_gpu_init_features_and_caps(drv); + struct format_metadata metadata; + metadata.tiling = I915_TILING_Y; + metadata.priority = 3; + metadata.modifier = I915_FORMAT_MOD_Y_TILED; + if (features[feat_3d].enabled) { /* This doesn't mean host can scanout everything, it just means host * hypervisor can show it. */ @@ -595,21 +601,22 @@ static int virtio_gpu_init(struct driver *drv) ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA, BO_USE_TEXTURE_MASK); } else { + + uint64_t render = BO_USE_RENDER_MASK | ~BO_USE_LINEAR; /* Virtio primary plane only allows this format. */ - virtio_gpu_add_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA, - BO_USE_RENDER_MASK | BO_USE_SCANOUT); + virtio_gpu_add_combination(drv, DRM_FORMAT_XRGB8888, &metadata, + render | 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); + virtio_gpu_add_combination(drv, DRM_FORMAT_ARGB8888, &metadata, + render | 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); + ARRAY_SIZE(render_target_formats), &metadata, render); virtio_gpu_add_combinations(drv, dumb_texture_source_formats, - ARRAY_SIZE(dumb_texture_source_formats), - &LINEAR_METADATA, BO_USE_TEXTURE_MASK); + ARRAY_SIZE(dumb_texture_source_formats), &metadata, + render); 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, @@ -639,11 +646,14 @@ static int virtio_gpu_init(struct driver *drv) drv_modify_combination(drv, DRM_FORMAT_R16, &LINEAR_METADATA, BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER); #ifdef USE_GRALLOC1 - drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &LINEAR_METADATA, + drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &metadata, BO_USE_CAMERA_WRITE | BO_USE_CAMERA_READ); #endif - return drv_modify_linear_combinations(drv); + drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); + drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); + + return 0; } static void virtio_gpu_close(struct driver *drv) @@ -655,10 +665,26 @@ static void virtio_gpu_close(struct driver *drv) static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, uint64_t use_flags) { - if (features[feat_3d].enabled) + struct combination *combo = drv_get_combination(bo->drv, format, (use_flags & ~BO_USE_SCANOUT)); + if (!combo) + return -EINVAL; + uint64_t modifier = combo->metadata.modifier; + switch (modifier) { + case DRM_FORMAT_MOD_LINEAR: + bo->meta.tiling = I915_TILING_NONE; + break; + case I915_FORMAT_MOD_Y_TILED: + bo->meta.tiling = I915_TILING_Y; + break; + } + + bo->meta.format_modifiers[0] = modifier; + + if (features[feat_3d].enabled) { return virtio_virgl_bo_create(bo, width, height, format, use_flags); - else + } else { return virtio_dumb_bo_create(bo, width, height, format, use_flags); + } } static int virtio_gpu_bo_destroy(struct bo *bo)