File indexing completed on 2024-05-19 16:34:46
0001 /* 0002 SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "scene/itemrenderer_qpainter.h" 0008 #include "platformsupport/scenes/qpainter/qpaintersurfacetexture.h" 0009 #include "scene/imageitem.h" 0010 #include "scene/workspacescene_qpainter.h" 0011 0012 #include <QPainter> 0013 0014 namespace KWin 0015 { 0016 0017 ItemRendererQPainter::ItemRendererQPainter() 0018 : m_painter(std::make_unique<QPainter>()) 0019 { 0020 } 0021 0022 ItemRendererQPainter::~ItemRendererQPainter() 0023 { 0024 } 0025 0026 ImageItem *ItemRendererQPainter::createImageItem(Scene *scene, Item *parent) 0027 { 0028 return new ImageItem(scene, parent); 0029 } 0030 0031 QPainter *ItemRendererQPainter::painter() const 0032 { 0033 return m_painter.get(); 0034 } 0035 0036 void ItemRendererQPainter::beginFrame(RenderTarget *renderTarget) 0037 { 0038 QImage *buffer = std::get<QImage *>(renderTarget->nativeHandle()); 0039 m_painter->begin(buffer); 0040 m_painter->setWindow(renderTargetRect()); 0041 } 0042 0043 void ItemRendererQPainter::endFrame() 0044 { 0045 m_painter->end(); 0046 } 0047 0048 void ItemRendererQPainter::renderBackground(const QRegion ®ion) 0049 { 0050 m_painter->setCompositionMode(QPainter::CompositionMode_Source); 0051 for (const QRect &rect : region) { 0052 m_painter->fillRect(rect, Qt::transparent); 0053 } 0054 m_painter->setCompositionMode(QPainter::CompositionMode_SourceOver); 0055 } 0056 0057 void ItemRendererQPainter::renderItem(Item *item, int mask, const QRegion &_region, const WindowPaintData &data) 0058 { 0059 QRegion region = _region; 0060 0061 const QRect boundingRect = item->mapToGlobal(item->boundingRect()).toAlignedRect(); 0062 if (!(mask & (Scene::PAINT_WINDOW_TRANSFORMED | Scene::PAINT_SCREEN_TRANSFORMED))) { 0063 region &= boundingRect; 0064 } 0065 0066 if (region.isEmpty()) { 0067 return; 0068 } 0069 0070 m_painter->save(); 0071 m_painter->setClipRegion(region); 0072 m_painter->setClipping(true); 0073 m_painter->setOpacity(data.opacity()); 0074 0075 if (mask & Scene::PAINT_WINDOW_TRANSFORMED) { 0076 m_painter->translate(data.xTranslation(), data.yTranslation()); 0077 m_painter->scale(data.xScale(), data.yScale()); 0078 } 0079 0080 renderItem(m_painter.get(), item); 0081 0082 m_painter->restore(); 0083 } 0084 0085 void ItemRendererQPainter::renderItem(QPainter *painter, Item *item) const 0086 { 0087 const QList<Item *> sortedChildItems = item->sortedChildItems(); 0088 0089 painter->save(); 0090 painter->translate(item->position()); 0091 painter->setOpacity(painter->opacity() * item->opacity()); 0092 0093 for (Item *childItem : sortedChildItems) { 0094 if (childItem->z() >= 0) { 0095 break; 0096 } 0097 if (childItem->explicitVisible()) { 0098 renderItem(painter, childItem); 0099 } 0100 } 0101 0102 item->preprocess(); 0103 if (auto surfaceItem = qobject_cast<SurfaceItem *>(item)) { 0104 renderSurfaceItem(painter, surfaceItem); 0105 } else if (auto decorationItem = qobject_cast<DecorationItem *>(item)) { 0106 renderDecorationItem(painter, decorationItem); 0107 } else if (auto imageItem = qobject_cast<ImageItem *>(item)) { 0108 renderImageItem(painter, imageItem); 0109 } 0110 0111 for (Item *childItem : sortedChildItems) { 0112 if (childItem->z() < 0) { 0113 continue; 0114 } 0115 if (childItem->explicitVisible()) { 0116 renderItem(painter, childItem); 0117 } 0118 } 0119 0120 painter->restore(); 0121 } 0122 0123 void ItemRendererQPainter::renderSurfaceItem(QPainter *painter, SurfaceItem *surfaceItem) const 0124 { 0125 const SurfacePixmap *surfaceTexture = surfaceItem->pixmap(); 0126 if (!surfaceTexture || !surfaceTexture->isValid()) { 0127 return; 0128 } 0129 0130 QPainterSurfaceTexture *platformSurfaceTexture = 0131 static_cast<QPainterSurfaceTexture *>(surfaceTexture->texture()); 0132 if (!platformSurfaceTexture->isValid()) { 0133 platformSurfaceTexture->create(); 0134 } else { 0135 platformSurfaceTexture->update(surfaceItem->damage()); 0136 } 0137 surfaceItem->resetDamage(); 0138 0139 const QVector<QRectF> shape = surfaceItem->shape(); 0140 for (const QRectF rect : shape) { 0141 const QMatrix4x4 matrix = surfaceItem->surfaceToBufferMatrix(); 0142 const QPointF bufferTopLeft = matrix.map(rect.topLeft()); 0143 const QPointF bufferBottomRight = matrix.map(rect.bottomRight()); 0144 0145 painter->drawImage(rect, platformSurfaceTexture->image(), 0146 QRectF(bufferTopLeft, bufferBottomRight)); 0147 } 0148 } 0149 0150 void ItemRendererQPainter::renderDecorationItem(QPainter *painter, DecorationItem *decorationItem) const 0151 { 0152 const auto renderer = static_cast<const SceneQPainterDecorationRenderer *>(decorationItem->renderer()); 0153 QRectF dtr, dlr, drr, dbr; 0154 decorationItem->window()->layoutDecorationRects(dlr, dtr, drr, dbr); 0155 0156 painter->drawImage(dtr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Top)); 0157 painter->drawImage(dlr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Left)); 0158 painter->drawImage(drr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Right)); 0159 painter->drawImage(dbr, renderer->image(SceneQPainterDecorationRenderer::DecorationPart::Bottom)); 0160 } 0161 0162 void ItemRendererQPainter::renderImageItem(QPainter *painter, ImageItem *imageItem) const 0163 { 0164 painter->drawImage(imageItem->rect(), imageItem->image()); 0165 } 0166 0167 } // namespace KWin