1 /*
2 * va_drm_utils.c - VA/DRM Utilities
3 *
4 * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
5 * Copyright (c) 2023 Emil Velikov
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28 #include "sysdeps.h"
29 #include <xf86drm.h>
30 #include <sys/stat.h>
31 #include <sys/utsname.h>
32 #include "va_drm_utils.h"
33 #include "va_drmcommon.h"
34
35 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
36
37 static char *
va_DRM_GetDrmDriverName(int fd)38 va_DRM_GetDrmDriverName(int fd)
39 {
40 drmVersionPtr drm_version = drmGetVersion(fd);
41 char *driver_name;
42
43 if (!drm_version)
44 return NULL;
45
46 driver_name = strdup(drm_version->name);
47 drmFreeVersion(drm_version);
48
49 return driver_name;
50 }
51
52 /* Returns the VA driver names and how many they are, for the active display */
53 VAStatus
VA_DRM_GetDriverNames(VADriverContextP ctx,char ** drivers,unsigned * num_drivers)54 VA_DRM_GetDriverNames(VADriverContextP ctx, char **drivers, unsigned *num_drivers)
55 {
56 #define MAX_NAMES 2 // Adjust if needed
57
58 static const struct {
59 const char * const drm_driver;
60 const char * const va_driver[MAX_NAMES];
61 } map[] = {
62 { "xe", { "iHD" } },
63 { "i915", { "iHD", "i965" } }, // Intel Media and OTC GenX
64 { "pvrsrvkm", { "pvr" } }, // Intel UMG PVR
65 { "radeon", { "r600", "radeonsi" } }, // Mesa Gallium
66 { "amdgpu", { "radeonsi" } }, // Mesa Gallium
67 { "WSL", { "d3d12" } }, // Mesa Gallium
68 { "nvidia-drm", { "nvidia" } }, // Unofficial NVIDIA
69 };
70
71 const struct drm_state * const drm_state = ctx->drm_state;
72 char *drm_driver;
73 unsigned count = 0;
74
75 if (!drm_state || drm_state->fd < 0)
76 return VA_STATUS_ERROR_INVALID_DISPLAY;
77
78 drm_driver = va_DRM_GetDrmDriverName(drm_state->fd);
79 if (!drm_driver)
80 return VA_STATUS_ERROR_UNKNOWN;
81
82 /* Map vgem to WSL2 for Windows subsystem for linux */
83 struct utsname sysinfo = {};
84 if (!strncmp(drm_driver, "vgem", 4) && uname(&sysinfo) >= 0 &&
85 strstr(sysinfo.release, "WSL")) {
86 free(drm_driver);
87 drm_driver = strdup("WSL");
88 if (!drm_driver)
89 return VA_STATUS_ERROR_UNKNOWN;
90 }
91
92 for (unsigned i = 0; i < ARRAY_SIZE(map); i++) {
93 if (strcmp(map[i].drm_driver, drm_driver) == 0) {
94 const char * const *va_drivers = map[i].va_driver;
95 for (; count < MAX_NAMES && va_drivers[count] && count < *num_drivers; count++)
96 drivers[count] = strdup(va_drivers[count]);
97
98 break;
99 }
100 }
101
102 /* Fallback to the drm driver, if there's no va equivalent in the map. */
103 if (!count) {
104 drivers[count] = drm_driver;
105 count++;
106 } else {
107 free(drm_driver);
108 }
109
110 *num_drivers = count;
111
112 return VA_STATUS_SUCCESS;
113 }
114