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 }