1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 NVIDIA, Inc.
6 * Copyright (c) 2021 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 VK_EXT_device_drm_properties tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktApiDeviceDrmPropertiesTests.hpp"
26 #include "vktTestGroupUtil.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "deFilePath.hpp"
29 #include "deDirectoryIterator.hpp"
30 #include "deDynamicLibrary.hpp"
31 #if DEQP_SUPPORT_DRM
32 #if !defined(__FreeBSD__)
33 // major() and minor() are defined in sys/types.h on FreeBSD, and in
34 // sys/sysmacros.h on Linux and Solaris.
35 #include <sys/sysmacros.h>
36 #endif // !defined(__FreeBSD__)
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
40 #include <xf86drm.h>
41 #endif // DEQP_SUPPORT_DRM
42
43 using namespace vk;
44
45 namespace vkt
46 {
47 namespace api
48 {
49 namespace
50 {
51
52 enum TestType
53 {
54 TEST_FILES_EXIST = 0,
55 };
56
checkSupport(Context & context,const TestType config)57 void checkSupport (Context& context, const TestType config)
58 {
59 DE_UNREF(config);
60 context.requireDeviceFunctionality("VK_EXT_physical_device_drm");
61 }
62
63 #if DEQP_SUPPORT_DRM
64 class LibDrm : protected de::DynamicLibrary
65 {
66 static const char* libDrmFiles[];
67
68 typedef int (*PFNDRMGETDEVICES2PROC)(deUint32, drmDevicePtr[], int);
69 typedef int (*PFNDRMGETDEVICESPROC)(drmDevicePtr[], int);
70 typedef void (*PFNDRMFREEDEVICESPROC)(drmDevicePtr[], int);
71 PFNDRMGETDEVICES2PROC pGetDevices2;
72 PFNDRMGETDEVICESPROC pGetDevices;
73 PFNDRMFREEDEVICESPROC pFreeDevices;
74
intGetDevices(drmDevicePtr devices[],int maxDevices) const75 int intGetDevices(drmDevicePtr devices[], int maxDevices) const
76 {
77 if (pGetDevices2)
78 return pGetDevices2(0, devices, maxDevices);
79 else
80 return pGetDevices(devices, maxDevices);
81 }
82
83 public:
LibDrm()84 LibDrm() : DynamicLibrary(libDrmFiles) {
85 pGetDevices2 = (PFNDRMGETDEVICES2PROC)getFunction("drmGetDevices2");
86 pGetDevices = (PFNDRMGETDEVICESPROC)getFunction("drmGetDevices");
87 pFreeDevices = (PFNDRMFREEDEVICESPROC)getFunction("drmFreeDevices");
88
89 if (!pGetDevices2 && !pGetDevices)
90 TCU_FAIL("Could not load a valid drmGetDevices() variant from libdrm");
91
92 if (!pFreeDevices)
93 TCU_FAIL("Could not load drmFreeDevices() from libdrm");
94 }
95
getDevices(int * pNumDevices) const96 drmDevicePtr *getDevices(int *pNumDevices) const
97 {
98 *pNumDevices = intGetDevices(DE_NULL, 0);
99
100 if (*pNumDevices < 0)
101 TCU_THROW(NotSupportedError, "Failed to query number of DRM devices in system");
102
103 if (*pNumDevices == 0)
104 return DE_NULL;
105
106 drmDevicePtr *devs = new drmDevicePtr[*pNumDevices];
107
108 *pNumDevices = intGetDevices(devs, *pNumDevices);
109
110 if (*pNumDevices < 0)
111 {
112 delete[] devs;
113 TCU_FAIL("Failed to query list of DRM devices in system");
114 }
115
116 return devs;
117 }
118
freeDevices(drmDevicePtr * devices,int count) const119 void freeDevices(drmDevicePtr *devices, int count) const
120 {
121 pFreeDevices(devices, count);
122 delete[] devices;
123 }
124
~LibDrm()125 ~LibDrm() { }
126 };
127
128 const char* LibDrm::libDrmFiles[] =
129 {
130 "libdrm.so.2",
131 "libdrm.so",
132 DE_NULL
133 };
134 #endif // DEQP_SUPPORT_DRM
135
testFilesExist(const VkPhysicalDeviceDrmPropertiesEXT & deviceDrmProperties)136 void testFilesExist (const VkPhysicalDeviceDrmPropertiesEXT& deviceDrmProperties)
137 {
138 bool primaryFound = !deviceDrmProperties.hasPrimary;
139 bool renderFound = !deviceDrmProperties.hasRender;
140
141 #if DEQP_SUPPORT_DRM
142 static const LibDrm libDrm;
143
144 int numDrmDevices;
145 drmDevicePtr* drmDevices = libDrm.getDevices(&numDrmDevices);
146
147 for (int i = 0; i < numDrmDevices; i++)
148 {
149 for (int j = 0; j < DRM_NODE_MAX; j++)
150 {
151 if (!(drmDevices[i]->available_nodes & (1 << j)))
152 continue;
153
154 struct stat statBuf;
155 deMemset(&statBuf, 0, sizeof(statBuf));
156 int res = stat(drmDevices[i]->nodes[j], &statBuf);
157
158 if (res || !(statBuf.st_mode & S_IFCHR))
159 continue;
160
161 if (deviceDrmProperties.primaryMajor == major(statBuf.st_rdev) &&
162 deviceDrmProperties.primaryMinor == minor(statBuf.st_rdev))
163 {
164 primaryFound = true;
165 continue;
166 }
167
168 if (deviceDrmProperties.renderMajor == major(statBuf.st_rdev) &&
169 deviceDrmProperties.renderMinor == minor(statBuf.st_rdev))
170 {
171 renderFound = true;
172 continue;
173 }
174 }
175 }
176
177 libDrm.freeDevices(drmDevices, numDrmDevices);
178 #endif // DEQP_SUPPORT_DRM
179
180 if (!primaryFound && !renderFound) {
181 TCU_THROW(NotSupportedError, "Nether DRM primary nor render device files were found");
182 }
183 }
184
testDeviceDrmProperties(Context & context,const TestType testType)185 static tcu::TestStatus testDeviceDrmProperties (Context& context, const TestType testType)
186 {
187
188 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
189 VkPhysicalDeviceProperties2 deviceProperties2;
190 const int memsetPattern = 0xaa;
191 VkPhysicalDeviceDrmPropertiesEXT deviceDrmProperties;
192
193 deMemset(&deviceDrmProperties, 0, sizeof(deviceDrmProperties));
194 deviceDrmProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT;
195 deviceDrmProperties.pNext = DE_NULL;
196
197 deMemset(&deviceProperties2, memsetPattern, sizeof(deviceProperties2));
198 deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
199 deviceProperties2.pNext = &deviceDrmProperties;
200
201 context.getInstanceInterface().getPhysicalDeviceProperties2(physDevice, &deviceProperties2);
202
203 switch (testType)
204 {
205 case TEST_FILES_EXIST: testFilesExist (deviceDrmProperties); break;
206 default: TCU_THROW(InternalError, "Unknown test type specified");
207 }
208
209 return tcu::TestStatus::pass("Pass");
210 }
211
createTestCases(tcu::TestCaseGroup * group)212 static void createTestCases (tcu::TestCaseGroup* group)
213 {
214 addFunctionCase(group, "drm_files_exist", "Verify device files for major/minor nodes exist", checkSupport, testDeviceDrmProperties, TEST_FILES_EXIST);
215 }
216
217 } // anonymous
218
createDeviceDrmPropertiesTests(tcu::TestContext & testCtx)219 tcu::TestCaseGroup* createDeviceDrmPropertiesTests(tcu::TestContext& testCtx)
220 {
221 return createTestGroup(testCtx, "device_drm_properties", "VK_EXT_device_drm_properties tests", createTestCases);
222 }
223
224 } // api
225 } // vkt
226