File indexing completed on 2024-11-10 04:57:05
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: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 #include "backingstore.h" 0011 #include "core/graphicsbuffer.h" 0012 #include "core/graphicsbufferview.h" 0013 #include "internalwindow.h" 0014 #include "logging.h" 0015 #include "swapchain.h" 0016 #include "window.h" 0017 0018 #include <QPainter> 0019 #include <libdrm/drm_fourcc.h> 0020 0021 namespace KWin 0022 { 0023 namespace QPA 0024 { 0025 0026 BackingStore::BackingStore(QWindow *window) 0027 : QPlatformBackingStore(window) 0028 { 0029 } 0030 0031 QPaintDevice *BackingStore::paintDevice() 0032 { 0033 return m_bufferView->image(); 0034 } 0035 0036 void BackingStore::resize(const QSize &size, const QRegion &staticContents) 0037 { 0038 QPlatformWindow *platformWindow = static_cast<QPlatformWindow *>(window()->handle()); 0039 platformWindow->invalidateSurface(); 0040 } 0041 0042 void BackingStore::beginPaint(const QRegion ®ion) 0043 { 0044 Window *platformWindow = static_cast<Window *>(window()->handle()); 0045 Swapchain *swapchain = platformWindow->swapchain({{DRM_FORMAT_ARGB8888, {DRM_FORMAT_MOD_LINEAR}}}); 0046 if (!swapchain) { 0047 qCCritical(KWIN_QPA, "Failed to ceate a swapchain for the backing store!"); 0048 return; 0049 } 0050 0051 const auto oldBuffer = m_buffer; 0052 m_buffer = swapchain->acquire(); 0053 if (!m_buffer) { 0054 qCCritical(KWIN_QPA, "Failed to acquire a graphics buffer for the backing store"); 0055 return; 0056 } 0057 0058 m_bufferView = std::make_unique<GraphicsBufferView>(m_buffer, GraphicsBuffer::Read | GraphicsBuffer::Write); 0059 if (m_bufferView->isNull()) { 0060 qCCritical(KWIN_QPA) << "Failed to map a graphics buffer for the backing store"; 0061 return; 0062 } 0063 0064 if (oldBuffer && oldBuffer != m_buffer && oldBuffer->size() == m_buffer->size()) { 0065 const GraphicsBufferView oldView(oldBuffer, GraphicsBuffer::Read); 0066 std::memcpy(m_bufferView->image()->bits(), oldView.image()->constBits(), oldView.image()->sizeInBytes()); 0067 } 0068 0069 QImage *image = m_bufferView->image(); 0070 image->setDevicePixelRatio(platformWindow->devicePixelRatio()); 0071 0072 if (image->hasAlphaChannel()) { 0073 QPainter p(image); 0074 p.setCompositionMode(QPainter::CompositionMode_Source); 0075 const QColor blank = Qt::transparent; 0076 for (const QRect &rect : region) { 0077 p.fillRect(rect, blank); 0078 } 0079 } 0080 } 0081 0082 void BackingStore::endPaint() 0083 { 0084 m_bufferView.reset(); 0085 } 0086 0087 void BackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) 0088 { 0089 Window *platformWindow = static_cast<Window *>(window->handle()); 0090 InternalWindow *internalWindow = platformWindow->internalWindow(); 0091 if (!internalWindow) { 0092 return; 0093 } 0094 0095 const qreal scale = platformWindow->devicePixelRatio(); 0096 QRegion bufferDamage; 0097 for (const QRect &rect : region) { 0098 bufferDamage += QRectF(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale).toAlignedRect(); 0099 } 0100 0101 internalWindow->present(InternalWindowFrame{ 0102 .buffer = m_buffer, 0103 .bufferDamage = bufferDamage, 0104 }); 0105 } 0106 0107 } 0108 }