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