diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc index b01a0a9..06013c9 100644 --- a/cros_gralloc/cros_gralloc_driver.cc +++ b/cros_gralloc/cros_gralloc_driver.cc @@ -27,6 +27,11 @@ // DRM Card nodes start at 0 #define DRM_CARD_NODE_START 0 +#define IVSH_WIDTH 1600 +#define IVSH_HEIGHT 900 + +#define IVSH_DEVICE_NUM 2 + class cros_gralloc_driver_preloader { public: @@ -109,6 +114,54 @@ cros_gralloc_driver *cros_gralloc_driver::get_instance() close(fd); \ } +int32_t cros_gralloc_driver::reload() +{ + int fd; + drmVersionPtr version; + char const *str = "%s/renderD%d"; + char *node; + + // Max probe two ivshm node, the first one is used for screen cast. + for (uint32_t i = drv_num_; i < drv_num_ + IVSH_DEVICE_NUM; 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; + } + + drmFreeVersion(version); + drv_ivshmem_ = drv_create(fd); + if (!drv_ivshmem_) { + drv_loge("Failed to create driver\n"); + close(fd); + continue;; + } + + if (drv_init(drv_ivshmem_, gpu_grp_type_)) { + drv_loge("Failed to init driver\n"); + DRV_DESTROY(drv_ivshmem_) + continue;; + } + if (drv_virtgpu_is_ivshm(drv_ivshmem_)) { + drv_logi("New added node is virtio-ivishmem node"); + return 0; + } else { + drv_logi("New added node is NOT virtio-ivishmem node"); + DRV_DESTROY(drv_ivshmem_) + continue; + } + } + return -ENODEV; +} + cros_gralloc_driver::cros_gralloc_driver() { /* @@ -134,9 +187,9 @@ cros_gralloc_driver::cros_gralloc_driver() char *node_name[render_num] = {}; int availabe_node = 0; int virtio_node_idx = -1; + int ivshm_node_idx = -1; int renderer_idx = -1; int video_idx = -1; - uint32_t gpu_grp_type = 0; char buf[PROP_VALUE_MAX]; property_get("ro.product.device", buf, "unknown"); @@ -149,6 +202,10 @@ cros_gralloc_driver::cros_gralloc_driver() DRV_DESTROY(drv_kms_) DRV_DESTROY(drv_render_) + if (drv_ivshmem_) { + DRV_DESTROY(drv_ivshmem_) + } + for (uint32_t i = min_render_node; i < max_render_node; i++) { if (asprintf(&node, render_nodes_fmt, DRM_DIR_NAME, i) < 0) continue; @@ -177,7 +234,10 @@ cros_gralloc_driver::cros_gralloc_driver() continue; if (!strcmp(version->name, "virtio_gpu")) { - virtio_node_idx = availabe_node; + if (virtio_node_idx == -1) + virtio_node_idx = availabe_node; + else if (ivshm_node_idx == -1) + ivshm_node_idx = availabe_node; } if (!strcmp(version->name, "i915")) { @@ -201,23 +261,11 @@ cros_gralloc_driver::cros_gralloc_driver() drmFreeVersion(version); } - if (availabe_node > 0) { - switch (availabe_node) { - // only have one render node, is GVT-d/BM/VirtIO - case 1: - gpu_grp_type = (virtio_node_idx != -1)? ONE_GPU_VIRTIO: ONE_GPU_INTEL; - break; - // is SR-IOV or iGPU + dGPU - case 2: - gpu_grp_type = (virtio_node_idx != -1)? TWO_GPU_IGPU_VIRTIO: TWO_GPU_IGPU_DGPU; - break; - // is SR-IOV + dGPU - case 3: - gpu_grp_type = THREE_GPU_IGPU_VIRTIO_DGPU; - // TO-DO: the 3rd node is i915 or others. - break; - } + drv_num_ = DRM_RENDER_NODE_START + availabe_node; + if (availabe_node > 0) { + if ((renderer_idx != -1) && (video_idx != -1) && (video_idx != renderer_idx)) + gpu_grp_type_ |= GPU_TYPE_DUAL_IGPU_DGPU; // if no i915 node found if (renderer_idx == -1) { if (virtio_node_idx != -1) { @@ -262,31 +310,48 @@ cros_gralloc_driver::cros_gralloc_driver() drv_kms_ = drv_render_; } + if (ivshm_node_idx != -1) { + if (!(drv_ivshmem_ = drv_create(node_fd[ivshm_node_idx]))) { + drv_loge("Failed to create driver for the ivshm device with card id %d\n", + ivshm_node_idx); + close(node_fd[ivshm_node_idx]); + } + } + // Init drv - DRV_INIT(drv_render_, gpu_grp_type, renderer_idx) + DRV_INIT(drv_render_, gpu_grp_type_, renderer_idx) if (video_idx != renderer_idx) - DRV_INIT(drv_video_, gpu_grp_type, video_idx) + DRV_INIT(drv_video_, gpu_grp_type_, video_idx) if ((virtio_node_idx != -1) && (virtio_node_idx != renderer_idx)) - DRV_INIT(drv_kms_, gpu_grp_type, virtio_node_idx) - if (drv_kms_ && (virtio_node_idx != renderer_idx)) { + DRV_INIT(drv_kms_, gpu_grp_type_, virtio_node_idx) + if (drv_kms_ && (virtio_node_idx != renderer_idx) && (drv_kms_ != drv_render_)) { bool virtiopic_with_blob = drv_virtpci_with_blob(drv_kms_); // The virtio pci device with blob feature could import buffers // from i915, otherwise need use virtio to allocate scanout // non-video buffers. if (virtiopic_with_blob) { - drv_logi("virtio gpu device with blob\n"); + drv_logi("Virtio gpu device with blob\n"); if ((drv_kms_ != drv_render_) && drv_kms_) DRV_DESTROY(drv_kms_) drv_kms_ = drv_render_; } else { - drv_logi("virtio ivshmem device or no blob\n"); + drv_logi("Virtio ivshmem device or no blob\n"); + } + } + if (ivshm_node_idx != -1) { + DRV_INIT(drv_ivshmem_, gpu_grp_type_, ivshm_node_idx) + if (drv_virtgpu_is_ivshm(drv_ivshmem_)) { + drv_logi("Node is virtio-ivishmem node"); + } else { + drv_logi("Node is NOT virtio-ivishmem node"); + DRV_DESTROY(drv_ivshmem_) } } } for (int i = 0; i < availabe_node; i++) { free(node_name[i]); - if ((i != renderer_idx) && (i != video_idx) && (i != virtio_node_idx)) { + if ((i != renderer_idx) && (i != video_idx) && (i != virtio_node_idx) && (i != ivshm_node_idx)) { close(node_fd[i]); } } @@ -322,6 +387,14 @@ bool cros_gralloc_driver::is_video_format(const struct cros_gralloc_buffer_descr return true; } +bool cros_gralloc_driver::use_ivshm_drv(const struct cros_gralloc_buffer_descriptor *descriptor) +{ + if ((descriptor->use_flags & BO_USE_SCANOUT) && + (descriptor->width == IVSH_WIDTH) && (descriptor->height == IVSH_HEIGHT)) + return true; + return false; +} + bool cros_gralloc_driver::get_resolved_format_and_use_flags( const struct cros_gralloc_buffer_descriptor *descriptor, uint32_t *out_format, uint64_t *out_use_flags) @@ -331,7 +404,9 @@ bool cros_gralloc_driver::get_resolved_format_and_use_flags( struct combination *combo; struct driver *drv = is_video_format(descriptor) ? drv_video_ : drv_render_; - if ((descriptor->use_flags & BO_USE_SCANOUT) && !(is_video_format(descriptor))) + if (drv_ivshmem_ && use_ivshm_drv(descriptor)) { + drv = drv_ivshmem_; + } else if ((descriptor->use_flags & BO_USE_SCANOUT) && !(is_video_format(descriptor))) drv = drv_kms_; if (mt8183_camera_quirk_ && (descriptor->use_flags & BO_USE_CAMERA_READ) && @@ -377,7 +452,13 @@ bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descript uint32_t resolved_format; uint64_t resolved_use_flags; struct driver *drv = is_video_format(descriptor) ? drv_video_ : drv_render_; - if ((descriptor->use_flags & BO_USE_SCANOUT) && !(is_video_format(descriptor))) + if (!drv_ivshmem_ && (descriptor->width == IVSH_WIDTH) && (descriptor->height == IVSH_HEIGHT)) { + if (reload()) { + } + } + if (drv_ivshmem_ && use_ivshm_drv(descriptor)) { + drv = drv_ivshmem_; + } else if ((descriptor->use_flags & BO_USE_SCANOUT) && !(is_video_format(descriptor))) drv = drv_kms_; uint32_t max_texture_size = drv_get_max_texture_2d_size(drv); if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags)) @@ -428,9 +509,10 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto struct driver *drv; drv = is_video_format(descriptor) ? drv_video_ : drv_render_; - if ((descriptor->use_flags & BO_USE_SCANOUT) && (!is_video_format(descriptor))) { + if (drv_ivshmem_ && use_ivshm_drv(descriptor)) { + drv = drv_ivshmem_; + } else if ((descriptor->use_flags & BO_USE_SCANOUT) && !(is_video_format(descriptor))) drv = drv_kms_; - } if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags)) { ALOGE("Failed to resolve format and use_flags."); @@ -585,7 +667,9 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle) .use_flags = hnd->use_flags, }; drv = is_video_format(&descriptor) ? drv_video_ : drv_render_; - if ((hnd->use_flags & BO_USE_SCANOUT) && (!is_video_format(&descriptor))) + if (drv_ivshmem_ && use_ivshm_drv(&descriptor)) { + drv = drv_ivshmem_; + } else if ((hnd->use_flags & BO_USE_SCANOUT) && !(is_video_format(&descriptor))) drv = drv_kms_; auto hnd_it = handles_.find(hnd); diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h index befbe8b..89bce9f 100644 --- a/cros_gralloc/cros_gralloc_driver.h +++ b/cros_gralloc/cros_gralloc_driver.h @@ -8,6 +8,7 @@ #define CROS_GRALLOC_DRIVER_H #include "cros_gralloc_buffer.h" +#include "../drv_priv.h" #include #include @@ -61,6 +62,8 @@ class cros_gralloc_driver ~cros_gralloc_driver(); bool is_initialized(); bool is_video_format(const struct cros_gralloc_buffer_descriptor *descriptor); + bool use_ivshm_drv(const struct cros_gralloc_buffer_descriptor *descriptor); + int32_t reload(); cros_gralloc_buffer *get_buffer(cros_gralloc_handle_t hnd); bool get_resolved_format_and_use_flags(const struct cros_gralloc_buffer_descriptor *descriptor, @@ -90,6 +93,9 @@ class cros_gralloc_driver struct driver *drv_video_ = nullptr; // the drv_kms_ is used to allocate scanout non-video buffer. struct driver *drv_kms_ = nullptr; + struct driver *drv_ivshmem_ = nullptr; + uint32_t drv_num_ = 0; + uint64_t gpu_grp_type_ = GPU_TYPE_NORMAL; std::mutex mutex_; std::unordered_map> buffers_; std::unordered_map handles_; diff --git a/drv.c b/drv.c index 0c1be8b..43a430d 100644 --- a/drv.c +++ b/drv.c @@ -845,3 +845,15 @@ bool drv_virtpci_with_blob(struct driver * drv) } return ret; } + +bool drv_virtgpu_is_ivshm(struct driver * drv) +{ + bool ret = false; + assert(drv); + assert(drv->backend); + + if (drv->backend->virtgpu_is_ivshm) { + ret = drv->backend->virtgpu_is_ivshm(drv); + } + return ret; +} diff --git a/drv.h b/drv.h index 6aacdc1..a178cfc 100644 --- a/drv.h +++ b/drv.h @@ -253,6 +253,8 @@ uint32_t drv_get_max_texture_2d_size(struct driver *drv); bool drv_virtpci_with_blob(struct driver * drv); +bool drv_virtgpu_is_ivshm(struct driver * drv); + enum drv_log_level { DRV_LOGV, DRV_LOGD, diff --git a/drv_priv.h b/drv_priv.h index 167c73a..9a38f49 100644 --- a/drv_priv.h +++ b/drv_priv.h @@ -60,13 +60,8 @@ struct combination { uint64_t use_flags; }; -enum CIV_GPU_TYPE { - ONE_GPU_INTEL = 1, - ONE_GPU_VIRTIO, - TWO_GPU_IGPU_VIRTIO, - TWO_GPU_IGPU_DGPU, - THREE_GPU_IGPU_VIRTIO_DGPU -}; +#define GPU_TYPE_NORMAL 0 +#define GPU_TYPE_DUAL_IGPU_DGPU (1ull << 0) struct driver { int fd; @@ -74,7 +69,7 @@ struct driver { void *priv; pthread_mutex_t buffer_table_lock; void *buffer_table; - uint32_t gpu_grp_type; // enum CIV_GPU_TYPE + uint64_t gpu_grp_type; pthread_mutex_t mappings_lock; struct drv_array *mappings; struct drv_array *combos; @@ -112,6 +107,7 @@ struct backend { uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier); uint32_t (*get_max_texture_2d_size)(struct driver *drv); bool (*virtpci_with_blob)(struct driver *drv); + bool (*virtgpu_is_ivshm)(struct driver *drv); }; // clang-format off diff --git a/i915.c b/i915.c index 768ff12..204896b 100644 --- a/i915.c +++ b/i915.c @@ -443,9 +443,7 @@ static int i915_add_combinations(struct driver *drv) if (i915_has_tile4(i915)) { // in dual gpu case, only alloc x-tiling for dgpu for render - if (((drv->gpu_grp_type == TWO_GPU_IGPU_DGPU) || - (drv->gpu_grp_type == THREE_GPU_IGPU_VIRTIO_DGPU)) - && (i915->graphics_version >= 125)) + if ((drv->gpu_grp_type & GPU_TYPE_DUAL_IGPU_DGPU) && (i915->graphics_version >= 125)) return 0; struct format_metadata metadata_4_tiled = { .tiling = I915_TILING_4, @@ -476,8 +474,7 @@ static int i915_add_combinations(struct driver *drv) struct format_metadata metadata_y_tiled = { .tiling = I915_TILING_Y, .priority = 3, .modifier = I915_FORMAT_MOD_Y_TILED }; - if ((drv->gpu_grp_type == TWO_GPU_IGPU_DGPU) || - (drv->gpu_grp_type == THREE_GPU_IGPU_VIRTIO_DGPU)) { + if (drv->gpu_grp_type & GPU_TYPE_DUAL_IGPU_DGPU) { scanout_and_render_not_linear = unset_flags(scanout_and_render, BO_USE_SCANOUT); } /* Support y-tiled NV12 and P010 for libva */ diff --git a/virtgpu_virgl.c b/virtgpu_virgl.c index 87de3c6..f969e64 100644 --- a/virtgpu_virgl.c +++ b/virtgpu_virgl.c @@ -1183,6 +1183,11 @@ static bool virgl_virtpci_with_blob(struct driver *drv) { return ((prv->dev_feature & VIRTGPU_PARAM_QUERY_DEV_BIT ) && (prv->dev_feature & VIRTGPU_PARAM_RESOURCE_BLOB_BIT)); } +static bool virgl_drv_virtgpu_is_ivshm(struct driver *drv) { + struct virgl_priv *prv = (struct virgl_priv *)drv->priv; + return !(prv->dev_feature & VIRTGPU_PARAM_QUERY_DEV_BIT); +} + const struct backend virtgpu_virgl = { .name = "virtgpu_virgl", .init = virgl_init, .close = virgl_close, @@ -1198,4 +1203,5 @@ const struct backend virtgpu_virgl = { .name = "virtgpu_virgl", virgl_resolve_format_and_use_flags, .resource_info = virgl_resource_info, .get_max_texture_2d_size = virgl_get_max_texture_2d_size, - .virtpci_with_blob = virgl_virtpci_with_blob }; + .virtpci_with_blob = virgl_virtpci_with_blob, + .virtgpu_is_ivshm = virgl_drv_virtgpu_is_ivshm };