File indexing completed on 2024-11-10 04:56:40
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"