diff --git a/kcmkwin/kwintabbox/thumbnailitem.cpp b/kcmkwin/kwintabbox/thumbnailitem.cpp index baa8d56cc4..8e226175f3 100644 --- a/kcmkwin/kwintabbox/thumbnailitem.cpp +++ b/kcmkwin/kwintabbox/thumbnailitem.cpp @@ -2,7 +2,7 @@ KWin - the KDE window manager This file is part of the KDE project. -Copyright (C) 2011 Martin Gräßlin +Copyright (C) 2011, 2014 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,11 +26,91 @@ along with this program. If not, see . namespace KWin { + +BrightnessSaturationShader::BrightnessSaturationShader() + : QSGMaterialShader() + , m_id_matrix(0) + , m_id_opacity(0) + , m_id_saturation(0) + , m_id_brightness(0) +{ +} + +const char *BrightnessSaturationShader::vertexShader() const +{ + return + "attribute highp vec4 vertex; \n" + "attribute highp vec2 texCoord; \n" + "uniform highp mat4 u_matrix; \n" + "varying highp vec2 v_coord; \n" + "void main() { \n" + " v_coord = texCoord; \n" + " gl_Position = u_matrix * vertex; \n" + "}"; +} + +const char *BrightnessSaturationShader::fragmentShader() const +{ + return + "uniform sampler2D qt_Texture; \n" + "uniform lowp float u_opacity; \n" + "uniform highp float u_saturation; \n" + "uniform highp float u_brightness; \n" + "varying highp vec2 v_coord; \n" + "void main() { \n" + " lowp vec4 tex = texture2D(qt_Texture, v_coord); \n" + " if (u_saturation != 1.0) { \n" + " tex.rgb = mix(vec3(dot( vec3( 0.30, 0.59, 0.11 ), tex.rgb )), tex.rgb, u_saturation); \n" + " } \n" + " tex.rgb = tex.rgb * u_brightness; \n" + " gl_FragColor = tex * u_opacity; \n" + "}"; +} + +const char* const *BrightnessSaturationShader::attributeNames() const +{ + static char const *const names[] = { "vertex", "texCoord", 0 }; + return names; +} + +void BrightnessSaturationShader::updateState(const QSGMaterialShader::RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) +{ + Q_ASSERT(program()->isLinked()); + if (state.isMatrixDirty()) + program()->setUniformValue(m_id_matrix, state.combinedMatrix()); + if (state.isOpacityDirty()) + program()->setUniformValue(m_id_opacity, state.opacity()); + + auto *tx = static_cast(newMaterial); + auto *oldTx = static_cast(oldMaterial); + QSGTexture *t = tx->texture(); + t->setFiltering(QSGTexture::Linear); + + if (!oldTx || oldTx->texture()->textureId() != t->textureId()) + t->bind(); + else + t->updateBindOptions(); + + program()->setUniformValue(m_id_saturation, static_cast(tx->saturation)); + program()->setUniformValue(m_id_brightness, static_cast(tx->brightness)); +} + +void BrightnessSaturationShader::initialize() +{ + QSGMaterialShader::initialize(); + m_id_matrix = program()->uniformLocation("u_matrix"); + m_id_opacity = program()->uniformLocation("u_opacity"); + m_id_saturation = program()->uniformLocation("u_saturation"); + m_id_brightness = program()->uniformLocation("u_brightness"); +} + WindowThumbnailItem::WindowThumbnailItem(QQuickItem* parent) : QQuickItem(parent) , m_wId(0) , m_image() , m_clipToItem(nullptr) + , m_brightness(1.0) + , m_saturation(1.0) { setFlag(ItemHasContents); } @@ -85,17 +165,55 @@ void WindowThumbnailItem::findImage() QSGNode *WindowThumbnailItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) { Q_UNUSED(updatePaintNodeData) - QSGSimpleTextureNode *node = static_cast(oldNode); + QSGGeometryNode *node = static_cast(oldNode); if (!node) { - node = new QSGSimpleTextureNode(); - node->setFiltering(QSGTexture::Linear); - node->setTexture(window()->createTextureFromImage(m_image)); + node = new QSGGeometryNode(); + auto *material = new BrightnessSaturationMaterial; + material->setFlag(QSGMaterial::Blending); + material->setTexture(window()->createTextureFromImage(m_image)); + node->setMaterial(material); + QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4); + node->setGeometry(geometry); } - const QSize size(node->texture()->textureSize().scaled(boundingRect().size().toSize(), Qt::KeepAspectRatio)); + auto *material = static_cast(node->material()); + const QSize size(material->texture()->textureSize().scaled(boundingRect().size().toSize(), Qt::KeepAspectRatio)); const qreal x = boundingRect().x() + (boundingRect().width() - size.width())/2; const qreal y = boundingRect().y() + (boundingRect().height() - size.height())/2; - node->setRect(QRectF(QPointF(x, y), size)); + QSGGeometry::updateTexturedRectGeometry(node->geometry(), QRectF(QPointF(x, y), size), QRectF(0.0, 0.0, 1.0, 1.0)); + material->brightness = m_brightness; + material->saturation = m_saturation; + node->markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial); return node; } +qreal WindowThumbnailItem::brightness() const +{ + return m_brightness; +} + +qreal WindowThumbnailItem::saturation() const +{ + return m_saturation; +} + +void WindowThumbnailItem::setBrightness(qreal brightness) +{ + if (m_brightness == brightness) { + return; + } + m_brightness = brightness; + update(); + emit brightnessChanged(); +} + +void WindowThumbnailItem::setSaturation(qreal saturation) +{ + if (m_saturation == saturation) { + return; + } + m_saturation = saturation; + update(); + emit saturationChanged(); +} + } // namespace KWin diff --git a/kcmkwin/kwintabbox/thumbnailitem.h b/kcmkwin/kwintabbox/thumbnailitem.h index d5a915ce59..070fe399b0 100644 --- a/kcmkwin/kwintabbox/thumbnailitem.h +++ b/kcmkwin/kwintabbox/thumbnailitem.h @@ -2,7 +2,7 @@ KWin - the KDE window manager This file is part of the KDE project. -Copyright (C) 2011 Martin Gräßlin +Copyright (C) 2011, 2014 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,15 +23,48 @@ along with this program. If not, see . #include #include +#include namespace KWin { +class BrightnessSaturationShader : public QSGMaterialShader +{ +public: + BrightnessSaturationShader(); + virtual const char* vertexShader() const override; + virtual const char* fragmentShader() const override; + virtual const char*const* attributeNames() const override; + virtual void updateState(const RenderState& state, QSGMaterial* newMaterial, QSGMaterial* oldMaterial) override; + virtual void initialize() override; +private: + int m_id_matrix; + int m_id_opacity; + int m_id_saturation; + int m_id_brightness; +}; + +class BrightnessSaturationMaterial : public QSGTextureMaterial +{ +public: + virtual QSGMaterialShader* createShader() const override { + return new BrightnessSaturationShader; + } + QSGMaterialType *type() const override { + static QSGMaterialType type; + return &type; + } + qreal brightness; + qreal saturation; +}; + class WindowThumbnailItem : public QQuickItem { Q_OBJECT Q_PROPERTY(qulonglong wId READ wId WRITE setWId NOTIFY wIdChanged SCRIPTABLE true) Q_PROPERTY(QQuickItem *clipTo READ clipTo WRITE setClipTo NOTIFY clipToChanged) + Q_PROPERTY(qreal brightness READ brightness WRITE setBrightness NOTIFY brightnessChanged) + Q_PROPERTY(qreal saturation READ saturation WRITE setSaturation NOTIFY saturationChanged) public: explicit WindowThumbnailItem(QQuickItem *parent = nullptr); virtual ~WindowThumbnailItem(); @@ -42,8 +75,12 @@ public: QQuickItem *clipTo() const { return m_clipToItem; } + qreal brightness() const; + qreal saturation() const; void setWId(qulonglong wId); void setClipTo(QQuickItem *clip); + void setBrightness(qreal brightness); + void setSaturation(qreal saturation); virtual QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) override; enum Thumbnail { @@ -55,11 +92,15 @@ public: Q_SIGNALS: void wIdChanged(qulonglong wid); void clipToChanged(); + void brightnessChanged(); + void saturationChanged(); private: void findImage(); qulonglong m_wId; QImage m_image; QQuickItem *m_clipToItem; + qreal m_brightness; + qreal m_saturation; }; } // KWin