Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cast screen kms #142

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 114 additions & 30 deletions cros_gralloc/cros_gralloc_driver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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()
{
/*
Expand All @@ -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");
Expand All @@ -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;
Expand Down Expand Up @@ -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;
yhe39 marked this conversation as resolved.
Show resolved Hide resolved
else if (ivshm_node_idx == -1)
ivshm_node_idx = availabe_node;
}

if (!strcmp(version->name, "i915")) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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]);
}
}
Expand Down Expand Up @@ -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)
Expand All @@ -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) &&
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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.");
Expand Down Expand Up @@ -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);
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 @@ -8,6 +8,7 @@
#define CROS_GRALLOC_DRIVER_H

#include "cros_gralloc_buffer.h"
#include "../drv_priv.h"

#include <functional>
#include <memory>
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<uint32_t, std::unique_ptr<cros_gralloc_buffer>> buffers_;
std::unordered_map<cros_gralloc_handle_t, cros_gralloc_imported_handle_info> handles_;
Expand Down
12 changes: 12 additions & 0 deletions drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
2 changes: 2 additions & 0 deletions drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 4 additions & 8 deletions drv_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,16 @@ 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;
const struct backend *backend;
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;
Expand Down Expand Up @@ -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
Expand Down
7 changes: 2 additions & 5 deletions i915.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 */
Expand Down
8 changes: 7 additions & 1 deletion virtgpu_virgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 };