[libkwineffects] Add support for shaders in AnimationEffect
The animate and set calls are extended for an optional GLShader* to allow specifying a custom shader to use during the animation. To properly support rendering a complete window in the effect the AnimationEffect gets based on the DeformEffect. If a shader is used during the animation the window gets redirected. For the animation with shaders two new enum values are added to the AnimationType enum: * Shader * ShaderUniform The Shader animation type is for specifying that the animation uses a shader. During the animation a uniform "animationProgress" is set on the shader. The ShaderUniform animation type behaves exactly like the Shader type, but also animates a user provided uniform. The meta data of the animation is interpreted as a uniform location for a float uniform and during the animation this uniform is updated with the interpolated animation data.
This commit is contained in:
parent
7dddf3055b
commit
47b330ea23
5 changed files with 55 additions and 12 deletions
|
@ -72,7 +72,7 @@ AniData::AniData()
|
|||
AniData::AniData(AnimationEffect::Attribute a, int meta_, const FPx2 &to_,
|
||||
int delay, const FPx2 &from_, bool waitAtSource_,
|
||||
FullScreenEffectLockPtr fullScreenEffectLock_, bool keepAlive,
|
||||
PreviousWindowPixmapLockPtr previousWindowPixmapLock_)
|
||||
PreviousWindowPixmapLockPtr previousWindowPixmapLock_, GLShader *shader)
|
||||
: attribute(a)
|
||||
, from(from_)
|
||||
, to(to_)
|
||||
|
@ -84,6 +84,7 @@ AniData::AniData(AnimationEffect::Attribute a, int meta_, const FPx2 &to_,
|
|||
, keepAlive(keepAlive)
|
||||
, previousWindowPixmapLock(std::move(previousWindowPixmapLock_))
|
||||
, lastPresentTime(std::chrono::milliseconds::zero())
|
||||
, shader(shader)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
AniData(AnimationEffect::Attribute a, int meta, const FPx2 &to,
|
||||
int delay, const FPx2 &from, bool waitAtSource,
|
||||
FullScreenEffectLockPtr = FullScreenEffectLockPtr(),
|
||||
bool keepAlive = true, PreviousWindowPixmapLockPtr previousWindowPixmapLock = {});
|
||||
bool keepAlive = true, PreviousWindowPixmapLockPtr previousWindowPixmapLock = {}, GLShader *shader = nullptr);
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
|
@ -94,6 +94,7 @@ public:
|
|||
PreviousWindowPixmapLockPtr previousWindowPixmapLock;
|
||||
AnimationEffect::TerminationFlags terminationFlags;
|
||||
std::chrono::milliseconds lastPresentTime;
|
||||
GLShader *shader{nullptr};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
#include "kwinanimationeffect.h"
|
||||
#include "kwinglutils.h"
|
||||
#include "anidata_p.h"
|
||||
|
||||
#include <QAction>
|
||||
|
@ -207,7 +208,7 @@ void AnimationEffect::validate(Attribute a, uint &meta, FPx2 *from, FPx2 *to, co
|
|||
}
|
||||
}
|
||||
|
||||
quint64 AnimationEffect::p_animate(EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, const QEasingCurve &curve, int delay, FPx2 from, bool keepAtTarget, bool fullScreenEffect, bool keepAlive)
|
||||
quint64 AnimationEffect::p_animate(EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, const QEasingCurve &curve, int delay, FPx2 from, bool keepAtTarget, bool fullScreenEffect, bool keepAlive, GLShader *shader)
|
||||
{
|
||||
const bool waitAtSource = from.isValid();
|
||||
validate(a, meta, &from, &to, w);
|
||||
|
@ -249,7 +250,8 @@ quint64 AnimationEffect::p_animate(EffectWindow *w, Attribute a, uint meta, int
|
|||
waitAtSource, // Whether the animation should be kept at source
|
||||
fullscreen, // Full screen effect lock
|
||||
keepAlive, // Keep alive flag
|
||||
previousPixmap // Previous window pixmap lock
|
||||
previousPixmap, // Previous window pixmap lock
|
||||
shader
|
||||
));
|
||||
|
||||
const quint64 ret_id = ++d->m_animCounter;
|
||||
|
@ -280,6 +282,9 @@ quint64 AnimationEffect::p_animate(EffectWindow *w, Attribute a, uint meta, int
|
|||
} else {
|
||||
triggerRepaint();
|
||||
}
|
||||
if (shader) {
|
||||
DeformEffect::redirect(w);
|
||||
}
|
||||
return ret_id;
|
||||
}
|
||||
|
||||
|
@ -405,6 +410,9 @@ bool AnimationEffect::cancel(quint64 animationId)
|
|||
for (AniMap::iterator entry = d->m_animations.begin(), mapEnd = d->m_animations.end(); entry != mapEnd; ++entry) {
|
||||
for (QList<AniData>::iterator anim = entry->first.begin(), animEnd = entry->first.end(); anim != animEnd; ++anim) {
|
||||
if (anim->id == animationId) {
|
||||
if (anim->shader && std::none_of(entry->first.begin(), entry->first.end(), [animationId] (const auto &anim) { return anim.id != animationId && anim.shader; })) {
|
||||
unredirect(entry.key());
|
||||
}
|
||||
entry->first.erase(anim); // remove the animation
|
||||
if (entry->first.isEmpty()) { // no other animations on the window, release it.
|
||||
d->m_animations.erase(entry);
|
||||
|
@ -642,11 +650,27 @@ void AnimationEffect::paintWindow(EffectWindow *w, int mask, QRegion region, Win
|
|||
case CrossFadePrevious:
|
||||
data.setCrossFadeProgress(progress(*anim));
|
||||
break;
|
||||
case Shader:
|
||||
if (anim->shader && anim->shader->isValid()) {
|
||||
ShaderBinder binder{anim->shader};
|
||||
anim->shader->setUniform("animationProgress", progress(*anim));
|
||||
setShader(w, anim->shader);
|
||||
}
|
||||
break;
|
||||
case ShaderUniform:
|
||||
if (anim->shader && anim->shader->isValid()) {
|
||||
ShaderBinder binder{anim->shader};
|
||||
anim->shader->setUniform("animationProgress", progress(*anim));
|
||||
anim->shader->setUniform(anim->meta, interpolated(*anim));
|
||||
setShader(w, anim->shader);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
effects->paintWindow(w, mask, region, data);
|
||||
}
|
||||
|
||||
|
@ -667,6 +691,9 @@ void AnimationEffect::postPaintScreen()
|
|||
}
|
||||
EffectWindow *window = entry.key();
|
||||
d->m_justEndedAnimation = anim->id;
|
||||
if (anim->shader && std::none_of(entry->first.begin(), entry->first.end(), [anim] (const auto &other) { return anim->id != other.id && other.shader; })) {
|
||||
unredirect(window);
|
||||
}
|
||||
animationEnded(window, anim->attribute, anim->meta);
|
||||
d->m_justEndedAnimation = 0;
|
||||
// NOTICE animationEnded is an external call and might have called "::animate"
|
||||
|
@ -854,6 +881,8 @@ void AnimationEffect::updateLayerRepaints()
|
|||
case Brightness:
|
||||
case Saturation:
|
||||
case CrossFadePrevious:
|
||||
case Shader:
|
||||
case ShaderUniform:
|
||||
createRegion = true;
|
||||
break;
|
||||
case Rotation:
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <QEasingCurve>
|
||||
#include <QElapsedTimer>
|
||||
#include <QtMath>
|
||||
#include <kwineffects.h>
|
||||
#include <kwindeformeffect.h>
|
||||
#include <kwineffects_export.h>
|
||||
|
||||
namespace KWin
|
||||
|
@ -191,7 +191,7 @@ class AnimationEffectPrivate;
|
|||
*
|
||||
* @since 4.8
|
||||
*/
|
||||
class KWINEFFECTS_EXPORT AnimationEffect : public Effect
|
||||
class KWINEFFECTS_EXPORT AnimationEffect : public DeformEffect
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -217,6 +217,16 @@ public:
|
|||
Clip,
|
||||
Generic,
|
||||
CrossFadePrevious,
|
||||
/**
|
||||
* Performs an animation with a provided shader.
|
||||
* The float uniform @c animationProgress is set to the current progress of the animation.
|
||||
**/
|
||||
Shader,
|
||||
/**
|
||||
* Like Shader, but additionally allows to animate a float uniform passed to the shader.
|
||||
* The uniform location must be provided as metadata.
|
||||
**/
|
||||
ShaderUniform,
|
||||
NonFloatBase = Position
|
||||
};
|
||||
Q_ENUM(Attribute)
|
||||
|
@ -360,12 +370,13 @@ protected:
|
|||
* @param fullScreen Sets this effect as the active full screen effect for the
|
||||
* duration of the animation.
|
||||
* @param keepAlive Whether closed windows should be kept alive during animation.
|
||||
* @param shader Optional shader to use to render the window.
|
||||
* @returns An ID that you can use to cancel a running animation.
|
||||
* @since 4.8
|
||||
*/
|
||||
quint64 animate(EffectWindow *w, Attribute a, uint meta, int ms, const FPx2 &to, const QEasingCurve &curve = QEasingCurve(), int delay = 0, const FPx2 &from = FPx2(), bool fullScreen = false, bool keepAlive = true)
|
||||
quint64 animate(EffectWindow *w, Attribute a, uint meta, int ms, const FPx2 &to, const QEasingCurve &curve = QEasingCurve(), int delay = 0, const FPx2 &from = FPx2(), bool fullScreen = false, bool keepAlive = true, GLShader *shader = nullptr)
|
||||
{
|
||||
return p_animate(w, a, meta, ms, to, curve, delay, from, false, fullScreen, keepAlive);
|
||||
return p_animate(w, a, meta, ms, to, curve, delay, from, false, fullScreen, keepAlive, shader);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -392,12 +403,13 @@ protected:
|
|||
* @param fullScreen Sets this effect as the active full screen effect for the
|
||||
* duration of the animation.
|
||||
* @param keepAlive Whether closed windows should be kept alive during animation.
|
||||
* @param shader Optional shader to use to render the window.
|
||||
* @returns An ID that you need to use to cancel this manipulation.
|
||||
* @since 4.11
|
||||
*/
|
||||
quint64 set(EffectWindow *w, Attribute a, uint meta, int ms, const FPx2 &to, const QEasingCurve &curve = QEasingCurve(), int delay = 0, const FPx2 &from = FPx2(), bool fullScreen = false, bool keepAlive = true)
|
||||
quint64 set(EffectWindow *w, Attribute a, uint meta, int ms, const FPx2 &to, const QEasingCurve &curve = QEasingCurve(), int delay = 0, const FPx2 &from = FPx2(), bool fullScreen = false, bool keepAlive = true, GLShader *shader = nullptr)
|
||||
{
|
||||
return p_animate(w, a, meta, ms, to, curve, delay, from, true, fullScreen, keepAlive);
|
||||
return p_animate(w, a, meta, ms, to, curve, delay, from, true, fullScreen, keepAlive, shader);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -506,7 +518,7 @@ protected:
|
|||
AniMap state() const;
|
||||
|
||||
private:
|
||||
quint64 p_animate(EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, const QEasingCurve &curve, int delay, FPx2 from, bool keepAtTarget, bool fullScreenEffect, bool keepAlive);
|
||||
quint64 p_animate(EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, const QEasingCurve &curve, int delay, FPx2 from, bool keepAtTarget, bool fullScreenEffect, bool keepAlive, GLShader *shader);
|
||||
QRect clipRect(const QRect &windowRect, const AniData &) const;
|
||||
float interpolated(const AniData &, int i = 0) const;
|
||||
float progress(const AniData &) const;
|
||||
|
|
|
@ -180,7 +180,7 @@ X-KDE-Library=kwin4_effect_cooleffect
|
|||
|
||||
#define KWIN_EFFECT_API_MAKE_VERSION(major, minor) ((major) << 8 | (minor))
|
||||
#define KWIN_EFFECT_API_VERSION_MAJOR 0
|
||||
#define KWIN_EFFECT_API_VERSION_MINOR 233
|
||||
#define KWIN_EFFECT_API_VERSION_MINOR 234
|
||||
#define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
|
||||
KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR)
|
||||
|
||||
|
|
Loading…
Reference in a new issue