File indexing completed on 2024-05-19 16:34:47

0001 /*
0002     SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "scene/surfaceitem.h"
0008 
0009 namespace KWin
0010 {
0011 
0012 SurfaceItem::SurfaceItem(Scene *scene, Item *parent)
0013     : Item(scene, parent)
0014 {
0015 }
0016 
0017 QMatrix4x4 SurfaceItem::surfaceToBufferMatrix() const
0018 {
0019     return m_surfaceToBufferMatrix;
0020 }
0021 
0022 void SurfaceItem::setSurfaceToBufferMatrix(const QMatrix4x4 &matrix)
0023 {
0024     m_surfaceToBufferMatrix = matrix;
0025 }
0026 
0027 void SurfaceItem::addDamage(const QRegion &region)
0028 {
0029     m_damage += region;
0030     scheduleRepaint(region);
0031     Q_EMIT damaged();
0032 }
0033 
0034 void SurfaceItem::resetDamage()
0035 {
0036     m_damage = QRegion();
0037 }
0038 
0039 QRegion SurfaceItem::damage() const
0040 {
0041     return m_damage;
0042 }
0043 
0044 SurfacePixmap *SurfaceItem::pixmap() const
0045 {
0046     if (m_pixmap && m_pixmap->isValid()) {
0047         return m_pixmap.get();
0048     }
0049     if (m_previousPixmap && m_previousPixmap->isValid()) {
0050         return m_previousPixmap.get();
0051     }
0052     return nullptr;
0053 }
0054 
0055 SurfacePixmap *SurfaceItem::previousPixmap() const
0056 {
0057     return m_previousPixmap.get();
0058 }
0059 
0060 void SurfaceItem::referencePreviousPixmap()
0061 {
0062     if (m_previousPixmap && m_previousPixmap->isDiscarded()) {
0063         m_referencePixmapCounter++;
0064     }
0065 }
0066 
0067 void SurfaceItem::unreferencePreviousPixmap()
0068 {
0069     if (!m_previousPixmap || !m_previousPixmap->isDiscarded()) {
0070         return;
0071     }
0072     m_referencePixmapCounter--;
0073     if (m_referencePixmapCounter == 0) {
0074         m_previousPixmap.reset();
0075     }
0076 }
0077 
0078 void SurfaceItem::updatePixmap()
0079 {
0080     if (!m_pixmap) {
0081         m_pixmap = createPixmap();
0082     }
0083     if (m_pixmap->isValid()) {
0084         m_pixmap->update();
0085     } else {
0086         m_pixmap->create();
0087         if (m_pixmap->isValid()) {
0088             unreferencePreviousPixmap();
0089             discardQuads();
0090         }
0091     }
0092 }
0093 
0094 void SurfaceItem::discardPixmap()
0095 {
0096     if (m_pixmap) {
0097         if (m_pixmap->isValid()) {
0098             m_previousPixmap = std::move(m_pixmap);
0099             m_previousPixmap->markAsDiscarded();
0100             referencePreviousPixmap();
0101         } else {
0102             m_pixmap.reset();
0103         }
0104     }
0105 }
0106 
0107 void SurfaceItem::destroyPixmap()
0108 {
0109     m_pixmap.reset();
0110 }
0111 
0112 void SurfaceItem::preprocess()
0113 {
0114     updatePixmap();
0115 }
0116 
0117 WindowQuadList SurfaceItem::buildQuads() const
0118 {
0119     if (!pixmap()) {
0120         return {};
0121     }
0122 
0123     const QVector<QRectF> region = shape();
0124     const auto size = pixmap()->size();
0125 
0126     WindowQuadList quads;
0127     quads.reserve(region.count());
0128 
0129     for (const QRectF rect : region) {
0130         WindowQuad quad;
0131 
0132         // Use toPoint to round the device position to match what we eventually
0133         // do for the geometry, otherwise we end up with mismatched UV
0134         // coordinates as the texture size is going to be in (rounded) device
0135         // coordinates as well.
0136         const QPointF bufferTopLeft = m_surfaceToBufferMatrix.map(rect.topLeft()).toPoint();
0137         const QPointF bufferTopRight = m_surfaceToBufferMatrix.map(rect.topRight()).toPoint();
0138         const QPointF bufferBottomRight = m_surfaceToBufferMatrix.map(rect.bottomRight()).toPoint();
0139         const QPointF bufferBottomLeft = m_surfaceToBufferMatrix.map(rect.bottomLeft()).toPoint();
0140 
0141         quad[0] = WindowVertex(rect.topLeft(), QPointF{bufferTopLeft.x() / size.width(), bufferTopLeft.y() / size.height()});
0142         quad[1] = WindowVertex(rect.topRight(), QPointF{bufferTopRight.x() / size.width(), bufferTopRight.y() / size.height()});
0143         quad[2] = WindowVertex(rect.bottomRight(), QPointF{bufferBottomRight.x() / size.width(), bufferBottomRight.y() / size.height()});
0144         quad[3] = WindowVertex(rect.bottomLeft(), QPointF{bufferBottomLeft.x() / size.width(), bufferBottomLeft.y() / size.height()});
0145 
0146         quads << quad;
0147     }
0148 
0149     return quads;
0150 }
0151 
0152 ContentType SurfaceItem::contentType() const
0153 {
0154     return ContentType::None;
0155 }
0156 
0157 SurfaceTexture::~SurfaceTexture()
0158 {
0159 }
0160 
0161 SurfacePixmap::SurfacePixmap(std::unique_ptr<SurfaceTexture> &&texture, QObject *parent)
0162     : QObject(parent)
0163     , m_texture(std::move(texture))
0164 {
0165 }
0166 
0167 void SurfacePixmap::update()
0168 {
0169 }
0170 
0171 SurfaceTexture *SurfacePixmap::texture() const
0172 {
0173     return m_texture.get();
0174 }
0175 
0176 bool SurfacePixmap::hasAlphaChannel() const
0177 {
0178     return m_hasAlphaChannel;
0179 }
0180 
0181 QSize SurfacePixmap::size() const
0182 {
0183     return m_size;
0184 }
0185 
0186 bool SurfacePixmap::isDiscarded() const
0187 {
0188     return m_isDiscarded;
0189 }
0190 
0191 void SurfacePixmap::markAsDiscarded()
0192 {
0193     m_isDiscarded = true;
0194 }
0195 
0196 } // namespace KWin