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