File indexing completed on 2024-05-19 05:31:37

0001 /*
0002     SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "core/shmgraphicsbufferallocator.h"
0008 
0009 #include "config-kwin.h"
0010 
0011 #include "core/graphicsbuffer.h"
0012 #include "utils/memorymap.h"
0013 
0014 #include <drm_fourcc.h>
0015 #include <fcntl.h>
0016 #include <sys/mman.h>
0017 #include <unistd.h>
0018 
0019 namespace KWin
0020 {
0021 
0022 class ShmGraphicsBuffer : public GraphicsBuffer
0023 {
0024     Q_OBJECT
0025 
0026 public:
0027     ShmGraphicsBuffer(ShmAttributes &&attributes, MemoryMap &&memoryMap);
0028 
0029     Map map(MapFlags flags) override;
0030     void unmap() override;
0031 
0032     QSize size() const override;
0033     bool hasAlphaChannel() const override;
0034     const ShmAttributes *shmAttributes() const override;
0035 
0036 private:
0037     ShmAttributes m_attributes;
0038     MemoryMap m_memoryMap;
0039     bool m_hasAlphaChannel;
0040 };
0041 
0042 ShmGraphicsBuffer::ShmGraphicsBuffer(ShmAttributes &&attributes, MemoryMap &&memoryMap)
0043     : m_attributes(std::move(attributes))
0044     , m_memoryMap(std::move(memoryMap))
0045     , m_hasAlphaChannel(alphaChannelFromDrmFormat(attributes.format))
0046 {
0047 }
0048 
0049 GraphicsBuffer::Map ShmGraphicsBuffer::map(MapFlags flags)
0050 {
0051     if (m_memoryMap.isValid()) {
0052         return Map{
0053             .data = m_memoryMap.data(),
0054             .stride = uint32_t(m_attributes.stride),
0055         };
0056     } else {
0057         return Map{};
0058     }
0059 }
0060 
0061 void ShmGraphicsBuffer::unmap()
0062 {
0063 }
0064 
0065 QSize ShmGraphicsBuffer::size() const
0066 {
0067     return m_attributes.size;
0068 }
0069 
0070 bool ShmGraphicsBuffer::hasAlphaChannel() const
0071 {
0072     return m_hasAlphaChannel;
0073 }
0074 
0075 const ShmAttributes *ShmGraphicsBuffer::shmAttributes() const
0076 {
0077     return &m_attributes;
0078 }
0079 
0080 GraphicsBuffer *ShmGraphicsBufferAllocator::allocate(const GraphicsBufferOptions &options)
0081 {
0082     if (!options.software) {
0083         return nullptr;
0084     }
0085     if (!options.modifiers.isEmpty() && !options.modifiers.contains(DRM_FORMAT_MOD_LINEAR)) {
0086         return nullptr;
0087     }
0088 
0089     switch (options.format) {
0090     case DRM_FORMAT_ARGB8888:
0091     case DRM_FORMAT_XRGB8888:
0092         break;
0093     default:
0094         return nullptr;
0095     }
0096 
0097     const int stride = options.size.width() * 4;
0098     const int bufferSize = options.size.height() * stride;
0099 
0100 #if HAVE_MEMFD
0101     FileDescriptor fd = FileDescriptor(memfd_create("shm", MFD_CLOEXEC | MFD_ALLOW_SEALING));
0102     if (!fd.isValid()) {
0103         return nullptr;
0104     }
0105 
0106     if (ftruncate(fd.get(), bufferSize) < 0) {
0107         return nullptr;
0108     }
0109 
0110     fcntl(fd.get(), F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_SEAL);
0111 #else
0112     char templateName[] = "/tmp/kwin-shm-XXXXXX";
0113     FileDescriptor fd{mkstemp(templateName)};
0114     if (!fd.isValid()) {
0115         return nullptr;
0116     }
0117 
0118     unlink(templateName);
0119     int flags = fcntl(fd.get(), F_GETFD);
0120     if (flags == -1 || fcntl(fd.get(), F_SETFD, flags | FD_CLOEXEC) == -1) {
0121         return nullptr;
0122     }
0123 
0124     if (ftruncate(fd.get(), bufferSize) < 0) {
0125         return nullptr;
0126     }
0127 #endif
0128 
0129     ShmAttributes attributes{
0130         .fd = std::move(fd),
0131         .stride = stride,
0132         .offset = 0,
0133         .size = options.size,
0134         .format = options.format,
0135     };
0136 
0137     MemoryMap memoryMap(attributes.stride * attributes.size.height(), PROT_READ | PROT_WRITE, MAP_SHARED, attributes.fd.get(), attributes.offset);
0138     if (!memoryMap.isValid()) {
0139         return nullptr;
0140     }
0141 
0142     return new ShmGraphicsBuffer(std::move(attributes), std::move(memoryMap));
0143 }
0144 
0145 } // namespace KWin
0146 
0147 #include "moc_shmgraphicsbufferallocator.cpp"
0148 #include "shmgraphicsbufferallocator.moc"