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