From 7dddf3055bc8a46fc14a9b37bbae6c22a9aa4169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Wed, 13 Apr 2022 20:19:18 +0200 Subject: [PATCH] [libkwineffects] Support custom shaders in DeformEffect For a redirected window a custom shader can be specified to draw the redirected texture to screen. This is useful for inheriting effects to customize the rendering. Two new int uniforms TextureWidth and TextureHeight are added and set from DeformEffect when rendering the texture. --- src/libkwineffects/kwindeformeffect.cpp | 21 ++++++++++++++++----- src/libkwineffects/kwindeformeffect.h | 7 +++++++ src/libkwineffects/kwinglutils.cpp | 3 +++ src/libkwineffects/kwinglutils.h | 2 ++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/libkwineffects/kwindeformeffect.cpp b/src/libkwineffects/kwindeformeffect.cpp index 01124362d3..ec1a1a1586 100644 --- a/src/libkwineffects/kwindeformeffect.cpp +++ b/src/libkwineffects/kwindeformeffect.cpp @@ -16,6 +16,7 @@ struct DeformOffscreenData QScopedPointer texture; QScopedPointer fbo; bool isDirty = true; + GLShader *shader = nullptr; }; class DeformEffectPrivate @@ -26,7 +27,7 @@ public: QMetaObject::Connection windowDeletedConnection; void paint(EffectWindow *window, GLTexture *texture, const QRegion ®ion, - const WindowPaintData &data, const WindowQuadList &quads); + const WindowPaintData &data, const WindowQuadList &quads, GLShader *offscreenShader); GLTexture *maybeRender(EffectWindow *window, DeformOffscreenData *offscreenData); bool live = true; @@ -130,10 +131,10 @@ GLTexture *DeformEffectPrivate::maybeRender(EffectWindow *window, DeformOffscree } void DeformEffectPrivate::paint(EffectWindow *window, GLTexture *texture, const QRegion ®ion, - const WindowPaintData &data, const WindowQuadList &quads) + const WindowPaintData &data, const WindowQuadList &quads, GLShader *offscreenShader) { - ShaderBinder binder(ShaderTrait::MapTexture | ShaderTrait::Modulate | ShaderTrait::AdjustSaturation); - GLShader *shader = binder.shader(); + GLShader *shader = offscreenShader ? offscreenShader : ShaderManager::instance()->shader(ShaderTrait::MapTexture | ShaderTrait::Modulate | ShaderTrait::AdjustSaturation); + ShaderBinder binder(shader); const bool indexedQuads = GLVertexBuffer::supportsIndexedQuads(); const GLenum primitiveType = indexedQuads ? GL_QUADS : GL_TRIANGLES; @@ -165,6 +166,8 @@ void DeformEffectPrivate::paint(EffectWindow *window, GLTexture *texture, const shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp); shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a)); shader->setUniform(GLShader::Saturation, data.saturation()); + shader->setUniform(GLShader::TextureWidth, texture->width()); + shader->setUniform(GLShader::TextureHeight, texture->height()); texture->bind(); vbo->draw(effects->mapToRenderTarget(region), primitiveType, 0, verticesPerQuad * quads.count(), true); @@ -199,7 +202,7 @@ void DeformEffect::drawWindow(EffectWindow *window, int mask, const QRegion ® deform(window, mask, data, quads); GLTexture *texture = d->maybeRender(window, offscreenData); - d->paint(window, texture, region, data, quads); + d->paint(window, texture, region, data, quads, offscreenData->shader); } void DeformEffect::handleWindowDamaged(EffectWindow *window) @@ -234,4 +237,12 @@ void DeformEffect::destroyConnections() d->windowDeletedConnection = {}; } +void DeformEffect::setShader(EffectWindow *window, GLShader *shader) +{ + DeformOffscreenData *offscreenData = d->windows.value(window); + if (offscreenData) { + offscreenData->shader = shader; + } +} + } // namespace KWin diff --git a/src/libkwineffects/kwindeformeffect.h b/src/libkwineffects/kwindeformeffect.h index 720b56d328..5ae5685fd5 100644 --- a/src/libkwineffects/kwindeformeffect.h +++ b/src/libkwineffects/kwindeformeffect.h @@ -63,6 +63,13 @@ protected: */ virtual void deform(EffectWindow *window, int mask, WindowPaintData &data, WindowQuadList &quads); + /** + * Allows to specify a @p shader to draw the redirected texture for @p window. + * Can only be called once the window is redirected. + * @since 5.25 + **/ + void setShader(EffectWindow *window, GLShader *shader); + private Q_SLOTS: void handleWindowDamaged(EffectWindow *window); void handleWindowDeleted(EffectWindow *window); diff --git a/src/libkwineffects/kwinglutils.cpp b/src/libkwineffects/kwinglutils.cpp index bf3d9b44ec..9f60c29a85 100644 --- a/src/libkwineffects/kwinglutils.cpp +++ b/src/libkwineffects/kwinglutils.cpp @@ -437,6 +437,9 @@ void GLShader::resolveLocations() mColorLocation[Color] = uniformLocation("geometryColor"); + mIntLocation[TextureWidth] = uniformLocation("textureWidth"); + mIntLocation[TextureHeight] = uniformLocation("textureHeight"); + mLocationsResolved = true; } diff --git a/src/libkwineffects/kwinglutils.h b/src/libkwineffects/kwinglutils.h index 3103dd550d..b13490afea 100644 --- a/src/libkwineffects/kwinglutils.h +++ b/src/libkwineffects/kwinglutils.h @@ -128,6 +128,8 @@ public: enum IntUniform { AlphaToOne, ///< @deprecated no longer used + TextureWidth, + TextureHeight, IntUniformCount };