xref: /aosp_15_r20/external/libva/va/drm/va_drm_utils.c (revision 54e60f844a168e9a219354de272cd517ee8cd4b7)
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