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 ®ion) 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