diff --git a/src/imagination/vulkan/pvr_instance.c b/src/imagination/vulkan/pvr_instance.c index 0f3cd1e465b..86b8db720d2 100644 --- a/src/imagination/vulkan/pvr_instance.c +++ b/src/imagination/vulkan/pvr_instance.c @@ -12,7 +12,9 @@ #include "pvr_instance.h" +#include #include +#include #include "vk_alloc.h" #include "vk_log.h" @@ -38,22 +40,20 @@ struct pvr_drm_device_config { struct pvr_drm_device_info { const char *name; size_t len; - } render, display; + } render; }; -#define DEF_CONFIG(render_, display_) \ - { \ - .render = { .name = render_, .len = sizeof(render_) - 1 }, \ - .display = { .name = display_, .len = sizeof(display_) - 1 }, \ +#define DEF_CONFIG(render_) \ + { \ + .render = { .name = render_, .len = sizeof(render_) - 1 }, \ } -/* This is the list of supported DRM render/display driver configs. */ +/* This is the list of supported DRM render driver configs. */ static const struct pvr_drm_device_config pvr_drm_configs[] = { - DEF_CONFIG("mediatek,mt8173-gpu", "mediatek-drm"), - DEF_CONFIG("ti,am62-gpu", "ti,am625-dss"), - DEF_CONFIG("ti,j721s2-gpu", "ti,j721e-dss"), + DEF_CONFIG("mediatek,mt8173-gpu"), + DEF_CONFIG("ti,am62-gpu"), + DEF_CONFIG("ti,j721s2-gpu"), }; - #undef DEF_CONFIG static const struct vk_instance_extension_table pvr_instance_extensions = { @@ -121,6 +121,56 @@ pvr_drm_device_get_config(drmDevice *const drm_dev) return NULL; } +static bool pvr_drm_device_is_compatible_display(drmDevicePtr drm_dev) +{ + uint64_t has_dumb_buffer = 0; + uint64_t prime_caps = 0; + bool ret = false; + int32_t fd; + + mesa_logd("Checking DRM primary node for compatibility: %s", + drm_dev->nodes[DRM_NODE_PRIMARY]); + fd = open(drm_dev->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC); + if (fd < 0) { + mesa_logd("Failed to open display node: %s\n", + drm_dev->nodes[DRM_NODE_PRIMARY]); + return ret; + } + + /* Must support KMS */ + if (!drmIsKMS(fd)) { + mesa_logd("DRM device does not support KMS"); + goto out; + } + + /* Must support dumb buffers, as these are used by the PVR winsys to + * allocate device memory for PVR_WINSYS_BO_TYPE_DISPLAY buffer objects. + */ + if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb_buffer) || + !has_dumb_buffer) { + mesa_logd("DRM device does not support dumb buffers"); + goto out; + } + + /* Must support PRIME export (so GPU can import dumb buffers) */ + if (drmGetCap(fd, DRM_CAP_PRIME, &prime_caps)) { + mesa_loge("Failed to query DRM_CAP_PRIME: %s", strerror(errno)); + goto out; + } + + if (!(prime_caps & DRM_PRIME_CAP_EXPORT)) { + mesa_logd("DRM device lacks PRIME export support (caps: 0x%" PRIx64 ")", + prime_caps); + goto out; + } + + ret = true; + +out: + close(fd); + return ret; +} + static VkResult pvr_physical_device_enumerate(struct vk_instance *const vk_instance) { @@ -183,29 +233,25 @@ pvr_physical_device_enumerate(struct vk_instance *const vk_instance) mesa_logd("Found compatible render device '%s'.", drm_render_device->nodes[DRM_NODE_RENDER]); - /* ...then find the compatible display node. */ + /* ...then find a compatible display node, if available. */ for (int i = 0; i < num_drm_devices; i++) { drmDevice *const drm_dev = drm_devices[i]; + if (drm_dev->bustype != DRM_BUS_PLATFORM) + continue; + if (!(drm_dev->available_nodes & BITFIELD_BIT(DRM_NODE_PRIMARY))) continue; - if (pvr_drm_device_compatible(&config->display, drm_dev)) { - drm_display_device = drm_dev; - break; - } - } + if (!pvr_drm_device_is_compatible_display(drm_devices[i])) + continue; - if (!drm_display_device) { - mesa_loge("Render device '%s' has no compatible display device.", - drm_render_device->nodes[DRM_NODE_RENDER]); - result = VK_SUCCESS; - goto out_free_drm_devices; + drm_display_device = drm_dev; + mesa_logd("Found a compatible display device: '%s'.", + drm_display_device->nodes[DRM_NODE_PRIMARY]); + break; } - mesa_logd("Found compatible display device '%s'.", - drm_display_device->nodes[DRM_NODE_PRIMARY]); - pdevice = vk_alloc(&vk_instance->alloc, sizeof(*pdevice), 8, @@ -229,7 +275,9 @@ pvr_physical_device_enumerate(struct vk_instance *const vk_instance) if (PVR_IS_DEBUG_SET(INFO)) { pvr_physical_device_dump_info( pdevice, - drm_display_device->deviceinfo.platform->compatible, + drm_display_device + ? drm_display_device->deviceinfo.platform->compatible + : NULL, drm_render_device->deviceinfo.platform->compatible); } diff --git a/src/imagination/vulkan/pvr_physical_device.c b/src/imagination/vulkan/pvr_physical_device.c index 26db3a18426..0c646913f86 100644 --- a/src/imagination/vulkan/pvr_physical_device.c +++ b/src/imagination/vulkan/pvr_physical_device.c @@ -41,10 +41,12 @@ pvr_physical_device_dump_info(const struct pvr_physical_device *pdevice, char *const *comp_display, char *const *comp_render) { - drmVersionPtr version_display, version_render; - struct pvr_device_dump_info info; + drmVersionPtr version_display = NULL, version_render; + struct pvr_device_dump_info info = { 0 }; + + if (pdevice->ws->display_fd >= 0) + version_display = drmGetVersion(pdevice->ws->display_fd); - version_display = drmGetVersion(pdevice->ws->display_fd); if (!version_display) return; @@ -56,12 +58,14 @@ pvr_physical_device_dump_info(const struct pvr_physical_device *pdevice, info.device_info = &pdevice->dev_info; info.device_runtime_info = &pdevice->dev_runtime_info; - info.drm_display.patchlevel = version_display->version_patchlevel; - info.drm_display.major = version_display->version_major; - info.drm_display.minor = version_display->version_minor; - info.drm_display.name = version_display->name; - info.drm_display.date = version_display->date; - info.drm_display.comp = comp_display; + if (version_display) { + info.drm_display.patchlevel = version_display->version_patchlevel; + info.drm_display.major = version_display->version_major; + info.drm_display.minor = version_display->version_minor; + info.drm_display.name = version_display->name; + info.drm_display.date = version_display->date; + info.drm_display.comp = comp_display; + } info.drm_render.patchlevel = version_render->version_patchlevel; info.drm_render.major = version_render->version_major; info.drm_render.minor = version_render->version_minor; @@ -975,7 +979,7 @@ VkResult pvr_physical_device_init(struct pvr_physical_device *pdevice, goto err_out; } - if (instance->vk.enabled_extensions.KHR_display) { + if (instance->vk.enabled_extensions.KHR_display && drm_display_device) { display_path = vk_strdup(&instance->vk.alloc, drm_display_device->nodes[DRM_NODE_PRIMARY], VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);