File indexing completed on 2025-04-20 10:57:33

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "drm_dumb_buffer.h"
0010 
0011 #include "drm_gpu.h"
0012 #include "drm_logging.h"
0013 
0014 #include <cerrno>
0015 #include <drm_fourcc.h>
0016 #include <sys/mman.h>
0017 #include <xf86drm.h>
0018 
0019 namespace KWin
0020 {
0021 
0022 DrmDumbBuffer::DrmDumbBuffer(DrmGpu *gpu, const QSize &size, uint32_t format, uint32_t handle, uint32_t stride, size_t bufferSize)
0023     : DrmGpuBuffer(gpu, size, format, DRM_FORMAT_MOD_LINEAR, {handle, 0, 0, 0}, {stride, 0, 0, 0}, {0, 0, 0, 0}, 1)
0024     , m_bufferSize(bufferSize)
0025 {
0026 }
0027 
0028 DrmDumbBuffer::~DrmDumbBuffer()
0029 {
0030     m_image.reset();
0031     if (m_memory) {
0032         munmap(m_memory, m_bufferSize);
0033     }
0034     drm_mode_destroy_dumb destroyArgs;
0035     destroyArgs.handle = m_handles[0];
0036     drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs);
0037 }
0038 
0039 bool DrmDumbBuffer::map(QImage::Format format)
0040 {
0041     drm_mode_map_dumb mapArgs;
0042     memset(&mapArgs, 0, sizeof mapArgs);
0043     mapArgs.handle = m_handles[0];
0044     if (drmIoctl(m_gpu->fd(), DRM_IOCTL_MODE_MAP_DUMB, &mapArgs) != 0) {
0045         return false;
0046     }
0047 #ifdef KWIN_UNIT_TEST
0048     m_memory = reinterpret_cast<void *>(mapArgs.offset);
0049 #else
0050     void *address = mmap(nullptr, m_bufferSize, PROT_WRITE, MAP_SHARED, m_gpu->fd(), mapArgs.offset);
0051     if (address == MAP_FAILED) {
0052         return false;
0053     }
0054     m_memory = address;
0055 #endif
0056     m_image = std::make_unique<QImage>((uchar *)m_memory, m_size.width(), m_size.height(), m_strides[0], format);
0057     return !m_image->isNull();
0058 }
0059 
0060 QImage *DrmDumbBuffer::image() const
0061 {
0062     return m_image.get();
0063 }
0064 
0065 void *DrmDumbBuffer::data() const
0066 {
0067     return m_memory;
0068 }
0069 
0070 std::shared_ptr<DrmDumbBuffer> DrmDumbBuffer::createDumbBuffer(DrmGpu *gpu, const QSize &size, uint32_t format)
0071 {
0072     drm_mode_create_dumb createArgs;
0073     memset(&createArgs, 0, sizeof createArgs);
0074     createArgs.bpp = 32;
0075     createArgs.width = size.width();
0076     createArgs.height = size.height();
0077     if (drmIoctl(gpu->fd(), DRM_IOCTL_MODE_CREATE_DUMB, &createArgs) != 0) {
0078         qCWarning(KWIN_DRM) << "DRM_IOCTL_MODE_CREATE_DUMB failed" << strerror(errno);
0079         return nullptr;
0080     }
0081     return std::make_shared<DrmDumbBuffer>(gpu, size, format, createArgs.handle, createArgs.pitch, createArgs.size);
0082 }
0083 
0084 }