File indexing completed on 2025-04-20 10:57:32
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org> 0006 SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 #include "drm_buffer.h" 0011 0012 #include "drm_gpu.h" 0013 #include "drm_logging.h" 0014 0015 // system 0016 #include <sys/mman.h> 0017 // c++ 0018 #include <cerrno> 0019 // drm 0020 #include <drm_fourcc.h> 0021 #include <unistd.h> 0022 #include <xf86drm.h> 0023 #include <xf86drmMode.h> 0024 0025 namespace KWin 0026 { 0027 0028 DrmGpuBuffer::DrmGpuBuffer(DrmGpu *gpu, QSize size, uint32_t format, uint64_t modifier, const std::array<uint32_t, 4> &handles, const std::array<uint32_t, 4> &strides, const std::array<uint32_t, 4> &offsets, uint32_t planeCount) 0029 : m_gpu(gpu) 0030 , m_size(size) 0031 , m_format(format) 0032 , m_modifier(modifier) 0033 , m_handles(handles) 0034 , m_strides(strides) 0035 , m_offsets(offsets) 0036 , m_planeCount(planeCount) 0037 { 0038 } 0039 0040 DrmGpu *DrmGpuBuffer::gpu() const 0041 { 0042 return m_gpu; 0043 } 0044 0045 uint32_t DrmGpuBuffer::format() const 0046 { 0047 return m_format; 0048 } 0049 0050 uint64_t DrmGpuBuffer::modifier() const 0051 { 0052 return m_modifier; 0053 } 0054 0055 QSize DrmGpuBuffer::size() const 0056 { 0057 return m_size; 0058 } 0059 0060 const std::array<FileDescriptor, 4> &DrmGpuBuffer::fds() 0061 { 0062 if (!m_fds[0].isValid()) { 0063 createFds(); 0064 } 0065 return m_fds; 0066 } 0067 0068 std::array<uint32_t, 4> DrmGpuBuffer::handles() const 0069 { 0070 return m_handles; 0071 } 0072 0073 std::array<uint32_t, 4> DrmGpuBuffer::strides() const 0074 { 0075 return m_strides; 0076 } 0077 0078 std::array<uint32_t, 4> DrmGpuBuffer::offsets() const 0079 { 0080 return m_offsets; 0081 } 0082 0083 uint32_t DrmGpuBuffer::planeCount() const 0084 { 0085 return m_planeCount; 0086 } 0087 0088 void DrmGpuBuffer::createFds() 0089 { 0090 } 0091 0092 DrmFramebuffer::DrmFramebuffer(const std::shared_ptr<DrmGpuBuffer> &buffer, uint32_t fbId) 0093 : m_framebufferId(fbId) 0094 , m_gpu(buffer->gpu()) 0095 , m_buffer(buffer) 0096 { 0097 } 0098 0099 DrmFramebuffer::~DrmFramebuffer() 0100 { 0101 drmModeRmFB(m_gpu->fd(), m_framebufferId); 0102 } 0103 0104 uint32_t DrmFramebuffer::framebufferId() const 0105 { 0106 return m_framebufferId; 0107 } 0108 0109 DrmGpuBuffer *DrmFramebuffer::buffer() const 0110 { 0111 return m_buffer.get(); 0112 } 0113 0114 void DrmFramebuffer::releaseBuffer() 0115 { 0116 m_buffer.reset(); 0117 } 0118 0119 std::shared_ptr<DrmFramebuffer> DrmFramebuffer::createFramebuffer(const std::shared_ptr<DrmGpuBuffer> &buffer) 0120 { 0121 const auto size = buffer->size(); 0122 const auto handles = buffer->handles(); 0123 const auto strides = buffer->strides(); 0124 const auto offsets = buffer->offsets(); 0125 0126 uint32_t framebufferId = 0; 0127 int ret; 0128 if (buffer->gpu()->addFB2ModifiersSupported() && buffer->modifier() != DRM_FORMAT_MOD_INVALID) { 0129 uint64_t modifier[4]; 0130 for (uint32_t i = 0; i < 4; i++) { 0131 modifier[i] = i < buffer->planeCount() ? buffer->modifier() : 0; 0132 } 0133 ret = drmModeAddFB2WithModifiers(buffer->gpu()->fd(), size.width(), size.height(), buffer->format(), handles.data(), strides.data(), offsets.data(), modifier, &framebufferId, DRM_MODE_FB_MODIFIERS); 0134 } else { 0135 ret = drmModeAddFB2(buffer->gpu()->fd(), size.width(), size.height(), buffer->format(), handles.data(), strides.data(), offsets.data(), &framebufferId, 0); 0136 if (ret == EOPNOTSUPP && handles.size() == 1) { 0137 ret = drmModeAddFB(buffer->gpu()->fd(), size.width(), size.height(), 24, 32, strides[0], handles[0], &framebufferId); 0138 } 0139 } 0140 if (ret == 0) { 0141 return std::make_shared<DrmFramebuffer>(buffer, framebufferId); 0142 } else { 0143 return nullptr; 0144 } 0145 } 0146 }