Skip to content

Commit

Permalink
Use virtio ivshmem to allocate scanout buffer with certain resolution
Browse files Browse the repository at this point in the history
Add bg thread to detact the render node hotplug

signed-off-by: HeYue <[email protected]>
  • Loading branch information
yhe39 committed Feb 29, 2024
1 parent f6c1d6e commit fa41117
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 17 deletions.
200 changes: 185 additions & 15 deletions cros_gralloc/cros_gralloc_driver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

#include <cstdlib>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <xf86drm.h>

Expand All @@ -19,6 +22,12 @@
#include "i915_private_android.h"
#endif

#define IVSH_WIDTH 1920
#define IVSH_HEIGHT 1080

struct driver *cros_gralloc_driver::drv_ivshmem_ = nullptr;
int32_t cros_gralloc_driver::drv_num = 0;

// drv_render_ aim to open the render node
cros_gralloc_driver::cros_gralloc_driver() : drv_render_(nullptr)
{
Expand All @@ -35,6 +44,94 @@ 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);
}
//pthread_join(tid, NULL);
}

void *cros_gralloc_driver::reload2(void *arg)
{
int fd;
drmVersionPtr version;
char const *str = "%s/renderD%d";
const char *undesired[2] = { "vgem", nullptr };
uint32_t num_nodes = 63;
uint32_t min_node = 128;
uint32_t max_node = (min_node + num_nodes);
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;
bool in_loop = true;

do {
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);
drv_ivshmem_ = drv_create(fd);
if (!drv_ivshmem_) {
drv_log("Failed to create driver for ivshmem device\n");
close(fd);
break;
}
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");
break;
}
}
in_loop = false;
}
sleep(1);
} while (in_loop);
pthread_exit(NULL);
}

int32_t cros_gralloc_driver::init()
Expand Down Expand Up @@ -72,6 +169,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;
Expand Down Expand Up @@ -111,6 +215,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_) {
Expand All @@ -124,26 +229,33 @@ 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;
}
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;
}
Expand All @@ -154,11 +266,24 @@ 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_)
return -ENODEV;

if (!drv_ivshmem_) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, reload2, NULL);
}
return 0;

fail:
Expand All @@ -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;
}

Expand All @@ -177,17 +309,42 @@ 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_ && (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);

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;
}
Expand Down Expand Up @@ -230,9 +387,15 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto

struct bo *bo;
struct cros_gralloc_handle *hnd;

struct driver *drv;
drv = drv_render_;

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;
Expand Down Expand Up @@ -309,7 +472,6 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto
* native_handle_delete().
*/
hnd = static_cast<struct cros_gralloc_handle *>(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;
Expand Down Expand Up @@ -379,7 +541,11 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
return -EINVAL;
}

drv = drv_render_;
if (drv_ivshmem_ && use_ivshmem) {
drv = drv_ivshmem_;
} else {
drv = drv_render_;
}

auto buffer = get_buffer(hnd);
if (buffer) {
Expand Down Expand Up @@ -641,8 +807,12 @@ 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_ && use_ivshmem) {
drv = drv_ivshmem_;
} else {
drv = drv_render_;
}
return drv_resolve_format(drv, drm_format, usage);
}

Expand Down
6 changes: 6 additions & 0 deletions cros_gralloc/cros_gralloc_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,19 @@ class cros_gralloc_driver
void for_each_handle(const std::function<void(cros_gralloc_handle_t)> &function);

bool IsSupportedYUVFormat(uint32_t droid_format);
static void *reload2(void *arg);

private:
cros_gralloc_driver(cros_gralloc_driver const &);
cros_gralloc_driver operator=(cros_gralloc_driver const &);
cros_gralloc_buffer *get_buffer(cros_gralloc_handle_t hnd);

struct driver *drv_render_;
static struct driver *drv_ivshmem_;
bool use_ivshmem = false;
static int32_t drv_num;
bool is_sriov_mode = false;
pthread_t tid;
std::mutex mutex_;
std::unordered_map<uint32_t, cros_gralloc_buffer *> buffers_;
std::unordered_map<cros_gralloc_handle_t, std::pair<cros_gralloc_buffer *, int32_t>>
Expand Down
1 change: 0 additions & 1 deletion cros_gralloc/cros_gralloc_handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion drv_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit fa41117

Please sign in to comment.