static inline uint32_t align_up(uint32_t n, uint32_t a) { return ((n + a - 1) / a) * a; }
-int
-LinuxVirtGpuDevice::openDevice(const drmDevicePtr dev)
-{
- bool supported_bus = false;
-
- switch (dev->bustype) {
- case DRM_BUS_PCI:
- if (dev->deviceinfo.pci->vendor_id == VIRTGPU_PCI_VENDOR_ID &&
- dev->deviceinfo.pci->device_id == VIRTGPU_PCI_DEVICE_ID)
- supported_bus = true;
- break;
- case DRM_BUS_PLATFORM:
- supported_bus = true;
- break;
- default:
- break;
+int32_t LinuxVirtGpuDevice::openDevice() {
+ drmDevicePtr devs[8];
+ int32_t ret = -EINVAL;
+ int count = drmGetDevices2(0, devs, ARRAY_SIZE(devs));
+ if (count <= 0) {
+ mesa_logd("failed to enumerate DRM devices");
+ goto out;
}
- if (!supported_bus || !(dev->available_nodes & (1 << DRM_NODE_RENDER))) {
- const char *name = "unknown";
- for (uint32_t i = 0; i < DRM_NODE_MAX; i++) {
- if (dev->available_nodes & (1 << i)) {
- name = dev->nodes[i];
+ for (int i = 0; i < count; i++) {
+ drmDevicePtr dev = devs[i];
+ bool supported_bus = false;
+
+ switch (dev->bustype) {
+ case DRM_BUS_PCI:
+ if (dev->deviceinfo.pci->vendor_id == VIRTGPU_PCI_VENDOR_ID &&
+ dev->deviceinfo.pci->device_id == VIRTGPU_PCI_DEVICE_ID)
+ supported_bus = true;
+ break;
+ case DRM_BUS_PLATFORM:
+ supported_bus = true;
+ break;
+ default:
break;
+ }
+
+ if (!supported_bus || !(dev->available_nodes & (1 << DRM_NODE_RENDER))) {
+ const char* name = "unknown";
+ for (uint32_t i = 0; i < DRM_NODE_MAX; i++) {
+ if (dev->available_nodes & (1 << i)) {
+ name = dev->nodes[i];
+ break;
+ }
}
+
+ mesa_logd("skipping DRM device %s", name);
+ continue;
}
- mesa_logd("skipping DRM device %s", name);
- return -1;
- }
- const char *primary_path = dev->nodes[DRM_NODE_PRIMARY];
- const char *node_path = dev->nodes[DRM_NODE_RENDER];
+ const char* primary_path = dev->nodes[DRM_NODE_PRIMARY];
+ const char* node_path = dev->nodes[DRM_NODE_RENDER];
- int fd = open(node_path, O_RDWR | O_CLOEXEC);
- if (fd < 0) {
- mesa_logd("failed to open %s", node_path);
- return -1;
- }
+ int fd = open(node_path, O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ mesa_logd("failed to open %s", node_path);
+ ret = -errno;
+ goto out;
+ }
- drmVersionPtr version = drmGetVersion(fd);
- if (!version || strcmp(version->name, "virtio_gpu") ||
- version->version_major != 0) {
- if (version) {
- mesa_logd("unknown DRM driver %s version %d",
- version->name, version->version_major);
+ drmVersionPtr version = drmGetVersion(fd);
+ if (!version || strcmp(version->name, "virtio_gpu") || version->version_major != 0) {
+ if (version) {
+ mesa_logd("unknown DRM driver %s version %d", version->name,
+ version->version_major);
+ } else {
+ mesa_logd("failed to get DRM driver version");
+ }
+
+ if (version) {
+ drmFreeVersion(version);
+ }
+
+ close(fd);
+ ret = -errno;
+ goto out;
+ }
+
+ struct stat st;
+ if (stat(primary_path, &st) == 0) {
+ mHasPrimary = true;
+ mPrimaryMajor = major(st.st_rdev);
+ mPrimaryMinor = minor(st.st_rdev);
} else {
- mesa_logd("failed to get DRM driver version");
+ mHasPrimary = false;
+ mPrimaryMajor = 0;
+ mPrimaryMinor = 0;
}
- if (version)
- drmFreeVersion(version);
- close(fd);
- return -1;
- }
- struct stat st;
- if (stat(primary_path, &st) == 0) {
- mHasPrimary = true;
- mPrimaryMajor = major(st.st_rdev);
- mPrimaryMinor = minor(st.st_rdev);
- } else {
- mHasPrimary = false;
- mPrimaryMajor = 0;
- mPrimaryMinor = 0;
- }
- stat(node_path, &st);
- mRenderMajor = major(st.st_rdev);
- mRenderMinor = minor(st.st_rdev);
+ stat(node_path, &st);
+ mRenderMajor = major(st.st_rdev);
+ mRenderMinor = minor(st.st_rdev);
- mBusType = dev->bustype;
- if (dev->bustype == DRM_BUS_PCI)
- mPciBusInfo = *dev->businfo.pci;
+ mBusType = dev->bustype;
+ if (dev->bustype == DRM_BUS_PCI) {
+ mPciBusInfo = *dev->businfo.pci;
+ }
- drmFreeVersion(version);
+ drmFreeVersion(version);
+ mesa_logd("using DRM device %s", node_path);
- mesa_logd("using DRM device %s", node_path);
+ mDeviceHandle = static_cast<int64_t>(fd);
+ ret = 0;
+ break;
+ }
- return fd;
+out:
+ drmFreeDevices(devs, count);
+ return ret;
}
-LinuxVirtGpuDevice::LinuxVirtGpuDevice(enum VirtGpuCapset capset, int32_t descriptor)
- : VirtGpuDevice(capset) {
+LinuxVirtGpuDevice::LinuxVirtGpuDevice(enum VirtGpuCapset capset) : VirtGpuDevice(capset) {}
+
+int32_t LinuxVirtGpuDevice::init(int32_t descriptor) {
struct VirtGpuParam 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_CREATE_GUEST_HANDLE),
};
- int ret;
+ int ret = -EINVAL;
struct drm_virtgpu_get_caps get_caps = {0};
struct drm_virtgpu_context_init init = {0};
struct drm_virtgpu_context_set_param ctx_set_params[3] = {{0}};
#endif
if (descriptor < 0) {
- drmDevicePtr devs[8];
- int count = drmGetDevices2(0, devs, ARRAY_SIZE(devs));
- if (count < 0) {
- mesa_loge("failed to enumerate DRM devices");
- return;
- }
-
- int fd = -1;
- for (int i = 0; i < count; i++) {
- fd = openDevice(devs[i]);
- if (fd >= 0) break;
+ ret = openDevice();
+ if (ret < 0) {
+ mesa_logd("no virtio_gpu devices found");
+ return ret;
}
- drmFreeDevices(devs, count);
-
- if (fd < 0) {
- mesa_loge("Failed to open the virtio_gpu device.");
- return;
- }
-
- mDeviceHandle = static_cast<int64_t>(fd);
} else {
mDeviceHandle = dup(descriptor);
if (mDeviceHandle < 0) {
mesa_loge("Failed to dup rendernode: %s", strerror(errno));
- return;
+ return ret;
}
}
mCaps.params[i] = params[i].value;
}
+ auto capset = getCapset();
get_caps.cap_set_id = static_cast<uint32_t>(capset);
switch (capset) {
case kCapsetGfxStreamVulkan:
mesa_loge("DRM_IOCTL_VIRTGPU_CONTEXT_INIT failed with %s, continuing without context...",
strerror(errno));
}
+
+ return 0;
}
LinuxVirtGpuDevice::~LinuxVirtGpuDevice() { close(mDeviceHandle); }
}
VirtGpuDevice* osCreateVirtGpuDevice(enum VirtGpuCapset capset, int32_t descriptor) {
- return new LinuxVirtGpuDevice(capset, descriptor);
+ auto device = new LinuxVirtGpuDevice(capset);
+ int32_t ret = device->init(descriptor);
+ if (ret) {
+ return nullptr;
+ }
+
+ return device;
}
bool LinuxVirtGpuDevice::getDrmInfo(VirtGpuDrmInfo* drmInfo) {
pciBusInfo->bus = mPciBusInfo.bus;
pciBusInfo->device = mPciBusInfo.dev;
pciBusInfo->function = mPciBusInfo.func;
-
return true;
}