[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.
This commit is contained in:
Martin Flöser 2022-04-13 20:19:18 +02:00
parent f1f512791e
commit 7dddf3055b
4 changed files with 28 additions and 5 deletions

View file

@ -16,6 +16,7 @@ struct DeformOffscreenData
QScopedPointer<GLTexture> texture;
QScopedPointer<GLFramebuffer> 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 &region,
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 &region,
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 &reg
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

View file

@ -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);

View file

@ -437,6 +437,9 @@ void GLShader::resolveLocations()
mColorLocation[Color] = uniformLocation("geometryColor");
mIntLocation[TextureWidth] = uniformLocation("textureWidth");
mIntLocation[TextureHeight] = uniformLocation("textureHeight");
mLocationsResolved = true;
}

View file

@ -128,6 +128,8 @@ public:
enum IntUniform {
AlphaToOne, ///< @deprecated no longer used
TextureWidth,
TextureHeight,
IntUniformCount
};