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