From d8e61a46d02dfbbb6c07f1d072591b3ac6d10682 Mon Sep 17 00:00:00 2001 From: Matin Lotfaliei Date: Fri, 22 Jul 2022 13:10:22 -0700 Subject: [PATCH 1/3] Render once instead of 5 times --- .github/workflows/glslangValidator.yml | 36 +++++ CMakeLists.txt | 4 +- ConfigModel.cpp | 42 ++++++ ConfigModel.h | 23 ++++ ShaderManager.cpp | 74 ++++++++++ ShaderManager.h | 37 +++++ dbus.h | 13 +- shaders_110/shapecorners.frag | 60 ++++++--- shaders_140/shapecorners.frag | 58 +++++--- shapecorners.cpp | 178 +++++-------------------- shapecorners.h | 20 +-- shapecorners_config.cpp | 64 ++++----- shapecorners_config.h | 2 + 13 files changed, 366 insertions(+), 245 deletions(-) create mode 100644 .github/workflows/glslangValidator.yml create mode 100644 ConfigModel.cpp create mode 100644 ConfigModel.h create mode 100644 ShaderManager.cpp create mode 100644 ShaderManager.h diff --git a/.github/workflows/glslangValidator.yml b/.github/workflows/glslangValidator.yml new file mode 100644 index 0000000..54dcdae --- /dev/null +++ b/.github/workflows/glslangValidator.yml @@ -0,0 +1,36 @@ +name: GLSL Validator + +on: + push: + branches: [ master, latest-shapecorners-code, kwin_5.23 ] + pull_request: + branches: [ master ] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + ubuntu2004: + # The CMake configure and build commands are platform agnostic and should work equally + # well on Windows or Mac. You can convert this to a matrix build if you need + # cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v3 + + - name: Run github-actions-tune + uses: abbbi/github-actions-tune@v1 + + - name: Install Dependencies + uses: awalsh128/cache-apt-pkgs-action@staging + with: + packages: glslang-tools + version: 123.0 + refresh: true + + - name: Validate Shaders + run: glslangValidator shaders_110/shapecorners.frag shaders_140/shapecorners.frag diff --git a/CMakeLists.txt b/CMakeLists.txt index a633a22..da5706c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ if (NOT EFFECTS_H OR NOT KWIN_GLUTILS OR NOT KWIN_EFFECTS OR NOT OPENGL) message(FATAL_ERROR "cant continue") endif (NOT EFFECTS_H OR NOT KWIN_GLUTILS OR NOT KWIN_EFFECTS OR NOT OPENGL) -add_library(${SHAPECORNERS} MODULE shapecorners.cpp main.cpp dbus.h shapecorners.h) +add_library(${SHAPECORNERS} MODULE shapecorners.cpp main.cpp dbus.h shapecorners.h ShaderManager.cpp ShaderManager.h ConfigModel.h ConfigModel.cpp) target_link_libraries(${SHAPECORNERS} PUBLIC @@ -115,7 +115,7 @@ install(FILES shaders_110/shapecorners.frag DESTINATION ${DATAPATH}/kwin/shaders #config project(kwin4_shapecorners_config) -set(kwin4_shapecorners_config_SOURCES shapecorners_config.cpp shapecorners_config.h) +set(kwin4_shapecorners_config_SOURCES shapecorners_config.cpp shapecorners_config.h ConfigModel.cpp) ki18n_wrap_ui(kwin4_shapecorners_config_SOURCES shapecorners_config.ui) qt5_add_dbus_interface(kwin4_shapecorners_config_SOURCES org.kde.kwin.Effects.xml kwineffects_interface) add_library(kwin4_shapecorners_config MODULE ${kwin4_shapecorners_config_SOURCES}) diff --git a/ConfigModel.cpp b/ConfigModel.cpp new file mode 100644 index 0000000..99397ba --- /dev/null +++ b/ConfigModel.cpp @@ -0,0 +1,42 @@ +// +// Created by matin on 20/07/22. +// + +#include +#include +#include "ConfigModel.h" + +const QString + key_size = "roundness", + key_dsp = "dsp", + key_shadowColor = "shadowColor", + key_outlineColor = "outlineColor", + key_outlineThickness = "outlineThickness"; + +ConfigModel::ConfigModel(): + m_size(10), + m_outlineThickness(1), + m_shadowColor(QColor(Qt::black)), + m_outlineColor(QColor(Qt::black)), + m_dsp(false) +{ +} + +void ConfigModel::Load() { + KConfigGroup conf = KSharedConfig::openConfig("shapecorners.conf")->group("General"); + m_size = conf.readEntry(key_size, m_size); + m_shadowColor = conf.readEntry(key_shadowColor, m_shadowColor); + m_outlineColor = conf.readEntry(key_outlineColor, m_outlineColor); + m_outlineThickness = conf.readEntry(key_outlineThickness, m_outlineThickness); + m_dsp = conf.readEntry(key_dsp, m_dsp); +} + +void ConfigModel::Save() const { + KConfigGroup conf = KSharedConfig::openConfig("shapecorners.conf")->group("General"); + conf.writeEntry(key_size, m_size); + conf.writeEntry(key_dsp, m_dsp); + conf.writeEntry(key_shadowColor, m_shadowColor); + conf.writeEntry(key_outlineColor, m_outlineColor); + conf.writeEntry(key_outlineThickness, m_outlineThickness); + conf.sync(); +} diff --git a/ConfigModel.h b/ConfigModel.h new file mode 100644 index 0000000..9dfee29 --- /dev/null +++ b/ConfigModel.h @@ -0,0 +1,23 @@ +// +// Created by matin on 20/07/22. +// + +#ifndef KWIN4_SHAPECORNERS_CONFIG_CONFIGMODEL_H +#define KWIN4_SHAPECORNERS_CONFIG_CONFIGMODEL_H + +#include + +class ConfigModel { +public: + ConfigModel(); + void Load(); + void Save() const; + + float m_size, + m_outlineThickness; + QColor m_shadowColor, + m_outlineColor; + bool m_dsp; +}; + +#endif //KWIN4_SHAPECORNERS_CONFIG_CONFIGMODEL_H diff --git a/ShaderManager.cpp b/ShaderManager.cpp new file mode 100644 index 0000000..47e0d06 --- /dev/null +++ b/ShaderManager.cpp @@ -0,0 +1,74 @@ +// +// Created by matin on 20/07/22. +// + +#include +#include +#include +#include +#include "ShaderManager.h" + +ShaderManager::ShaderManager(): + m_manager(KWin::ShaderManager::instance()) +{ + QString shadersDir(QStringLiteral("kwin/shaders/1.10/")); +#ifdef KWIN_HAVE_OPENGLES + const qint64 coreVersionNumber = kVersionNumber(3, 0); +#else + const qint64 version = KWin::kVersionNumber(1, 40); +#endif + if (KWin::GLPlatform::instance()->glslVersion() >= version) + shadersDir = QStringLiteral("kwin/shaders/1.40/"); + + const QString fragmentshader = QStandardPaths::locate(QStandardPaths::GenericDataLocation, shadersDir + QStringLiteral("shapecorners.frag")); +// m_shader = KWin::ShaderManager::instance()->loadFragmentShader(KWin::ShaderManager::GenericShader, fragmentshader); + QFile file(fragmentshader); + if (file.open(QFile::ReadOnly)) + { + QByteArray frag = file.readAll(); + auto shader = m_manager->generateCustomShader(KWin::ShaderTrait::MapTexture, QByteArray(), frag); +#if KWIN_EFFECT_API_VERSION >= 235 + m_shader = std::move(shader); +#else + m_shader.reset(shader); +#endif + file.close(); +// qDebug() << frag; +// qDebug() << "shader valid: " << m_shader->isValid(); + if (m_shader->isValid()) + { + m_shader_windowSize = m_shader->uniformLocation("windowSize"); + m_shader_windowActive = m_shader->uniformLocation("windowActive"); + m_shader_shadowColor = m_shader->uniformLocation("shadowColor"); + m_shader_radius = m_shader->uniformLocation("radius"); + m_shader_outlineColor = m_shader->uniformLocation("outlineColor"); + m_shader_outlineThickness = m_shader->uniformLocation("outlineThickness"); + } + else + qDebug() << "ShapeCorners: no valid shaders found! ShapeCorners will not work."; + } + else + { + qDebug() << "ShapeCorners: no shaders found! Exiting..."; + } +} + +bool ShaderManager::IsValid() const { + return m_shader && m_shader->isValid(); +} + +void ShaderManager::Bind(QMatrix4x4 mvp, const QRect& geo, bool windowActive, const ConfigModel& config) const { + m_manager->pushShader(m_shader.get()); + mvp.translate((float)geo.x(), (float)geo.y()); + m_shader->setUniform(KWin::GLShader::ModelViewProjectionMatrix, mvp); + m_shader->setUniform(m_shader_windowSize, QVector2D{(float)geo.width(), (float)geo.height()}); + m_shader->setUniform(m_shader_windowActive, windowActive); + m_shader->setUniform(m_shader_shadowColor, config.m_shadowColor); + m_shader->setUniform(m_shader_radius, config.m_size); + m_shader->setUniform(m_shader_outlineColor, config.m_outlineColor); + m_shader->setUniform(m_shader_outlineThickness, config.m_outlineThickness); +} + +void ShaderManager::Unbind() const { + m_manager->popShader(); +} diff --git a/ShaderManager.h b/ShaderManager.h new file mode 100644 index 0000000..3bbb88a --- /dev/null +++ b/ShaderManager.h @@ -0,0 +1,37 @@ +// +// Created by matin on 20/07/22. +// + +#ifndef KWIN4_SHAPECORNERS_CONFIG_SHADERMANAGER_H +#define KWIN4_SHAPECORNERS_CONFIG_SHADERMANAGER_H + +#include +#include +#include "ConfigModel.h" + +namespace KWin { + class GLShader; + class ShaderManager; +} + +class ShaderManager { +public: + ShaderManager(); + + bool IsValid() const; + void Bind(QMatrix4x4 mvp, const QRect& geo, bool windowActive, const ConfigModel& config) const; + void Unbind() const; + +private: + std::unique_ptr m_shader; + KWin::ShaderManager* m_manager; + int m_shader_windowSize = 0; + int m_shader_windowActive = 0; + int m_shader_shadowColor = 0; + int m_shader_radius = 0; + int m_shader_outlineColor = 0; + int m_shader_outlineThickness = 0; +}; + + +#endif //KWIN4_SHAPECORNERS_CONFIG_SHADERMANAGER_H diff --git a/dbus.h b/dbus.h index 949be72..cf8fc6e 100644 --- a/dbus.h +++ b/dbus.h @@ -3,7 +3,6 @@ #include #include "shapecorners.h" -#include namespace KWin { @@ -21,12 +20,12 @@ class EffectAdaptor : public QDBusAbstractAdaptor public slots: Q_NOREPLY void setRoundness(int r) { - KConfigGroup conf = KSharedConfig::openConfig("shapecorners.conf")->group("General"); - if (conf.readEntry("dsp", false)) - { - conf.writeEntry("roundness", r); - conf.sync(); - m_effect->setRoundness(r); + ConfigModel config; + config.Load(); + if(config.m_dsp) { + config.m_size = r; + config.Save(); + m_effect->setConfig(config); } } Q_NOREPLY void configure() { m_effect->reconfigure(KWin::Effect::ReconfigureAll); } diff --git a/shaders_110/shapecorners.frag b/shaders_110/shapecorners.frag index 40ce02a..3ddbd91 100644 --- a/shaders_110/shapecorners.frag +++ b/shaders_110/shapecorners.frag @@ -1,8 +1,8 @@ #version 110 uniform sampler2D sampler; -uniform int radius; -uniform int cornerIndex; +uniform float radius; +uniform vec2 windowSize; uniform bool windowActive; uniform vec4 shadowColor; uniform vec4 outlineColor; @@ -16,33 +16,34 @@ vec4 goTowards(vec4 fromColor, vec4 toColor, float percent) { } vec4 shadowCorner(float distance_from_center, vec4 backColor, bool isTopCorner) { + float r2 = radius * sqrt(2.0); if (windowActive) { if (isTopCorner) { - float percent = (distance_from_center + 0.15) / (sqrt(2.0)+0.2); + float percent = (distance_from_center + 0.15*radius) / (r2+0.2*radius); return goTowards(shadowColor, backColor, percent); } else { - float percent = (distance_from_center - 0.25) / (sqrt(2.0)+0.1); + float percent = (distance_from_center - 0.25*radius) / (r2+0.1*radius); return goTowards(shadowColor, backColor, percent); } } else { if (isTopCorner) { - float percent = (distance_from_center + 0.55) / (sqrt(2.0)+0.5); + float percent = (distance_from_center + 0.55*radius) / (r2+0.5*radius); return goTowards(shadowColor, backColor, percent); } else { - float percent = (distance_from_center) / (sqrt(2.0)+0.1); + float percent = (distance_from_center) / (r2+0.1*radius); return goTowards(shadowColor, backColor, percent); } } } -vec4 shapeCorner(vec2 texcoord0, vec4 backColor, vec2 center, bool isTopCorner) { - float distance_from_center = distance(texcoord0, center); - if(distance_from_center < (1.0 - outlineThickness/float(radius))) +vec4 shapeCorner(vec2 coord0, vec4 backColor, vec2 center, bool isTopCorner) { + float distance_from_center = distance(coord0, center); + if(distance_from_center < radius - outlineThickness) backColor.a = 0.0; - else if(distance_from_center < 1.0) + else if(distance_from_center < radius) backColor = outlineColor; else { if(shadowColor.a > 0.0) @@ -53,16 +54,37 @@ vec4 shapeCorner(vec2 texcoord0, vec4 backColor, vec2 center, bool isTopCorner) return backColor; } -void main() +void main(void) { vec4 tex = texture2D(sampler, texcoord0); - if(cornerIndex == 0) - tex = shapeCorner(texcoord0, tex, vec2(1, 0), true); - else if(cornerIndex == 1) - tex = shapeCorner(texcoord0, tex, vec2(0, 0), true); - else if(cornerIndex == 2) - tex = shapeCorner(texcoord0, tex, vec2(0, 1), false); - else if(cornerIndex == 3) - tex = shapeCorner(texcoord0, tex, vec2(1, 1), false); + vec2 coord0 = vec2(texcoord0.x*windowSize.x, texcoord0.y*windowSize.y); + if(coord0.x < radius) { + if(coord0.y < radius) + tex = shapeCorner(coord0, tex, vec2(radius, radius), false); + else if (coord0.y > windowSize.y - radius) + tex = shapeCorner(coord0, tex, vec2(radius, windowSize.y - radius), true); + else if (coord0.x < outlineThickness) + tex = outlineColor; + else + tex.a = 0.0; + } + else if(coord0.x > windowSize.x - radius) { + if(coord0.y < radius) + tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius, radius), false); + else if (coord0.y > windowSize.y - radius) + tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius, windowSize.y - radius), true); + else if (coord0.x > windowSize.x - outlineThickness) + tex = outlineColor; + else + tex.a = 0.0; + } + else { + if (coord0.y < outlineThickness) + tex = outlineColor; + else if (coord0.y > windowSize.y - outlineThickness) + tex = outlineColor; + else + tex.a = 0.0; + } gl_FragColor = tex; } diff --git a/shaders_140/shapecorners.frag b/shaders_140/shapecorners.frag index 7b89983..acc67c8 100644 --- a/shaders_140/shapecorners.frag +++ b/shaders_140/shapecorners.frag @@ -1,8 +1,8 @@ #version 140 uniform sampler2D sampler; -uniform int radius; -uniform int cornerIndex; +uniform float radius; +uniform vec2 windowSize; uniform bool windowActive; uniform vec4 shadowColor; uniform vec4 outlineColor; @@ -17,33 +17,34 @@ vec4 goTowards(vec4 fromColor, vec4 toColor, float percent) { } vec4 shadowCorner(float distance_from_center, vec4 backColor, bool isTopCorner) { + float r2 = radius * sqrt(2); if (windowActive) { if (isTopCorner) { - float percent = (distance_from_center + 0.15) / (sqrt(2)+0.2); + float percent = (distance_from_center + 0.15*radius) / (r2+0.2*radius); return goTowards(shadowColor, backColor, percent); } else { - float percent = (distance_from_center - 0.25) / (sqrt(2)+0.1); + float percent = (distance_from_center - 0.25*radius) / (r2+0.1*radius); return goTowards(shadowColor, backColor, percent); } } else { if (isTopCorner) { - float percent = (distance_from_center + 0.55) / (sqrt(2)+0.5); + float percent = (distance_from_center + 0.55*radius) / (r2+0.5*radius); return goTowards(shadowColor, backColor, percent); } else { - float percent = (distance_from_center) / (sqrt(2)+0.1); + float percent = (distance_from_center) / (r2+0.1*radius); return goTowards(shadowColor, backColor, percent); } } } -vec4 shapeCorner(vec2 texcoord0, vec4 backColor, vec2 center, bool isTopCorner) { - float distance_from_center = distance(texcoord0, center); - if(distance_from_center < 1 - outlineThickness/radius) +vec4 shapeCorner(vec2 coord0, vec4 backColor, vec2 center, bool isTopCorner) { + float distance_from_center = distance(coord0, center); + if(distance_from_center < radius - outlineThickness) backColor.a = 0; - else if(distance_from_center < 1) + else if(distance_from_center < radius) backColor = outlineColor; else { if(shadowColor.a > 0) @@ -57,13 +58,34 @@ vec4 shapeCorner(vec2 texcoord0, vec4 backColor, vec2 center, bool isTopCorner) void main(void) { vec4 tex = texture(sampler, texcoord0); - if(cornerIndex == 0) - tex = shapeCorner(texcoord0, tex, vec2(1, 0), true); - else if(cornerIndex == 1) - tex = shapeCorner(texcoord0, tex, vec2(0, 0), true); - else if(cornerIndex == 2) - tex = shapeCorner(texcoord0, tex, vec2(0, 1), false); - else if(cornerIndex == 3) - tex = shapeCorner(texcoord0, tex, vec2(1, 1), false); + vec2 coord0 = vec2(texcoord0.x*windowSize.x, texcoord0.y*windowSize.y); + if(coord0.x < radius) { + if(coord0.y < radius) + tex = shapeCorner(coord0, tex, vec2(radius, radius), false); + else if (coord0.y > windowSize.y - radius) + tex = shapeCorner(coord0, tex, vec2(radius, windowSize.y - radius), true); + else if (coord0.x < outlineThickness) + tex = outlineColor; + else + tex.a = 0; + } + else if(coord0.x > windowSize.x - radius) { + if(coord0.y < radius) + tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius, radius), false); + else if (coord0.y > windowSize.y - radius) + tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius, windowSize.y - radius), true); + else if (coord0.x > windowSize.x - outlineThickness) + tex = outlineColor; + else + tex.a = 0; + } + else { + if (coord0.y < outlineThickness) + tex = outlineColor; + else if (coord0.y > windowSize.y - outlineThickness) + tex = outlineColor; + else + tex.a = 0; + } fragColor = tex; } diff --git a/shapecorners.cpp b/shapecorners.cpp index 426d3f0..e75e893 100644 --- a/shapecorners.cpp +++ b/shapecorners.cpp @@ -21,69 +21,28 @@ #include "shapecorners.h" #include #include -#include -#include -#include -#include -#include #include -#include #include +#include +#include -ShapeCornersEffect::ShapeCornersEffect() : KWin::Effect(), m_shader(nullptr) +ShapeCornersEffect::ShapeCornersEffect() : KWin::Effect() { new KWin::EffectAdaptor(this); QDBusConnection::sessionBus().registerObject("/ShapeCorners", this); - reconfigure(ReconfigureAll); - - QString shadersDir(QStringLiteral("kwin/shaders/1.10/")); -#ifdef KWIN_HAVE_OPENGLES - const qint64 coreVersionNumber = kVersionNumber(3, 0); -#else - const qint64 version = KWin::kVersionNumber(1, 40); -#endif - if (KWin::GLPlatform::instance()->glslVersion() >= version) - shadersDir = QStringLiteral("kwin/shaders/1.40/"); - - const QString fragmentshader = QStandardPaths::locate(QStandardPaths::GenericDataLocation, shadersDir + QStringLiteral("shapecorners.frag")); -// m_shader = KWin::ShaderManager::instance()->loadFragmentShader(KWin::ShaderManager::GenericShader, fragmentshader); - QFile file(fragmentshader); - if (file.open(QFile::ReadOnly)) - { - QByteArray frag = file.readAll(); - auto shader = KWin::ShaderManager::instance()->generateCustomShader(KWin::ShaderTrait::MapTexture, QByteArray(), frag); -#if KWIN_EFFECT_API_VERSION >= 235 - m_shader = std::move(shader); -#else - m_shader.reset(shader); -#endif - file.close(); -// qDebug() << frag; -// qDebug() << "shader valid: " << m_shader->isValid(); - if (m_shader->isValid()) - { - m_shader_cornerIndex = m_shader->uniformLocation("cornerIndex"); - m_shader_windowActive = m_shader->uniformLocation("windowActive"); - m_shader_shadowColor = m_shader->uniformLocation("shadowColor"); - m_shader_radius = m_shader->uniformLocation("radius"); - m_shader_outlineColor = m_shader->uniformLocation("outlineColor"); - m_shader_outlineThickness = m_shader->uniformLocation("outlineThickness"); - for (int i = 0; i < KWindowSystem::windows().count(); ++i) - if (KWin::EffectWindow *win = KWin::effects->findWindow(KWindowSystem::windows().at(i))) - windowAdded(win); - connect(KWin::effects, &KWin::EffectsHandler::windowAdded, this, &ShapeCornersEffect::windowAdded); - connect(KWin::effects, &KWin::EffectsHandler::windowClosed, this, [this](){m_managed.removeOne(dynamic_cast(sender()));}); - } - else - qDebug() << "ShapeCorners: no valid shaders found! ShapeCorners will not work."; + if(m_shaderManager.IsValid()) { + for (int i = 0; i < KWindowSystem::windows().count(); ++i) + if (KWin::EffectWindow *win = KWin::effects->findWindow(KWindowSystem::windows().at(i))) + windowAdded(win); + connect(KWin::effects, &KWin::EffectsHandler::windowAdded, this, &ShapeCornersEffect::windowAdded); + connect(KWin::effects, &KWin::EffectsHandler::windowClosed, this, [this](){ m_managed.removeOne(dynamic_cast(sender())); }); } else - { - qDebug() << "ShapeCorners: no shaders found! Exiting..."; deleteLater(); - } + + reconfigure(ReconfigureAll); } ShapeCornersEffect::~ShapeCornersEffect() = default; @@ -108,21 +67,11 @@ ShapeCornersEffect::windowAdded(KWin::EffectWindow *w) m_managed << w; } -void -ShapeCornersEffect::setRoundness(const int r) -{ - m_size = r; -} - void ShapeCornersEffect::reconfigure(ReconfigureFlags flags) { Q_UNUSED(flags) - KConfigGroup conf = KSharedConfig::openConfig("shapecorners.conf")->group("General"); - setRoundness(conf.readEntry("roundness", 5)); - m_shadowColor = conf.readEntry("shadowColor", QColor(Qt::black)); - m_outlineColor = conf.readEntry("outlineColor", QColor(Qt::black)); - m_outlineThickness = conf.readEntry("outlineThickness", 1.0f); + m_config.Load(); } #if KWIN_EFFECT_API_VERSION > 231 @@ -133,7 +82,7 @@ void ShapeCornersEffect::prePaintWindow(KWin::EffectWindow *w, KWin::WindowPrePaintData &data, int time) #endif { - if (!m_shader->isValid() + if (!m_shaderManager.IsValid() || !m_managed.contains(w) // || KWin::effects->hasActiveFullScreenEffect() || isMaximized(w) @@ -147,23 +96,14 @@ ShapeCornersEffect::prePaintWindow(KWin::EffectWindow *w, KWin::WindowPrePaintDa KWin::effects->prePaintWindow(w, data, time); return; } + const auto& geo = w->frameGeometry(); - const QRect rect[NTex] = - { - QRect(geo.topLeft().x(), geo.topLeft().y(), m_size, m_size), - QRect(geo.topRight().x()-m_size+1, geo.topRight().y(), m_size, m_size), - QRect(geo.bottomRight().x()-m_size+1, geo.bottomRight().y()-m_size+1, m_size, m_size), - QRect(geo.bottomLeft().x(), geo.bottomLeft().y()-m_size+1, m_size, m_size) - }; - for (int i = 0; i < NTex; ++i) - { - data.paint += rect[i]; + data.paint += geo; #if KWIN_EFFECT_API_VERSION < 234 - data.clip -= rect[i]; + data.clip -= geo; #endif - } - QRegion outerRect (geo.x()+m_size-1, geo.y()-1, - geo.width()-m_size*2+1, geo.height()-m_size*2+1, QRegion::Ellipse); + QRegion outerRect (geo.x()+m_config.m_size-1, geo.y()-1, + geo.width()-m_config.m_size*2+1, geo.height()-m_config.m_size*2+1, QRegion::Ellipse); data.paint += outerRect; #if KWIN_EFFECT_API_VERSION < 234 data.clip -=outerRect; @@ -184,7 +124,7 @@ static bool hasShadow(KWin::WindowQuadList &qds) void ShapeCornersEffect::paintWindow(KWin::EffectWindow *w, int mask, QRegion region, KWin::WindowPaintData &data) { - if (!m_shader->isValid() + if (!m_shaderManager.IsValid() || !m_managed.contains(w) // || KWin::effects->hasActiveFullScreenEffect() || isMaximized(w) @@ -201,16 +141,6 @@ ShapeCornersEffect::paintWindow(KWin::EffectWindow *w, int mask, QRegion region, return; } - //map the corners - const auto& geo = w->frameGeometry(); - const QRect rect[NTex] = - { - QRect(geo.topLeft().x(), geo.topLeft().y(), m_size, m_size), - QRect(geo.topRight().x()-m_size+1, geo.topRight().y(), m_size, m_size), - QRect(geo.bottomRight().x()-m_size+1, geo.bottomRight().y()-m_size+1, m_size, m_size), - QRect(geo.bottomLeft().x(), geo.bottomLeft().y()-m_size+1, m_size, m_size) - }; - #if KWIN_EFFECT_API_VERSION < 233 const KWin::WindowQuadList qds(data.quads); //paint the shadow @@ -218,17 +148,13 @@ ShapeCornersEffect::paintWindow(KWin::EffectWindow *w, int mask, QRegion region, KWin::effects->paintWindow(w, mask, region, data); #endif - //copy the corner regions - QList tex; - const QRect s(KWin::effects->virtualScreenGeometry()); - for (int i = 0; i < NTex; ++i) - { - KWin::GLTexture t = KWin::GLTexture(GL_RGBA8, rect[i].size()); - t.bind(); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect[i].x(), s.height() - rect[i].y() - rect[i].height(), rect[i].width(), rect[i].height()); - t.unbind(); - tex.append(t); - } + //copy the background + const auto& geo = w->frameGeometry(); + const auto& s = KWin::effects->virtualScreenGeometry(); + KWin::GLTexture back (GL_RGBA8, geo.size()); + back.bind(); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, geo.x(), s.height() - geo.y() - geo.height(), geo.width(), geo.height()); + back.unbind(); //paint the actual window #if KWIN_EFFECT_API_VERSION < 233 @@ -241,56 +167,18 @@ ShapeCornersEffect::paintWindow(KWin::EffectWindow *w, int mask, QRegion region, glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); { - KWin::ShaderBinder binder(m_shader.get()); - m_shader->setUniform(m_shader_windowActive, KWin::effects->activeWindow() == w); - m_shader->setUniform(m_shader_shadowColor, m_shadowColor); - m_shader->setUniform(m_shader_radius, m_size); - m_shader->setUniform(m_shader_outlineColor, m_outlineColor); - m_shader->setUniform(m_shader_outlineThickness, m_outlineThickness); - for (int i = 0; i < NTex; ++i) { - QMatrix4x4 mvp = data.screenProjectionMatrix(); - mvp.translate(rect[i].x(), rect[i].y()); - m_shader->setUniform(KWin::GLShader::ModelViewProjectionMatrix, mvp); - m_shader->setUniform(m_shader_cornerIndex, i); - tex[i].bind(); - tex[i].render(region & rect[i], rect[i], true); - tex[i].unbind(); - } - } - - if (m_outlineColor.alpha() > 0) { - glLineWidth(m_outlineThickness); - KWin::GLVertexBuffer *vbo = KWin::GLVertexBuffer::streamingBuffer(); - vbo->reset(); - vbo->setUseColor(true); - vbo->setColor(m_outlineColor); - KWin::ShaderBinder binder(KWin::ShaderTrait::UniformColor); - QMatrix4x4 mvp = data.screenProjectionMatrix(); - binder.shader()->setUniform(KWin::GLShader::ModelViewProjectionMatrix, mvp); - QVector verts{ - (float) (w->x()) + m_outlineThickness/2 - 1, (float) (w->y() + m_size), - (float) (w->x()) + m_outlineThickness/2 - 1, (float) (w->y() + w->height() - m_size), -#if KWIN_EFFECT_API_VERSION >= 234 - (float) (w->x() + m_size), (float)w->y() + m_outlineThickness/2 - 1, - (float) (w->x() + w->width() - m_size), (float)w->y() + m_outlineThickness/2 - 1, -#else - (float) (w->x() + m_size), (float)w->y() + m_outlineThickness/2, - (float) (w->x() + w->width() - m_size), (float)w->y() + m_outlineThickness/2, -#endif - (float) (w->x() + w->width()) - m_outlineThickness/2 + 1, (float) (w->y() + m_size), - (float) (w->x() + w->width())- m_outlineThickness/2 + 1, (float) (w->y() + w->height() - m_size), - (float) (w->x() + m_size), (float) (w->y() + w->height()) - m_outlineThickness/2 + 1, - (float) (w->x() + w->width() - m_size), (float) (w->y() + w->height()) - m_outlineThickness/2 + 1 - }; - vbo->setData(2 * 4, 2, verts.data(), nullptr); - vbo->render(region, GL_LINES, true); + m_shaderManager.Bind(data.screenProjectionMatrix(), geo, KWin::effects->activeWindow() == w, m_config); + back.bind(); + back.render(region, geo, true); + back.unbind(); + m_shaderManager.Unbind(); } + glDisable(GL_BLEND); + glDisable(GL_SCISSOR_TEST); #if KWIN_EFFECT_API_VERSION < 233 data.quads = qds; #endif - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); } bool ShapeCornersEffect::supported() diff --git a/shapecorners.h b/shapecorners.h index 014bdc1..68240ce 100644 --- a/shapecorners.h +++ b/shapecorners.h @@ -21,9 +21,7 @@ #define SHAPECORNERS_H #include -#include - -namespace KWin { class GLTexture; } +#include "ShaderManager.h" class Q_DECL_EXPORT ShapeCornersEffect : public KWin::Effect { @@ -36,7 +34,7 @@ class Q_DECL_EXPORT ShapeCornersEffect : public KWin::Effect static bool enabledByDefault() { return supported(); } static bool isMaximized(KWin::EffectWindow *w); - void setRoundness(int r); + void setConfig(const ConfigModel& config) { m_config = config; } void reconfigure(ReconfigureFlags flags) override; #if KWIN_EFFECT_API_VERSION > 231 @@ -51,19 +49,9 @@ protected Q_SLOTS: void windowAdded(KWin::EffectWindow *window); private: - enum { TopLeft = 0, TopRight, BottomRight, BottomLeft, NTex }; - int m_size; - float m_outlineThickness; - QColor m_shadowColor, m_outlineColor; QList m_managed; - - std::unique_ptr m_shader; - int m_shader_cornerIndex = 0; - int m_shader_windowActive = 0; - int m_shader_shadowColor = 0; - int m_shader_radius = 0; - int m_shader_outlineColor = 0; - int m_shader_outlineThickness = 0; + ShaderManager m_shaderManager; + ConfigModel m_config; }; #endif //SHAPECORNERS_H diff --git a/shapecorners_config.cpp b/shapecorners_config.cpp index 4e6ee24..bdefed1 100644 --- a/shapecorners_config.cpp +++ b/shapecorners_config.cpp @@ -36,22 +36,8 @@ class ShapeCornersConfig::Private public: Private(ShapeCornersConfig *config) : q(config) - , roundness("roundness") - , dsp("dsp") - , shadowColor("shadowColor") - , outlineColor("outlineColor") - , outlineThickness("outlineThickness") - , defaultRoundness(5) - , defaultShadows(false) - , defaultShadowColor(QColor(Qt::black)) - , defaultOutlineColor(QColor(Qt::black)) - , defaultOutlineThickness(1.0f) {} ShapeCornersConfig *q; - QString roundness, dsp, shadowColor, - outlineColor, outlineThickness; - QVariant defaultRoundness, defaultShadows, defaultShadowColor, - defaultOutlineColor, defaultOutlineThickness; ConfigDialog *ui; }; @@ -74,17 +60,17 @@ void ShapeCornersConfig::load() { KCModule::load(); - KConfigGroup conf = KSharedConfig::openConfig("shapecorners.conf")->group("General"); - d->ui->roundness->setValue(conf.readEntry(d->roundness, d->defaultRoundness).toInt()); - d->ui->dsp->setChecked(conf.readEntry(d->dsp, d->defaultShadows).toBool()); - QColor shadowColor = conf.readEntry(d->shadowColor, d->defaultShadowColor).value(); + m_config.Load(); + d->ui->roundness->setValue(m_config.m_size); + d->ui->dsp->setChecked(m_config.m_dsp); + QColor shadowColor = m_config.m_shadowColor; d->ui->drawShadowEnabled->setChecked(shadowColor.alpha() > 0); shadowColor.setAlpha(255); d->ui->shadowColor->setColor(shadowColor); - QColor outlineColor = conf.readEntry(d->outlineColor, d->defaultOutlineColor).value(); + QColor outlineColor = m_config.m_outlineColor; d->ui->drawOutlineEnabled->setChecked(outlineColor.alpha() > 0); d->ui->outlineColor->setColor(outlineColor); - d->ui->outlineThickness->setValue(conf.readEntry(d->outlineThickness, d->defaultOutlineThickness).toFloat()); + d->ui->outlineThickness->setValue(m_config.m_outlineThickness); emit changed(false); } @@ -92,18 +78,16 @@ void ShapeCornersConfig::save() { KCModule::save(); - KConfigGroup conf = KSharedConfig::openConfig("shapecorners.conf")->group("General"); - conf.writeEntry(d->roundness, d->ui->roundness->value()); - conf.writeEntry(d->dsp, d->ui->dsp->isChecked()); - auto shadowColor = d->ui->shadowColor->color(); - shadowColor.setAlpha(d->ui->drawShadowEnabled->isChecked()? 255: 0); - conf.writeEntry(d->shadowColor, shadowColor); - auto outlineColor = d->ui->outlineColor->color(); + m_config.m_size = d->ui->roundness->value(); + m_config.m_dsp = d->ui->dsp->isChecked(); + m_config.m_shadowColor = d->ui->shadowColor->color(); + m_config.m_shadowColor.setAlpha(d->ui->drawShadowEnabled->isChecked()? 255: 0); + m_config.m_outlineColor = d->ui->outlineColor->color(); if(!d->ui->drawOutlineEnabled->isChecked()) - outlineColor.setAlpha(0); - conf.writeEntry(d->outlineColor, outlineColor); - conf.writeEntry(d->outlineThickness, d->ui->outlineThickness->value()); - conf.sync(); + m_config.m_outlineColor.setAlpha(0); + m_config.m_outlineThickness = d->ui->outlineThickness->value(); + m_config.Save(); + emit changed(false); OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Effects"), @@ -115,13 +99,17 @@ void ShapeCornersConfig::defaults() { KCModule::defaults(); - d->ui->roundness->setValue(d->defaultRoundness.toInt()); - d->ui->dsp->setChecked(d->defaultShadows.toBool()); - d->ui->shadowColor->setColor(d->defaultShadowColor.value()); - d->ui->drawShadowEnabled->setChecked(d->defaultShadowColor.value().alpha() > 0); - d->ui->outlineColor->setColor(d->defaultOutlineColor.value()); - d->ui->drawOutlineEnabled->setChecked(d->defaultOutlineColor.value().alpha() > 0); - d->ui->outlineThickness->setValue(d->defaultOutlineThickness.toFloat()); + ConfigModel defaultConfig; + d->ui->roundness->setValue(m_config.m_size); + d->ui->dsp->setChecked(m_config.m_dsp); + QColor shadowColor = m_config.m_shadowColor; + d->ui->drawShadowEnabled->setChecked(shadowColor.alpha() > 0); + shadowColor.setAlpha(255); + d->ui->shadowColor->setColor(shadowColor); + QColor outlineColor = m_config.m_outlineColor; + d->ui->drawOutlineEnabled->setChecked(outlineColor.alpha() > 0); + d->ui->outlineColor->setColor(outlineColor); + d->ui->outlineThickness->setValue(m_config.m_outlineThickness); emit changed(true); } diff --git a/shapecorners_config.h b/shapecorners_config.h index 564553d..4a35729 100644 --- a/shapecorners_config.h +++ b/shapecorners_config.h @@ -1,5 +1,6 @@ #include +#include class ShapeCornersConfig : public KCModule { @@ -13,6 +14,7 @@ public slots: void defaults() override; private: + ConfigModel m_config; class Private; Private * const d; friend class Private; From 377bd9008a1a970f969e8e82c42a0b62a1daf3b2 Mon Sep 17 00:00:00 2001 From: Matin Lotfaliei Date: Fri, 22 Jul 2022 13:27:41 -0700 Subject: [PATCH 2/3] Use QRect instead of QRectF for KWin 5.26 --- shapecorners.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/shapecorners.cpp b/shapecorners.cpp index e75e893..dc30c83 100644 --- a/shapecorners.cpp +++ b/shapecorners.cpp @@ -21,7 +21,6 @@ #include "shapecorners.h" #include #include -#include #include #include #include @@ -97,7 +96,12 @@ ShapeCornersEffect::prePaintWindow(KWin::EffectWindow *w, KWin::WindowPrePaintDa return; } - const auto& geo = w->frameGeometry(); +#if KWIN_EFFECT_API_VERSION <= 235 + const QRect& geo = w->frameGeometry(); +#else + const QRectF& geoF = w->frameGeometry(); + const QRect geo ((int)geo.left(), (int)geo.top(), (int)geo.width(), (int)geo.height()); +#endif data.paint += geo; #if KWIN_EFFECT_API_VERSION < 234 data.clip -= geo; @@ -149,7 +153,12 @@ ShapeCornersEffect::paintWindow(KWin::EffectWindow *w, int mask, QRegion region, #endif //copy the background - const auto& geo = w->frameGeometry(); +#if KWIN_EFFECT_API_VERSION <= 235 + const QRect& geo = w->frameGeometry(); +#else + const QRectF& geoF = w->frameGeometry(); + const QRect geo ((int)geo.left(), (int)geo.top(), (int)geo.width(), (int)geo.height()); +#endif const auto& s = KWin::effects->virtualScreenGeometry(); KWin::GLTexture back (GL_RGBA8, geo.size()); back.bind(); From 330bed620d8929c517448951ec6b3c9fc23a8c69 Mon Sep 17 00:00:00 2001 From: Matin Lotfaliei Date: Fri, 22 Jul 2022 13:31:49 -0700 Subject: [PATCH 3/3] Update the incorrect API version --- shapecorners.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shapecorners.cpp b/shapecorners.cpp index dc30c83..d70fb5b 100644 --- a/shapecorners.cpp +++ b/shapecorners.cpp @@ -96,7 +96,7 @@ ShapeCornersEffect::prePaintWindow(KWin::EffectWindow *w, KWin::WindowPrePaintDa return; } -#if KWIN_EFFECT_API_VERSION <= 235 +#if KWIN_EFFECT_API_VERSION < 235 const QRect& geo = w->frameGeometry(); #else const QRectF& geoF = w->frameGeometry(); @@ -153,7 +153,7 @@ ShapeCornersEffect::paintWindow(KWin::EffectWindow *w, int mask, QRegion region, #endif //copy the background -#if KWIN_EFFECT_API_VERSION <= 235 +#if KWIN_EFFECT_API_VERSION < 235 const QRect& geo = w->frameGeometry(); #else const QRectF& geoF = w->frameGeometry();