• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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