summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Langdale <philipl@overt.org>2019-12-16 19:23:14 -0800
committerPhilip Langdale <github.philipl@overt.org>2021-11-15 21:07:21 -0800
commitb030cfe05f585234c10337576047bc314b36faef (patch)
tree06cab98a1847b681bd59792645fe13da3747cf2d
parent3bfc37dcb46b43e44ff4f99d1947ccfd603379b9 (diff)
downloadmpv-b030cfe05f585234c10337576047bc314b36faef.tar.bz2
mpv-b030cfe05f585234c10337576047bc314b36faef.tar.xz
vo_gpu: vulkan: open DRM render fd when using VK_KHR_display
While the basic Vulkan Display context can theoretically drive the display without the involvement of any non-Vulkan code, that prevents us from using VAAPI acceleration. When initialising VAAPI without a window system, we need to provide it with an opened DRM render fd corresponding to the device to use. In the context of using VK_KHR_display, that means we need to identify which DRM device matches the selected Vulkan device, and then open its render fd and set the necessary state that VAAPI expects to find. With that done, the normal VAAPI<->Vulkan interop can kick in and we get working acceleration
-rw-r--r--video/out/vulkan/context_display.c104
1 files changed, 102 insertions, 2 deletions
diff --git a/video/out/vulkan/context_display.c b/video/out/vulkan/context_display.c
index 5545b3378d..956a3f2a2f 100644
--- a/video/out/vulkan/context_display.c
+++ b/video/out/vulkan/context_display.c
@@ -15,11 +15,19 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "options/m_config.h"
-
#include "context.h"
+#include "options/m_config.h"
#include "utils.h"
+#if HAVE_DRM
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "libmpv/render_gl.h"
+#include "video/out/drm_common.h"
+#endif
+
struct vulkan_display_opts {
int display;
int mode;
@@ -278,14 +286,83 @@ struct priv {
struct vulkan_display_opts *opts;
uint32_t width;
uint32_t height;
+
+#if HAVE_DRM
+ struct mpv_opengl_drm_params_v2 drm_params;
+#endif
};
+#if HAVE_DRM
+static void open_render_fd(struct ra_ctx *ctx, const char *render_path)
+{
+ struct priv *p = ctx->priv;
+ p->drm_params.fd = -1;
+ p->drm_params.render_fd = open(render_path, O_RDWR | O_CLOEXEC);
+ if (p->drm_params.render_fd == -1) {
+ MP_WARN(ctx, "Failed to open render node: %s\n",
+ strerror(errno));
+ }
+}
+
+static bool drm_setup(struct ra_ctx *ctx, int display_idx,
+ VkPhysicalDevicePCIBusInfoPropertiesEXT *pci_props)
+{
+ drmDevice *devs[32] = {};
+ int count = drmGetDevices2(0, devs, MP_ARRAY_SIZE(devs));
+ for (int i = 0; i < count; i++) {
+ drmDevice *dev = devs[i];
+
+ if (dev->bustype != DRM_BUS_PCI ||
+ dev->businfo.pci->domain != pci_props->pciDomain ||
+ dev->businfo.pci->bus != pci_props->pciBus ||
+ dev->businfo.pci->dev != pci_props->pciDevice ||
+ dev->businfo.pci->func != pci_props->pciFunction)
+ {
+ continue;
+ }
+
+ // Found our matching device.
+ MP_DBG(ctx, "DRM device found for Vulkan device at %04X:%02X:%02X:%02X\n",
+ pci_props->pciDomain, pci_props->pciBus,
+ pci_props->pciDevice, pci_props->pciFunction);
+
+ if (!(dev->available_nodes & 1 << DRM_NODE_RENDER)) {
+ MP_DBG(ctx, "Card does not have a render node.\n");
+ continue;
+ }
+
+ open_render_fd(ctx, dev->nodes[DRM_NODE_RENDER]);
+
+ break;
+ }
+ drmFreeDevices(devs, MP_ARRAY_SIZE(devs));
+
+ struct priv *p = ctx->priv;
+ if (p->drm_params.render_fd == -1) {
+ MP_WARN(ctx, "Couldn't open DRM render node for Vulkan device "
+ "at: %04X:%02X:%02X:%02X\n",
+ pci_props->pciDomain, pci_props->pciBus,
+ pci_props->pciDevice, pci_props->pciFunction);
+ return false;
+ }
+
+ return true;
+}
+#endif
+
static void display_uninit(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
ra_vk_ctx_uninit(ctx);
mpvk_uninit(&p->vk);
+
+#if HAVE_DRM
+ if (p->drm_params.render_fd != -1) {
+ close(p->drm_params.render_fd);
+ p->drm_params.render_fd = -1;
+ }
+#endif
}
static bool display_init(struct ra_ctx *ctx)
@@ -318,6 +395,20 @@ static bool display_init(struct ra_ctx *ctx)
goto error;
}
+#if HAVE_DRM
+ VkPhysicalDevicePCIBusInfoPropertiesEXT pci_props = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT,
+ };
+ VkPhysicalDeviceProperties2KHR props = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
+ .pNext = &pci_props,
+ };
+ vkGetPhysicalDeviceProperties2(device, &props);
+
+ if (!drm_setup(ctx, display_idx, &pci_props))
+ MP_WARN(ctx, "Failed to set up DRM.\n");
+#endif
+
struct mode_selector selector = {
.display_idx = display_idx,
.mode_idx = mode_idx,
@@ -351,6 +442,15 @@ static bool display_init(struct ra_ctx *ctx)
if (!ra_vk_ctx_init(ctx, vk, params, VK_PRESENT_MODE_FIFO_KHR))
goto error;
+#if HAVE_DRM
+ if (p->drm_params.render_fd > -1) {
+ ra_add_native_resource(ctx->ra, "drm_params_v2", &p->drm_params);
+ } else {
+ MP_WARN(ctx,
+ "No DRM render fd available. VAAPI hwaccel will not be usable.\n");
+ }
+#endif
+
ret = true;
done: