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 }