• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *	  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Vulkan coverage tests for extension VK_EXT_acquire_drm_display
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktWsiAcquireDrmDisplayTests.hpp"
25 
26 #include "vktCustomInstancesDevices.hpp"
27 #include "vktTestCase.hpp"
28 #include "vkDeviceUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 
31 #include "tcuDefs.hpp"
32 #include "tcuLibDrm.hpp"
33 
34 #if DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
35 #include <fcntl.h>
36 #endif // DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
37 
38 #include <string>
39 #include <vector>
40 
41 namespace vkt
42 {
43 namespace wsi
44 {
45 using namespace vk;
46 using std::string;
47 using std::vector;
48 #if DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
49 using tcu::LibDrm;
50 #endif // DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
51 
52 #define INVALID_PTR 0xFFFFFFFF
53 
54 enum DrmTestIndex
55 {
56 	DRM_TEST_INDEX_START,
57 	DRM_TEST_INDEX_GET_DRM_DISPLAY,
58 	DRM_TEST_INDEX_GET_DRM_DISPLAY_INVALID_FD,
59 	DRM_TEST_INDEX_GET_DRM_DISPLAY_INVALID_CONNECTOR_ID,
60 	DRM_TEST_INDEX_GET_DRM_DISPLAY_NOT_MASTER,
61 	DRM_TEST_INDEX_GET_DRM_DISPLAY_UNOWNED_CONNECTOR_ID,
62 	DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY,
63 	DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY_INVALID_FD,
64 	DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY_NOT_MASTER,
65 	DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY_UNOWNED_CONNECTOR_ID,
66 	DRM_TEST_INDEX_RELEASE_DISPLAY,
67 	DRM_TEST_INDEX_LAST
68 };
69 
70 /*--------------------------------------------------------------------*//*!
71  * \brief Vulkan VK_EXT_acquire_drm_display extension tests
72  *//*--------------------------------------------------------------------*/
73 class AcquireDrmDisplayTestInstance : public TestInstance
74 {
75 public:
76 								AcquireDrmDisplayTestInstance				(Context& context, const DrmTestIndex testId);
77 	tcu::TestStatus				iterate										(void) override;
78 
79 private:
80 	CustomInstance				createInstanceWithAcquireDrmDisplay			(void);
81 
82 #if DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
83 	LibDrm::FdPtr				getDrmFdPtr									(void);
84 	deUint32					getConnectedConnectorId						(int fd, deUint32 connectorId = 0);
85 	deUint32					getValidCrtcId								(int fd, deUint32 connectorId);
86 	bool						isDrmMaster									(int fd);
87 
88 	// VK_EXT_acquire_drm_display extension tests
89 	tcu::TestStatus				testGetDrmDisplayEXT						(void);
90 	tcu::TestStatus				testGetDrmDisplayEXTInvalidFd				(void);
91 	tcu::TestStatus				testGetDrmDisplayEXTInvalidConnectorId		(void);
92 	tcu::TestStatus				testGetDrmDisplayEXTNotMaster				(void);
93 	tcu::TestStatus				testGetDrmDisplayEXTUnownedConnectorId		(void);
94 	tcu::TestStatus				testAcquireDrmDisplayEXT					(void);
95 	tcu::TestStatus				testAcquireDrmDisplayEXTInvalidFd			(void);
96 	tcu::TestStatus				testAcquireDrmDisplayEXTNotMaster			(void);
97 	tcu::TestStatus				testAcquireDrmDisplayEXTUnownedConnectorId	(void);
98 	tcu::TestStatus				testReleaseDisplayEXT						(void);
99 
100 	const LibDrm				m_libDrm;
101 #endif // DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
102 
103 	const CustomInstance		m_instance;
104 	const InstanceInterface&	m_vki;
105 	const VkPhysicalDevice		m_physDevice;
106 	const DrmTestIndex			m_testId;
107 };
108 
109 /*--------------------------------------------------------------------*//*!
110  * \brief AcquireDrmDisplayTestInstance constructor
111  *
112  * Initializes AcquireDrmDisplayTestInstance object
113  *
114  * \param context	Context object
115  * \param testId    Enum for which test to run
116  *//*--------------------------------------------------------------------*/
AcquireDrmDisplayTestInstance(Context & context,const DrmTestIndex testId)117 AcquireDrmDisplayTestInstance::AcquireDrmDisplayTestInstance (Context& context, const DrmTestIndex testId)
118 	: TestInstance	(context)
119 	, m_instance	(createInstanceWithAcquireDrmDisplay())
120 	, m_vki			(m_instance.getDriver())
121 	, m_physDevice	(vk::chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
122 	, m_testId		(testId)
123 {
124 	DE_UNREF(m_testId);
125 }
126 
127 /*--------------------------------------------------------------------*//*!
128  * \brief Step forward test execution
129  *
130  * \return true if application should call iterate() again and false
131  *		 if test execution session is complete.
132  *//*--------------------------------------------------------------------*/
iterate(void)133 tcu::TestStatus AcquireDrmDisplayTestInstance::iterate (void)
134 {
135 #if DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
136 	switch (m_testId)
137 	{
138 		case DRM_TEST_INDEX_GET_DRM_DISPLAY:							return testGetDrmDisplayEXT();
139 		case DRM_TEST_INDEX_GET_DRM_DISPLAY_INVALID_FD:					return testGetDrmDisplayEXTInvalidFd();
140 		case DRM_TEST_INDEX_GET_DRM_DISPLAY_INVALID_CONNECTOR_ID:		return testGetDrmDisplayEXTInvalidConnectorId();
141 		case DRM_TEST_INDEX_GET_DRM_DISPLAY_NOT_MASTER:					return testGetDrmDisplayEXTNotMaster();
142 		case DRM_TEST_INDEX_GET_DRM_DISPLAY_UNOWNED_CONNECTOR_ID:		return testGetDrmDisplayEXTUnownedConnectorId();
143 		case DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY:						return testAcquireDrmDisplayEXT();
144 		case DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY_INVALID_FD:				return testAcquireDrmDisplayEXTInvalidFd();
145 		case DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY_NOT_MASTER:				return testAcquireDrmDisplayEXTNotMaster();
146 		case DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY_UNOWNED_CONNECTOR_ID:	return testAcquireDrmDisplayEXTUnownedConnectorId();
147 		case DRM_TEST_INDEX_RELEASE_DISPLAY:							return testReleaseDisplayEXT();
148 		default:
149 		{
150 			DE_FATAL("Impossible");
151 		}
152 	}
153 
154 	TCU_FAIL("Invalid test identifier");
155 #else
156 	TCU_THROW(NotSupportedError, "Drm not supported.");
157 #endif // DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
158 }
159 
160 // /*--------------------------------------------------------------------*//*!
161 //  * \brief Create a instance with the VK_EXT_acquire_drm_display extension.
162 //  *
163 //  * \return The created instance
164 //  *//*--------------------------------------------------------------------*/
createInstanceWithAcquireDrmDisplay(void)165 CustomInstance AcquireDrmDisplayTestInstance::createInstanceWithAcquireDrmDisplay (void)
166 {
167 	vector<VkExtensionProperties> supportedExtensions = enumerateInstanceExtensionProperties(m_context.getPlatformInterface(), DE_NULL);
168 	vector<string> requiredExtensions = {
169 		"VK_EXT_acquire_drm_display",
170 		"VK_EXT_direct_mode_display",
171 	};
172 
173 	for (const auto& extension : requiredExtensions)
174 		if (!isExtensionStructSupported(supportedExtensions, RequiredExtension(extension)))
175 			TCU_THROW(NotSupportedError, "Instance extension not supported.");
176 
177 	return createCustomInstanceWithExtensions(m_context, requiredExtensions);
178 }
179 
180 #if DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
181 // /*--------------------------------------------------------------------*//*!
182 //  * \brief Open a fd for the Drm corresponding to the Vulkan instance
183 //  *
184 //  * \return A LibDrm::FdPtr with the int fd.
185 //  *//*--------------------------------------------------------------------*/
getDrmFdPtr(void)186 LibDrm::FdPtr AcquireDrmDisplayTestInstance::getDrmFdPtr (void)
187 {
188 	VkPhysicalDeviceProperties2			deviceProperties2;
189 	VkPhysicalDeviceDrmPropertiesEXT	deviceDrmProperties;
190 
191 	deMemset(&deviceDrmProperties, 0, sizeof(deviceDrmProperties));
192 	deviceDrmProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT;
193 	deviceDrmProperties.pNext = DE_NULL;
194 
195 	deMemset(&deviceProperties2, 0, sizeof(deviceProperties2));
196 	deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
197 	deviceProperties2.pNext = &deviceDrmProperties;
198 
199 	m_vki.getPhysicalDeviceProperties2(m_physDevice, &deviceProperties2);
200 
201 	if (!deviceDrmProperties.hasPrimary)
202 		TCU_THROW(NotSupportedError, "No DRM primary device.");
203 
204 	int numDrmDevices;
205 	drmDevicePtr* drmDevices = m_libDrm.getDevices(&numDrmDevices);
206 	const char* drmNode = m_libDrm.findDeviceNode(drmDevices, numDrmDevices, deviceDrmProperties.primaryMajor, deviceDrmProperties.primaryMinor);
207 
208 	if (!drmNode)
209 		TCU_THROW(NotSupportedError, "No DRM node.");
210 
211 	return m_libDrm.openFd(drmNode);
212 }
213 
214 /*--------------------------------------------------------------------*//*!
215  * \brief Get a connected Drm connector
216  *
217  * \param fd			A Drm fd to query
218  * \param connectorId	If nonzero, a connector to be different from
219  * \return The connectorId of the connected Drm connector
220  *//*--------------------------------------------------------------------*/
getConnectedConnectorId(int fd,deUint32 connectorId)221 deUint32 AcquireDrmDisplayTestInstance::getConnectedConnectorId (int fd, deUint32 connectorId)
222 {
223 	LibDrm::ResPtr res = m_libDrm.getResources(fd);
224 	if (!res)
225 		TCU_THROW(NotSupportedError, "Could not get DRM resources.");
226 
227 	for (int i = 0; i < res->count_connectors; ++i)
228 	{
229 		if (connectorId && connectorId == res->connectors[i])
230 			continue;
231 		LibDrm::ConnectorPtr conn = m_libDrm.getConnector(fd, res->connectors[i]);
232 
233 		if (conn && conn->connection == DRM_MODE_CONNECTED) {
234 			return res->connectors[i];
235 		}
236 	}
237 	return 0;
238 }
239 
240 /*--------------------------------------------------------------------*//*!
241  * \brief Get a valid Drm crtc for the connector
242  *
243  * \param fd			A Drm fd to query
244  * \param connectorId	The connector that the crtc is valid for
245  * \return The crtcId of the valid Drm crtc
246  *//*--------------------------------------------------------------------*/
getValidCrtcId(int fd,deUint32 connectorId)247 deUint32 AcquireDrmDisplayTestInstance::getValidCrtcId (int fd, deUint32 connectorId)
248 {
249 	LibDrm::ResPtr res = m_libDrm.getResources(fd);
250 	LibDrm::ConnectorPtr conn = m_libDrm.getConnector(fd, connectorId);
251 	if (!res || !conn)
252 		TCU_THROW(NotSupportedError, "Could not get DRM resources or connector.");
253 
254 	for (int i = 0; i < conn->count_encoders; ++i)
255 	{
256 		LibDrm::EncoderPtr enc = m_libDrm.getEncoder(fd, conn->encoders[i]);
257 		if (!enc)
258 			continue;
259 
260 		for (int j = 0; j < res->count_crtcs; ++j)
261 			if (enc->possible_crtcs & (1 << j))
262 				return res->crtcs[j];
263 	}
264 	return 0;
265 }
266 
267 /*--------------------------------------------------------------------*//*!
268  * \brief Checks if we have Drm master permissions
269  *
270  * \param fd A Drm fd to query
271  * \return True if we have Drm master
272  *//*--------------------------------------------------------------------*/
isDrmMaster(int fd)273 bool AcquireDrmDisplayTestInstance::isDrmMaster (int fd)
274 {
275 	/*
276 	 * Call a drm API that requires master permissions, but with an invalid
277 	 * value. If we are master it should return -EINVAL, but if we are not
278 	 * it should return -EACCESS.
279 	 */
280 	return m_libDrm.authMagic(fd, 0) != -EACCES;
281 }
282 
283 // /*--------------------------------------------------------------------*//*!
284 //  * \brief Tests successfully getting a connected Drm display
285 //  *
286 //  * Throws an exception on fail.
287 //  *
288 //  * \return tcu::TestStatus::pass on success
289 //  *//*--------------------------------------------------------------------*/
testGetDrmDisplayEXT(void)290 tcu::TestStatus AcquireDrmDisplayTestInstance::testGetDrmDisplayEXT (void)
291 {
292 	LibDrm::FdPtr fdPtr = getDrmFdPtr();
293 	if (!fdPtr)
294 		TCU_THROW(NotSupportedError, "Could not open DRM.");
295 	int fd = *fdPtr;
296 
297 	deUint32 connectorId = getConnectedConnectorId(fd);
298 	if (!connectorId)
299 		TCU_THROW(NotSupportedError, "Could not find a DRM connector.");
300 
301 	VkDisplayKHR display = INVALID_PTR;
302 	VkResult result = m_vki.getDrmDisplayEXT(m_physDevice, fd, connectorId, &display);
303 	if (result != VK_SUCCESS)
304 		TCU_FAIL("vkGetDrmDisplayEXT failed.");
305 
306 	if (display == DE_NULL || display == INVALID_PTR)
307 		TCU_FAIL("vkGetDrmDisplayEXT did not set display.");
308 
309 	return tcu::TestStatus::pass("pass");
310 }
311 
312 // /*--------------------------------------------------------------------*//*!
313 //  * \brief Tests getting an error with an invalid Drm fd
314 //  *
315 //  * Throws an exception on fail.
316 //  *
317 //  * \return tcu::TestStatus::pass on success
318 //  *//*--------------------------------------------------------------------*/
testGetDrmDisplayEXTInvalidFd(void)319 tcu::TestStatus AcquireDrmDisplayTestInstance::testGetDrmDisplayEXTInvalidFd (void)
320 {
321 	LibDrm::FdPtr fdPtr = getDrmFdPtr();
322 	if (!fdPtr)
323 		TCU_THROW(NotSupportedError, "Could not open DRM.");
324 	int fd = *fdPtr;
325 
326 	deUint32 connectorId = getConnectedConnectorId(fd);
327 	if (!connectorId)
328 		TCU_THROW(NotSupportedError, "Could not find a DRM connector.");
329 
330 	int invalidFd = fd + 1;
331 	VkDisplayKHR display = INVALID_PTR;
332 	VkResult result = m_vki.getDrmDisplayEXT(m_physDevice, invalidFd, connectorId, &display);
333 	if (result != VK_ERROR_UNKNOWN)
334 		TCU_FAIL("vkGetDrmDisplayEXT failed to return error.");
335 
336 	if (display != DE_NULL)
337 		TCU_FAIL("vkGetDrmDisplayEXT did not set display to null.");
338 
339 	return tcu::TestStatus::pass("pass");
340 }
341 
342 // /*--------------------------------------------------------------------*//*!
343 //  * \brief Tests getting an error with an invalid connector id
344 //  *
345 //  * Throws an exception on fail.
346 //  *
347 //  * \return tcu::TestStatus::pass on success
348 //  *//*--------------------------------------------------------------------*/
testGetDrmDisplayEXTInvalidConnectorId(void)349 tcu::TestStatus AcquireDrmDisplayTestInstance::testGetDrmDisplayEXTInvalidConnectorId (void)
350 {
351 	LibDrm::FdPtr fdPtr = getDrmFdPtr();
352 	if (!fdPtr)
353 		TCU_THROW(NotSupportedError, "Could not open DRM.");
354 	int fd = *fdPtr;
355 
356 	deUint32 connectorId = getConnectedConnectorId(fd);
357 	if (!connectorId)
358 		TCU_THROW(NotSupportedError, "Could not find a DRM connector.");
359 
360 	deUint32 invalidConnectorId = connectorId + 1234;
361 	VkDisplayKHR display = INVALID_PTR;
362 	VkResult result = m_vki.getDrmDisplayEXT(m_physDevice, fd, invalidConnectorId, &display);
363 	if (result != VK_ERROR_UNKNOWN)
364 		TCU_FAIL("vkGetDrmDisplayEXT failed to return error.");
365 
366 	if (display != DE_NULL)
367 		TCU_FAIL("vkGetDrmDisplayEXT did not set display to null.");
368 
369 	return tcu::TestStatus::pass("pass");
370 }
371 
372 // /*--------------------------------------------------------------------*//*!
373 //  * \brief Tests successfully getting without master
374 //  *
375 //  * Throws an exception on fail.
376 //  *
377 //  * \return tcu::TestStatus::pass on success
378 //  *//*--------------------------------------------------------------------*/
testGetDrmDisplayEXTNotMaster(void)379 tcu::TestStatus AcquireDrmDisplayTestInstance::testGetDrmDisplayEXTNotMaster (void)
380 {
381 	LibDrm::FdPtr masterFdPtr = getDrmFdPtr();
382 	LibDrm::FdPtr notMasterFdPtr = getDrmFdPtr();
383 	if (!masterFdPtr || !notMasterFdPtr)
384 		TCU_THROW(NotSupportedError, "Could not open DRM.");
385 	if (*masterFdPtr == *notMasterFdPtr)
386 		TCU_THROW(NotSupportedError, "Did not open 2 different fd.");
387 	int fd = *notMasterFdPtr;
388 
389 	deUint32 connectorId = getConnectedConnectorId(fd);
390 	if (!connectorId)
391 		TCU_THROW(NotSupportedError, "Could not find a DRM connector.");
392 
393 	VkDisplayKHR display = INVALID_PTR;
394 	VkResult result = m_vki.getDrmDisplayEXT(m_physDevice, fd, connectorId, &display);
395 	if (result != VK_SUCCESS)
396 		TCU_FAIL("vkGetDrmDisplayEXT failed.");
397 
398 	if (display == DE_NULL || display == INVALID_PTR)
399 		TCU_FAIL("vkGetDrmDisplayEXT did not set display.");
400 
401 	return tcu::TestStatus::pass("pass");
402 }
403 
404 // /*--------------------------------------------------------------------*//*!
405 //  * \brief Tests getting an error with an unowned connector id
406 //  *
407 //  * This needs to be run with drm master permissions.
408 //  * No other drm client can be running, such as X or Wayland.
409 //  * Then, to run with drm master, either:
410 //  *   Add your user to the "video" linux group.
411 //  *   Log in to the virtual tty.
412 //  *   Run as root.
413 //  * This also requires 2 physically connected displays.
414 //  *
415 //  * Throws an exception on fail.
416 //  *
417 //  * \return tcu::TestStatus::pass on success
418 //  *//*--------------------------------------------------------------------*/
testGetDrmDisplayEXTUnownedConnectorId(void)419 tcu::TestStatus AcquireDrmDisplayTestInstance::testGetDrmDisplayEXTUnownedConnectorId (void)
420 {
421 	LibDrm::FdPtr fdPtr = getDrmFdPtr();
422 	if (!fdPtr)
423 		TCU_THROW(NotSupportedError, "Could not open DRM.");
424 	int fd = *fdPtr;
425 
426 	if (!isDrmMaster(fd))
427 		TCU_THROW(NotSupportedError, "Does not have drm master permissions.");
428 
429 	deUint32 connectorId		= getConnectedConnectorId(fd);
430 	deUint32 otherConnectorId	= getConnectedConnectorId(fd, connectorId);
431 	deUint32 crtcId				= getValidCrtcId(fd, connectorId);
432 	if (!connectorId || !crtcId || !otherConnectorId || connectorId == otherConnectorId)
433 		TCU_THROW(NotSupportedError, "Could not find 2 DRM connectors or a crtc.");
434 
435 	// Lease the first connector, but try to get the other connector.
436 	deUint32		objects[2] = {connectorId, crtcId};
437 	LibDrm::FdPtr	leaseFdPtr = m_libDrm.createLease(fd, objects, 2, O_CLOEXEC);
438 	if (!leaseFdPtr)
439 		TCU_THROW(NotSupportedError, "Could not lease DRM.");
440 	int leaseFd = *leaseFdPtr;
441 
442 	VkDisplayKHR display = INVALID_PTR;
443 	VkResult result = m_vki.getDrmDisplayEXT(m_physDevice, leaseFd, otherConnectorId, &display);
444 	if (result != VK_ERROR_UNKNOWN)
445 		TCU_FAIL("vkGetDrmDisplayEXT failed to return error.");
446 
447 	if (display != DE_NULL)
448 		TCU_FAIL("vkGetDrmDisplayEXT did not set display to null.");
449 
450 	return tcu::TestStatus::pass("pass");
451 }
452 
453 // /*--------------------------------------------------------------------*//*!
454 //  * \brief Tests successfully acquiring a connected Drm display
455 //  *
456 //  * This needs to be run with drm master permissions.
457 //  * No other drm client can be running, such as X or Wayland.
458 //  * Then, to run with drm master, either:
459 //  *   Add your user to the "video" linux group.
460 //  *   Log in to the virtual tty.
461 //  *   Run as root.
462 //  *
463 //  * Throws an exception on fail.
464 //  *
465 //  * \return tcu::TestStatus::pass on success
466 //  *//*--------------------------------------------------------------------*/
testAcquireDrmDisplayEXT(void)467 tcu::TestStatus AcquireDrmDisplayTestInstance::testAcquireDrmDisplayEXT (void)
468 {
469 	LibDrm::FdPtr fdPtr = getDrmFdPtr();
470 	if (!fdPtr)
471 		TCU_THROW(NotSupportedError, "Could not open DRM.");
472 	int fd = *fdPtr;
473 
474 	if (!isDrmMaster(fd))
475 		TCU_THROW(NotSupportedError, "Does not have drm master permissions.");
476 
477 	deUint32 connectorId = getConnectedConnectorId(fd);
478 	if (!connectorId)
479 		TCU_THROW(NotSupportedError, "Could not find a DRM connector.");
480 
481 	VkDisplayKHR display = INVALID_PTR;
482 	VkResult result = m_vki.getDrmDisplayEXT(m_physDevice, fd, connectorId, &display);
483 	if (result != VK_SUCCESS)
484 		TCU_FAIL("vkGetDrmDisplayEXT failed.");
485 
486 	if (display == DE_NULL || display == INVALID_PTR)
487 		TCU_FAIL("vkGetDrmDisplayEXT did not set display.");
488 
489 	result = m_vki.acquireDrmDisplayEXT(m_physDevice, fd, display);
490 	if (result != VK_SUCCESS)
491 		TCU_FAIL("vkAcquireDrmDisplayEXT failed.");
492 
493 	return tcu::TestStatus::pass("pass");
494 }
495 
496 // /*--------------------------------------------------------------------*//*!
497 //  * \brief Tests getting an error with an invalid drm fd
498 //  *
499 //  * Throws an exception on fail.
500 //  *
501 //  * \return tcu::TestStatus::pass on success
502 //  *//*--------------------------------------------------------------------*/
testAcquireDrmDisplayEXTInvalidFd(void)503 tcu::TestStatus AcquireDrmDisplayTestInstance::testAcquireDrmDisplayEXTInvalidFd (void)
504 {
505 	LibDrm::FdPtr fdPtr = getDrmFdPtr();
506 	if (!fdPtr)
507 		TCU_THROW(NotSupportedError, "Could not open DRM.");
508 	int fd = *fdPtr;
509 
510 	deUint32 connectorId = getConnectedConnectorId(fd);
511 	if (!connectorId)
512 		TCU_THROW(NotSupportedError, "Could not find a DRM connector.");
513 
514 	VkDisplayKHR display = INVALID_PTR;
515 	VkResult result = m_vki.getDrmDisplayEXT(m_physDevice, fd, connectorId, &display);
516 	if (result != VK_SUCCESS)
517 		TCU_FAIL("vkGetDrmDisplayEXT failed.");
518 
519 	if (display == DE_NULL || display == INVALID_PTR)
520 		TCU_FAIL("vkGetDrmDisplayEXT did not set display.");
521 
522 	int invalidFd = fd + 1;
523 	result = m_vki.acquireDrmDisplayEXT(m_physDevice, invalidFd, display);
524 	if (result != VK_ERROR_UNKNOWN)
525 		TCU_FAIL("vkAcquireDrmDisplayEXT failed to return error.");
526 
527 	return tcu::TestStatus::pass("pass");
528 }
529 
530 // /*--------------------------------------------------------------------*//*!
531 //  * \brief Tests getting an error without master
532 //  *
533 //  * Throws an exception on fail.
534 //  *
535 //  * \return tcu::TestStatus::pass on success
536 //  *//*--------------------------------------------------------------------*/
testAcquireDrmDisplayEXTNotMaster(void)537 tcu::TestStatus AcquireDrmDisplayTestInstance::testAcquireDrmDisplayEXTNotMaster (void)
538 {
539 	LibDrm::FdPtr masterFdPtr = getDrmFdPtr();
540 	LibDrm::FdPtr notMasterFdPtr = getDrmFdPtr();
541 	if (!masterFdPtr || !notMasterFdPtr)
542 		TCU_THROW(NotSupportedError, "Could not open DRM.");
543 	if (*masterFdPtr == *notMasterFdPtr)
544 		TCU_THROW(NotSupportedError, "Did not open 2 different fd.");
545 	int fd = *notMasterFdPtr;
546 
547 	deUint32 connectorId = getConnectedConnectorId(fd);
548 	if (!connectorId)
549 		TCU_THROW(NotSupportedError, "Could not find a DRM connector.");
550 
551 	VkDisplayKHR display = INVALID_PTR;
552 	VkResult result = m_vki.getDrmDisplayEXT(m_physDevice, fd, connectorId, &display);
553 	if (result != VK_SUCCESS)
554 		TCU_FAIL("vkGetDrmDisplayEXT failed.");
555 
556 	if (display == DE_NULL || display == INVALID_PTR)
557 		TCU_FAIL("vkGetDrmDisplayEXT did not set display.");
558 
559 	result = m_vki.acquireDrmDisplayEXT(m_physDevice, fd, display);
560 	if (result != VK_ERROR_INITIALIZATION_FAILED)
561 		TCU_FAIL("vkAcquireDrmDisplayEXT failed to return error.");
562 
563 	return tcu::TestStatus::pass("pass");
564 }
565 
566 // /*--------------------------------------------------------------------*//*!
567 //  * \brief Tests getting an error with an unowned connector id
568 //  *
569 //  * This needs to be run with drm master permissions.
570 //  * No other drm client can be running, such as X or Wayland.
571 //  * Then, to run with drm master, either:
572 //  *   Add your user to the "video" linux group.
573 //  *   Log in to the virtual tty.
574 //  *   Run as root.
575 //  * This also requires 2 physically connected displays.
576 //  *
577 //  * Throws an exception on fail.
578 //  *
579 //  * \return tcu::TestStatus::pass on success
580 //  *//*--------------------------------------------------------------------*/
testAcquireDrmDisplayEXTUnownedConnectorId(void)581 tcu::TestStatus AcquireDrmDisplayTestInstance::testAcquireDrmDisplayEXTUnownedConnectorId (void)
582 {
583 	LibDrm::FdPtr fdPtr = getDrmFdPtr();
584 	if (!fdPtr)
585 		TCU_THROW(NotSupportedError, "Could not open DRM.");
586 	int fd = *fdPtr;
587 
588 	if (!isDrmMaster(fd))
589 		TCU_THROW(NotSupportedError, "Does not have drm master permissions.");
590 
591 	deUint32 connectorId		= getConnectedConnectorId(fd);
592 	deUint32 otherConnectorId	= getConnectedConnectorId(fd, connectorId);
593 	deUint32 crtcId				= getValidCrtcId(fd, connectorId);
594 	if (!connectorId || !crtcId || !otherConnectorId || connectorId == otherConnectorId)
595 		TCU_THROW(NotSupportedError, "Could not find 2 DRM connectors or a crtc.");
596 
597 	// Lease the first connector, but try to get and acquire the other connector.
598 	deUint32		objects[2] = {connectorId, crtcId};
599 	LibDrm::FdPtr	leaseFdPtr = m_libDrm.createLease(fd, objects, 2, O_CLOEXEC);
600 	if (!leaseFdPtr)
601 		TCU_THROW(NotSupportedError, "Could not lease DRM.");
602 	int leaseFd = *leaseFdPtr;
603 
604 	// We know that this would fail with leaseFd, so use the original master fd.
605 	VkDisplayKHR display = INVALID_PTR;
606 	VkResult result = m_vki.getDrmDisplayEXT(m_physDevice, fd, otherConnectorId, &display);
607 	if (result != VK_SUCCESS)
608 		TCU_FAIL("vkGetDrmDisplayEXT failed.");
609 
610 	if (display == DE_NULL || display == INVALID_PTR)
611 		TCU_FAIL("vkGetDrmDisplayEXT did not set display.");
612 
613 	result = m_vki.acquireDrmDisplayEXT(m_physDevice, leaseFd, display);
614 	if (result != VK_ERROR_INITIALIZATION_FAILED)
615 		TCU_FAIL("vkAcquireDrmDisplayEXT failed to return error.");
616 
617 	return tcu::TestStatus::pass("pass");
618 }
619 
620 // /*--------------------------------------------------------------------*//*!
621 //  * \brief Tests successfully releasing an acquired Drm display
622 //  *
623 //  * This needs to be run with drm master permissions.
624 //  * No other drm client can be running, such as X or Wayland.
625 //  * Then, to run with drm master, either:
626 //  *   Add your user to the "video" linux group.
627 //  *   Log in to the virtual tty.
628 //  *   Run as root.
629 //  *
630 //  * Throws an exception on fail.
631 //  *
632 //  * \return tcu::TestStatus::pass on success
633 //  *//*--------------------------------------------------------------------*/
testReleaseDisplayEXT(void)634 tcu::TestStatus AcquireDrmDisplayTestInstance::testReleaseDisplayEXT (void)
635 {
636 	LibDrm::FdPtr fdPtr = getDrmFdPtr();
637 	if (!fdPtr)
638 		TCU_THROW(NotSupportedError, "Could not open DRM.");
639 	int fd = *fdPtr;
640 
641 	if (!isDrmMaster(fd))
642 		TCU_THROW(NotSupportedError, "Does not have drm master permissions.");
643 
644 	deUint32 connectorId = getConnectedConnectorId(fd);
645 	if (!connectorId)
646 		TCU_THROW(NotSupportedError, "Could not find a DRM connector.");
647 
648 	VkDisplayKHR display = INVALID_PTR;
649 	VkResult result = m_vki.getDrmDisplayEXT(m_physDevice, fd, connectorId, &display);
650 	if (result != VK_SUCCESS)
651 		TCU_FAIL("vkGetDrmDisplayEXT failed.");
652 
653 	if (display == DE_NULL || display == INVALID_PTR)
654 		TCU_FAIL("vkGetDrmDisplayEXT did not set display.");
655 
656 	result = m_vki.acquireDrmDisplayEXT(m_physDevice, fd, display);
657 	if (result != VK_SUCCESS)
658 		TCU_FAIL("vkAcquireDrmDisplayEXT failed.");
659 
660 	result = m_vki.releaseDisplayEXT(m_physDevice, display);
661 	if (result != VK_SUCCESS)
662 		TCU_FAIL("vkReleaseDisplayEXT failed.");
663 
664 	return tcu::TestStatus::pass("pass");
665 }
666 #endif // DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
667 
668 /*--------------------------------------------------------------------*//*!
669  * \brief Acquire Drm display tests case class
670  *//*--------------------------------------------------------------------*/
671 class AcquireDrmDisplayTestsCase : public vkt::TestCase
672 {
673 public:
AcquireDrmDisplayTestsCase(tcu::TestContext & context,const char * name,const char * description,const DrmTestIndex testId)674 	AcquireDrmDisplayTestsCase (tcu::TestContext &context, const char *name, const char *description, const DrmTestIndex testId)
675 		: TestCase	(context, name, description)
676 		, m_testId	(testId)
677 	{
678 	}
679 private:
680 	const DrmTestIndex	m_testId;
681 
createInstance(vkt::Context & context) const682 	vkt::TestInstance*	createInstance	(vkt::Context& context) const
683 	{
684 		return new AcquireDrmDisplayTestInstance(context, m_testId);
685 	}
686 };
687 
688 
689 /*--------------------------------------------------------------------*//*!
690  * \brief Adds a test into group
691  *//*--------------------------------------------------------------------*/
addTest(tcu::TestCaseGroup * group,const DrmTestIndex testId,const char * name,const char * description)692 static void addTest (tcu::TestCaseGroup* group, const DrmTestIndex testId, const char* name, const char* description)
693 {
694 	tcu::TestContext&	testCtx	= group->getTestContext();
695 
696 	group->addChild(new AcquireDrmDisplayTestsCase(testCtx, name, description, testId));
697 }
698 
699 /*--------------------------------------------------------------------*//*!
700  * \brief Adds VK_EXT_acquire_drm_display extension tests into group
701  *//*--------------------------------------------------------------------*/
createAcquireDrmDisplayTests(tcu::TestCaseGroup * group)702 void createAcquireDrmDisplayTests (tcu::TestCaseGroup* group)
703 {
704 	// VK_EXT_acquire_drm_display extension tests
705 	addTest(group, DRM_TEST_INDEX_GET_DRM_DISPLAY,							"get_drm_display",							"Get Drm display test");
706 	addTest(group, DRM_TEST_INDEX_GET_DRM_DISPLAY_INVALID_FD,				"get_drm_display_invalid_fd",				"Get Drm display with invalid fd test");
707 	addTest(group, DRM_TEST_INDEX_GET_DRM_DISPLAY_INVALID_CONNECTOR_ID,		"get_drm_display_invalid_connector_id",		"Get Drm display with invalid connector id test");
708 	addTest(group, DRM_TEST_INDEX_GET_DRM_DISPLAY_NOT_MASTER,				"get_drm_display_not_master",				"Get Drm display with not master test");
709 	addTest(group, DRM_TEST_INDEX_GET_DRM_DISPLAY_UNOWNED_CONNECTOR_ID,		"get_drm_display_unowned_connector_id",		"Get Drm display with unowned connector id test");
710 	addTest(group, DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY,						"acquire_drm_display",						"Acquire Drm display test");
711 	addTest(group, DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY_INVALID_FD,			"acquire_drm_display_invalid_fd",			"Acquire Drm display with invalid fd test");
712 	addTest(group, DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY_NOT_MASTER,			"acquire_drm_display_not_master",			"Acquire Drm display with not master test");
713 	addTest(group, DRM_TEST_INDEX_ACQUIRE_DRM_DISPLAY_UNOWNED_CONNECTOR_ID,	"acquire_drm_display_unowned_connector_id",	"Acquire Drm display with unowned connector id test");
714 
715 	// VK_EXT_direct_mode_display extension tests
716 	addTest(group, DRM_TEST_INDEX_RELEASE_DISPLAY,						"release_display",						"Release Drm display test");
717 }
718 
719 } //wsi
720 } //vkt
721 
722