1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2022 NVIDIA, Inc.
6 * Copyright (c) 2022 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Drm utilities.
23 *//*--------------------------------------------------------------------*/
24
25 #if DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
26
27 #include "tcuLibDrm.hpp"
28
29 #include "tcuDefs.hpp"
30
31 #include "deMemory.h"
32
33 #include <fcntl.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37
38 #if !defined(__FreeBSD__)
39 // major() and minor() are defined in sys/types.h on FreeBSD, and in
40 // sys/sysmacros.h on Linux and Solaris.
41 #include <sys/sysmacros.h>
42 #endif // !defined(__FreeBSD__)
43
44 namespace tcu
45 {
46
LibDrm(void)47 LibDrm::LibDrm (void) : DynamicLibrary(libDrmFiles)
48 {
49 pGetDevices2 = (PFNDRMGETDEVICES2PROC)getFunction("drmGetDevices2");
50 pGetDevices = (PFNDRMGETDEVICESPROC)getFunction("drmGetDevices");
51 pFreeDevices = (PFNDRMFREEDEVICESPROC)getFunction("drmFreeDevices");
52 pGetResources = (PFNDRMMODEGETRESOURCESPROC)getFunction("drmModeGetResources");
53 pFreeResources = (PFNDRMMODEFREERESOURCESPROC)getFunction("drmModeFreeResources");
54 pGetConnector = (PFNDRMMODEGETCONNECTORPROC)getFunction("drmModeGetConnector");
55 pFreeConnector = (PFNDRMMODEFREECONNECTORPROC)getFunction("drmModeFreeConnector");
56 pGetEncoder = (PFNDRMMODEGETENCODERPROC)getFunction("drmModeGetEncoder");
57 pFreeEncoder = (PFNDRMMODEFREEENCODERPROC)getFunction("drmModeFreeEncoder");
58 pCreateLease = (PFNDRMMODECREATELEASEPROC)getFunction("drmModeCreateLease");
59 pAuthMagic = (PFNDRMAUTHMAGIC)getFunction("drmAuthMagic");
60
61 /* libdrm did not add this API until 2.4.65, return NotSupported if it's too old. */
62 if (!pGetDevices2 && !pGetDevices)
63 TCU_THROW(NotSupportedError, "Could not load a valid drmGetDevices() variant from libdrm");
64 if (!pFreeDevices)
65 TCU_THROW(NotSupportedError, "Could not load drmFreeDevices() from libdrm");
66 if (!pGetResources)
67 TCU_FAIL("Could not load drmModeGetResources() from libdrm");
68 if (!pFreeResources)
69 TCU_FAIL("Could not load drmModeFreeResources() from libdrm");
70 if (!pGetConnector)
71 TCU_FAIL("Could not load drmModeGetConnector() from libdrm");
72 if (!pFreeConnector)
73 TCU_FAIL("Could not load drmModeFreeConnector() from libdrm");
74 if (!pGetEncoder)
75 TCU_FAIL("Could not load drmModeGetEncoder() from libdrm");
76 if (!pFreeEncoder)
77 TCU_FAIL("Could not load drmModeFreeEncoder() from libdrm");
78 if (!pCreateLease)
79 TCU_FAIL("Could not load drmModeCreateLease() from libdrm");
80 if (!pAuthMagic)
81 TCU_FAIL("Could not load drmAuthMagic() from libdrm");
82 }
83
~LibDrm(void)84 LibDrm::~LibDrm (void)
85 {
86 }
87
getDevices(int * pNumDevices) const88 drmDevicePtr* LibDrm::getDevices (int *pNumDevices) const
89 {
90 *pNumDevices = intGetDevices(DE_NULL, 0);
91
92 if (*pNumDevices < 0)
93 TCU_THROW(NotSupportedError,
94 "Failed to query number of DRM devices in system");
95
96 if (*pNumDevices == 0)
97 return DE_NULL;
98
99 drmDevicePtr *devs = new drmDevicePtr[*pNumDevices];
100
101 *pNumDevices = intGetDevices(devs, *pNumDevices);
102
103 if (*pNumDevices < 0) {
104 delete[] devs;
105 TCU_FAIL("Failed to query list of DRM devices in system");
106 }
107
108 return devs;
109 }
110
findDeviceNode(drmDevicePtr * devices,int count,deInt64 major,deInt64 minor) const111 const char* LibDrm::findDeviceNode (drmDevicePtr *devices, int count, deInt64 major, deInt64 minor) const
112 {
113 for (int i = 0; i < count; i++)
114 {
115 for (int j = 0; j < DRM_NODE_MAX; j++)
116 {
117 if (!(devices[i]->available_nodes & (1 << j)))
118 continue;
119
120 struct stat statBuf;
121 deMemset(&statBuf, 0, sizeof(statBuf));
122 int res = stat(devices[i]->nodes[j], &statBuf);
123
124 if (res || !(statBuf.st_mode & S_IFCHR))
125 continue;
126
127 if (major == major(statBuf.st_rdev) &&
128 minor == minor(statBuf.st_rdev))
129 {
130 return devices[i]->nodes[j];
131 }
132 }
133 }
134
135 return DE_NULL;
136 }
137
freeDevices(drmDevicePtr * devices,int count) const138 void LibDrm::freeDevices (drmDevicePtr *devices, int count) const
139 {
140 pFreeDevices(devices, count);
141 delete[] devices;
142 }
143
closeAndDeleteFd(int * fd)144 static void closeAndDeleteFd(int* fd) {
145 if (fd) {
146 close(*fd);
147 delete fd;
148 }
149 }
150
openFd(const char * node) const151 LibDrm::FdPtr LibDrm::openFd (const char* node) const
152 {
153 int fd = open(node, O_RDWR);
154 if (fd < 0)
155 return FdPtr(DE_NULL);
156 else
157 return FdPtr(new int{fd}, closeAndDeleteFd);
158 }
159
getResources(int fd) const160 LibDrm::ResPtr LibDrm::getResources (int fd) const
161 {
162 return ResPtr(pGetResources(fd), pFreeResources);
163 }
164
getConnector(int fd,deUint32 connectorId) const165 LibDrm::ConnectorPtr LibDrm::getConnector (int fd, deUint32 connectorId) const
166 {
167 return ConnectorPtr(pGetConnector(fd, connectorId), pFreeConnector);
168 }
169
getEncoder(int fd,deUint32 encoderId) const170 LibDrm::EncoderPtr LibDrm::getEncoder (int fd, deUint32 encoderId) const
171 {
172 return EncoderPtr(pGetEncoder(fd, encoderId), pFreeEncoder);
173 }
174
createLease(int fd,const deUint32 * objects,int numObjects,int flags) const175 LibDrm::FdPtr LibDrm::createLease (int fd, const deUint32 *objects, int numObjects, int flags) const
176 {
177 deUint32 leaseId;
178 int leaseFd = pCreateLease(fd, objects, numObjects, flags, &leaseId);
179 if (leaseFd < 0)
180 return FdPtr(DE_NULL);
181 else
182 return FdPtr(new int{leaseFd}, closeAndDeleteFd);
183 }
184
authMagic(int fd,drm_magic_t magic) const185 int LibDrm::authMagic (int fd, drm_magic_t magic) const
186 {
187 return pAuthMagic(fd, magic);
188 }
189
intGetDevices(drmDevicePtr devices[],int maxDevices) const190 int LibDrm::intGetDevices (drmDevicePtr devices[], int maxDevices) const
191 {
192 if (pGetDevices2)
193 return pGetDevices2(0, devices, maxDevices);
194 else
195 return pGetDevices(devices, maxDevices);
196 }
197
198 const char* LibDrm::libDrmFiles[] =
199 {
200 "libdrm.so.2",
201 "libdrm.so",
202 nullptr
203 };
204
205 } // tcu
206
207 #endif // DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
208