| /*------------------------------------------------------------------------- |
| * 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, deInt64 major, deInt64 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, deUint32 connectorId) const |
| { |
| return ConnectorPtr(pGetConnector(fd, connectorId), pFreeConnector); |
| } |
| |
| LibDrm::EncoderPtr LibDrm::getEncoder (int fd, deUint32 encoderId) const |
| { |
| return EncoderPtr(pGetEncoder(fd, encoderId), pFreeEncoder); |
| } |
| |
| LibDrm::FdPtr LibDrm::createLease (int fd, const deUint32 *objects, int numObjects, int flags) const |
| { |
| deUint32 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 |
| }; |
| |
| } // tcu |
| |
| #endif // DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC) |