| /*------------------------------------------------------------------------- |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2022 NVIDIA, Inc. |
| * Copyright (c) 2022 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Drm utilities. |
| *//*--------------------------------------------------------------------*/ |
| |
| #if DEQP_SUPPORT_DRM && !defined(CTS_USES_VULKANSC) |
| |
| #include "tcuLibDrm.hpp" |
| |
| #include "tcuDefs.hpp" |
| |
| #include "deMemory.h" |
| |
| #include <fcntl.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <unistd.h> |
| |
| #if !defined(__FreeBSD__) |
| // major() and minor() are defined in sys/types.h on FreeBSD, and in |
| // sys/sysmacros.h on Linux and Solaris. |
| #include <sys/sysmacros.h> |
| #endif // !defined(__FreeBSD__) |
| |
| namespace tcu |
| { |
| |
| LibDrm::LibDrm(void) : DynamicLibrary(libDrmFiles) |
| { |
| pGetDevices2 = (PFNDRMGETDEVICES2PROC)getFunction("drmGetDevices2"); |
| pGetDevices = (PFNDRMGETDEVICESPROC)getFunction("drmGetDevices"); |
| pFreeDevices = (PFNDRMFREEDEVICESPROC)getFunction("drmFreeDevices"); |
| pGetResources = (PFNDRMMODEGETRESOURCESPROC)getFunction("drmModeGetResources"); |
| pFreeResources = (PFNDRMMODEFREERESOURCESPROC)getFunction("drmModeFreeResources"); |
| pGetConnector = (PFNDRMMODEGETCONNECTORPROC)getFunction("drmModeGetConnector"); |
| pFreeConnector = (PFNDRMMODEFREECONNECTORPROC)getFunction("drmModeFreeConnector"); |
| pGetEncoder = (PFNDRMMODEGETENCODERPROC)getFunction("drmModeGetEncoder"); |
| pFreeEncoder = (PFNDRMMODEFREEENCODERPROC)getFunction("drmModeFreeEncoder"); |
| pCreateLease = (PFNDRMMODECREATELEASEPROC)getFunction("drmModeCreateLease"); |
| pAuthMagic = (PFNDRMAUTHMAGIC)getFunction("drmAuthMagic"); |
| |
| /* libdrm did not add this API until 2.4.65, return NotSupported if it's too old. */ |
| if (!pGetDevices2 && !pGetDevices) |
| TCU_THROW(NotSupportedError, "Could not load a valid drmGetDevices() variant from libdrm"); |
| if (!pFreeDevices) |
| TCU_THROW(NotSupportedError, "Could not load drmFreeDevices() from libdrm"); |
| if (!pGetResources) |
| TCU_FAIL("Could not load drmModeGetResources() from libdrm"); |
| if (!pFreeResources) |
| TCU_FAIL("Could not load drmModeFreeResources() from libdrm"); |
| if (!pGetConnector) |
| TCU_FAIL("Could not load drmModeGetConnector() from libdrm"); |
| if (!pFreeConnector) |
| TCU_FAIL("Could not load drmModeFreeConnector() from libdrm"); |
| if (!pGetEncoder) |
| TCU_FAIL("Could not load drmModeGetEncoder() from libdrm"); |
| if (!pFreeEncoder) |
| TCU_FAIL("Could not load drmModeFreeEncoder() from libdrm"); |
| if (!pCreateLease) |
| TCU_FAIL("Could not load drmModeCreateLease() from libdrm"); |
| if (!pAuthMagic) |
| TCU_FAIL("Could not load drmAuthMagic() from libdrm"); |
| } |
| |
| LibDrm::~LibDrm(void) |
| { |
| } |
| |
| drmDevicePtr *LibDrm::getDevices(int *pNumDevices) const |
| { |
| *pNumDevices = intGetDevices(DE_NULL, 0); |
| |
| if (*pNumDevices < 0) |
| TCU_THROW(NotSupportedError, "Failed to query number of DRM devices in system"); |
| |
| if (*pNumDevices == 0) |
| return DE_NULL; |
| |
| drmDevicePtr *devs = new drmDevicePtr[*pNumDevices]; |
| |
| *pNumDevices = intGetDevices(devs, *pNumDevices); |
| |
| if (*pNumDevices < 0) |
| { |
| delete[] devs; |
| TCU_FAIL("Failed to query list of DRM devices in system"); |
| } |
| |
| return devs; |
| } |
| |
| const char *LibDrm::findDeviceNode(drmDevicePtr *devices, int count, int64_t major, int64_t minor) const |
| { |
| for (int i = 0; i < count; i++) |
| { |
| for (int j = 0; j < DRM_NODE_MAX; j++) |
| { |
| if (!(devices[i]->available_nodes & (1 << j))) |
| continue; |
| |
| struct stat statBuf; |
| deMemset(&statBuf, 0, sizeof(statBuf)); |
| int res = stat(devices[i]->nodes[j], &statBuf); |
| |
| if (res || !(statBuf.st_mode & S_IFCHR)) |
| continue; |
| |
| if (major == major(statBuf.st_rdev) && minor == minor(statBuf.st_rdev)) |
| { |
| return devices[i]->nodes[j]; |
| } |
| } |
| } |
| |
| return DE_NULL; |
| } |
| |
| void LibDrm::freeDevices(drmDevicePtr *devices, int count) const |
| { |
| pFreeDevices(devices, count); |
| delete[] devices; |
| } |
| |
| static void closeAndDeleteFd(int *fd) |
| { |
| if (fd) |
| { |
| close(*fd); |
| delete fd; |
| } |
| } |
| |
| LibDrm::FdPtr LibDrm::openFd(const char *node) const |
| { |
| int fd = open(node, O_RDWR); |
| if (fd < 0) |
| return FdPtr(DE_NULL); |
| else |
| return FdPtr(new int{fd}, closeAndDeleteFd); |
| } |
| |
| LibDrm::ResPtr LibDrm::getResources(int fd) const |
| { |
| return ResPtr(pGetResources(fd), pFreeResources); |
| } |
| |
| LibDrm::ConnectorPtr LibDrm::getConnector(int fd, uint32_t connectorId) const |
| { |
| return ConnectorPtr(pGetConnector(fd, connectorId), pFreeConnector); |
| } |
| |
| LibDrm::EncoderPtr LibDrm::getEncoder(int fd, uint32_t encoderId) const |
| { |
| return EncoderPtr(pGetEncoder(fd, encoderId), pFreeEncoder); |
| } |
| |
| LibDrm::FdPtr LibDrm::createLease(int fd, const uint32_t *objects, int numObjects, int flags) const |
| { |
| uint32_t leaseId; |
| int leaseFd = pCreateLease(fd, objects, numObjects, flags, &leaseId); |
| if (leaseFd < 0) |
| return FdPtr(DE_NULL); |
| else |
| return FdPtr(new int{leaseFd}, closeAndDeleteFd); |
| } |
| |
| int LibDrm::authMagic(int fd, drm_magic_t magic) const |
| { |
| return pAuthMagic(fd, magic); |
| } |
| |
| int LibDrm::intGetDevices(drmDevicePtr devices[], int maxDevices) const |
| { |
| if (pGetDevices2) |
| return pGetDevices2(0, devices, maxDevices); |
| else |
| return pGetDevices(devices, maxDevices); |
| } |
| |
| const char *LibDrm::libDrmFiles[] = {"libdrm.so.2", "libdrm.so", nullptr}; |
| |
| } // namespace tcu |
| |
| #endif // DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC) |