Introduce an EffectsHandler::animationsSupported -> bool

Summary:
A new method to tell the effects system whether the compositor scene
is able to drive animations. E.g. on software emulation (llvmpipe) it's
better to not do any animations at all.

This information can be used by effects to adjust their behavior, e.g.
PresentWindows could skip transitions or effects can use it in their
supported check to completely disable themselves.

As a first step all scripted effects are considered to be unsupported
if animations are not supported. They inherit AnimationEffect and are
all about driving animations.

The information whether animations are supported comes from the Scene.
It's implemented in the following way:
 * XRender: animations are always supported
 * QPainter: animations are never supported
 * OpenGL: animations are supported, except for software emulation

In addition - for easier testing - there is a new env variable
KWIN_EFFECTS_FORCE_ANIMATIONS to overwrite the selection.

Reviewers: #kwin, #plasma

Subscribers: kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D2386
This commit is contained in:
Martin Gräßlin 2016-08-10 09:24:53 +02:00
parent bfb2094c0a
commit 142aab2e24
25 changed files with 160 additions and 64 deletions

View file

@ -74,6 +74,7 @@ void TranslucencyTest::initTestCase()
config->sync();
kwinApp()->setConfig(config);
qputenv("KWIN_EFFECTS_FORCE_ANIMATIONS", "1");
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
QVERIFY(Compositor::self());

View file

@ -229,5 +229,15 @@ public:
KWayland::Server::Display *waylandDisplay() const override {
return nullptr;
}
bool animationsSupported() const override {
return m_animationsSuported;
}
void setAnimationsSupported(bool set) {
m_animationsSuported = set;
}
private:
bool m_animationsSuported = true;
};
#endif

View file

@ -43,6 +43,11 @@ ScriptedEffect *ScriptedEffect::create(const KPluginMetaData&)
return nullptr;
}
bool ScriptedEffect::supported()
{
return true;
}
}
class TestBuiltInEffectLoader : public QObject
@ -182,67 +187,75 @@ void TestBuiltInEffectLoader::testSupported_data()
QTest::addColumn<QString>("name");
QTest::addColumn<bool>("expected");
QTest::addColumn<KWin::CompositingType>("type");
QTest::addColumn<bool>("animationsSupported");
const KWin::CompositingType xc = KWin::XRenderCompositing;
const KWin::CompositingType oc = KWin::OpenGL2Compositing;
QTest::newRow("blur") << QStringLiteral("blur") << false << xc;
QTest::newRow("blur") << QStringLiteral("blur") << false << xc << true;
// fails for GL as it does proper tests on what's supported and doesn't just check whether it's GL
QTest::newRow("blur-GL") << QStringLiteral("blur") << false << oc;
QTest::newRow("Contrast") << QStringLiteral("contrast") << false << xc;
QTest::newRow("blur-GL") << QStringLiteral("blur") << false << oc << true;
QTest::newRow("Contrast") << QStringLiteral("contrast") << false << xc << true;
// fails for GL as it does proper tests on what's supported and doesn't just check whether it's GL
QTest::newRow("Contrast-GL") << QStringLiteral("contrast") << false << oc;
QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << false << xc;
QTest::newRow("CoverSwitch-GL") << QStringLiteral("coverswitch") << true << oc;
QTest::newRow("Cube") << QStringLiteral("cube") << false << xc;
QTest::newRow("Cube-GL") << QStringLiteral("cube") << true << oc;
QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << false << xc;
QTest::newRow("CubeSlide-GL") << QStringLiteral("cubeslide") << true << oc;
QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << true << xc;
QTest::newRow("DimInactive") << QStringLiteral("diminactive") << true << xc;
QTest::newRow("DimScreen") << QStringLiteral("dimscreen") << true << xc;
QTest::newRow("FallApart") << QStringLiteral("fallapart") << false << xc;
QTest::newRow("FallApart-GL") << QStringLiteral("fallapart") << true << oc;
QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << false << xc;
QTest::newRow("FlipSwitch-GL") << QStringLiteral("flipswitch") << true << oc;
QTest::newRow("Glide") << QStringLiteral("glide") << false << xc;
QTest::newRow("Glide-GL") << QStringLiteral("glide") << true << oc;
QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << true << xc;
QTest::newRow("Invert") << QStringLiteral("invert") << false << xc;
QTest::newRow("Invert-GL") << QStringLiteral("invert") << true << oc;
QTest::newRow("Kscreen") << QStringLiteral("kscreen") << true << xc;
QTest::newRow("Logout") << QStringLiteral("logout") << true << xc;
QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false << xc;
QTest::newRow("LookingGlass-GL") << QStringLiteral("lookingglass") << true << oc;
QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false << xc;
QTest::newRow("MagicLamp-GL") << QStringLiteral("magiclamp") << true << oc;
QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true << xc;
QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true << xc;
QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true << xc;
QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true << xc;
QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true << xc;
QTest::newRow("Resize") << QStringLiteral("resize") << true << xc;
QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true << xc;
QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true << xc;
QTest::newRow("Sheet") << QStringLiteral("sheet") << false << xc;
QTest::newRow("Sheet-GL") << QStringLiteral("sheet") << true << oc;
QTest::newRow("ShowFps") << QStringLiteral("showfps") << true << xc;
QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true << xc;
QTest::newRow("Slide") << QStringLiteral("slide") << true << xc;
QTest::newRow("SlideBack") << QStringLiteral("slideback") << true << xc;
QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true << xc;
QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true << xc;
QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false << xc;
QTest::newRow("StartupFeedback-GL") << QStringLiteral("startupfeedback") << true << oc;
QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << true << xc;
QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << true << xc;
QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << true << xc;
QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << false << xc;
QTest::newRow("WobblyWindows-GL") << QStringLiteral("wobblywindows") << true << oc;
QTest::newRow("Zoom") << QStringLiteral("zoom") << true << xc;
QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false << xc;
QTest::newRow("Fade - Scripted") << QStringLiteral("fade") << false << xc;
QTest::newRow("Fade - Scripted + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << false << xc;
QTest::newRow("Contrast-GL") << QStringLiteral("contrast") << false << oc << true;
QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << false << xc << true;
QTest::newRow("CoverSwitch-GL") << QStringLiteral("coverswitch") << true << oc << true;
QTest::newRow("CoverSwitch-GL-no-anim") << QStringLiteral("coverswitch") << false << oc << false;
QTest::newRow("Cube") << QStringLiteral("cube") << false << xc << true;
QTest::newRow("Cube-GL") << QStringLiteral("cube") << true << oc << true;
QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << false << xc << true;
QTest::newRow("CubeSlide-GL") << QStringLiteral("cubeslide") << true << oc << true;
QTest::newRow("CubeSlide-GL-no-anim") << QStringLiteral("cubeslide") << false << oc << false;
QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << true << xc << true;
QTest::newRow("DimInactive") << QStringLiteral("diminactive") << true << xc << true;
QTest::newRow("DimScreen") << QStringLiteral("dimscreen") << true << xc << true;
QTest::newRow("FallApart") << QStringLiteral("fallapart") << false << xc << true;
QTest::newRow("FallApart-GL") << QStringLiteral("fallapart") << true << oc << true;
QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << false << xc << true;
QTest::newRow("FlipSwitch-GL") << QStringLiteral("flipswitch") << true << oc << true;
QTest::newRow("FlipSwitch-GL-no-anim") << QStringLiteral("flipswitch") << false << oc << false;
QTest::newRow("Glide") << QStringLiteral("glide") << false << xc << true;
QTest::newRow("Glide-GL") << QStringLiteral("glide") << true << oc << true;
QTest::newRow("Glide-GL-no-anim") << QStringLiteral("glide") << false << oc << false;
QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << true << xc << true;
QTest::newRow("Invert") << QStringLiteral("invert") << false << xc << true;
QTest::newRow("Invert-GL") << QStringLiteral("invert") << true << oc << true;
QTest::newRow("Kscreen") << QStringLiteral("kscreen") << true << xc << true;
QTest::newRow("Logout") << QStringLiteral("logout") << true << xc << true;
QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false << xc << true;
QTest::newRow("LookingGlass-GL") << QStringLiteral("lookingglass") << true << oc << true;
QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false << xc << true;
QTest::newRow("MagicLamp-GL") << QStringLiteral("magiclamp") << true << oc << true;
QTest::newRow("MagicLamp-GL-no-anim") << QStringLiteral("magiclamp") << false << oc << false;
QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true << xc << true;
QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true << xc << true;
QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true << xc << true;
QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true << xc << true;
QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true << xc << true;
QTest::newRow("Resize") << QStringLiteral("resize") << true << xc << true;
QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true << xc << true;
QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true << xc << true;
QTest::newRow("Sheet") << QStringLiteral("sheet") << false << xc << true;
QTest::newRow("Sheet-GL") << QStringLiteral("sheet") << true << oc << true;
QTest::newRow("Sheet-GL-no-anim") << QStringLiteral("sheet") << false << oc << false;
QTest::newRow("ShowFps") << QStringLiteral("showfps") << true << xc << true;
QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true << xc << true;
QTest::newRow("Slide") << QStringLiteral("slide") << true << xc << true;
QTest::newRow("SlideBack") << QStringLiteral("slideback") << true << xc << true;
QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true << xc << true;
QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true << xc << true;
QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false << xc << true;
QTest::newRow("StartupFeedback-GL") << QStringLiteral("startupfeedback") << true << oc << true;
QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << true << xc << true;
QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << true << xc << true;
QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << true << xc << true;
QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << false << xc << true;
QTest::newRow("WobblyWindows-GL") << QStringLiteral("wobblywindows") << true << oc << true;
QTest::newRow("WobblyWindows-GL-no-anim") << QStringLiteral("wobblywindows") << false << oc << false;
QTest::newRow("Zoom") << QStringLiteral("zoom") << true << xc << true;
QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false << xc << true;
QTest::newRow("Fade - Scripted") << QStringLiteral("fade") << false << xc << true;
QTest::newRow("Fade - Scripted + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << false << xc << true;
}
void TestBuiltInEffectLoader::testSupported()
@ -250,8 +263,11 @@ void TestBuiltInEffectLoader::testSupported()
QFETCH(QString, name);
QFETCH(bool, expected);
QFETCH(KWin::CompositingType, type);
QFETCH(bool, animationsSupported);
MockEffectsHandler mockHandler(type);
mockHandler.setAnimationsSupported(animationsSupported);
QCOMPARE(mockHandler.animationsSupported(), animationsSupported);
KWin::BuiltInEffectLoader loader;
QCOMPARE(loader.isEffectSupported(name), expected);
}

View file

@ -42,6 +42,11 @@ ScriptedEffect *ScriptedEffect::create(const KPluginMetaData&)
return nullptr;
}
bool ScriptedEffect::supported()
{
return true;
}
}
class TestPluginEffectLoader : public QObject

View file

@ -136,11 +136,17 @@ void TestScriptedEffectLoader::testHasEffect()
QFETCH(QString, name);
QFETCH(bool, expected);
MockEffectsHandler mockHandler(KWin::XRenderCompositing);
KWin::ScriptedEffectLoader loader;
QCOMPARE(loader.hasEffect(name), expected);
// each available effect should also be supported
QCOMPARE(loader.isEffectSupported(name), expected);
if (expected) {
mockHandler.setAnimationsSupported(false);
QVERIFY(!loader.isEffectSupported(name));
}
}
void TestScriptedEffectLoader::testKnownEffects()

View file

@ -205,6 +205,9 @@ bool ScriptedEffectLoader::hasEffect(const QString &name) const
bool ScriptedEffectLoader::isEffectSupported(const QString &name) const
{
// scripted effects are in general supported
if (!ScriptedEffect::supported()) {
return false;
}
return hasEffect(name);
}
@ -239,6 +242,11 @@ bool ScriptedEffectLoader::loadEffect(const KPluginMetaData &effect, LoadEffectF
return false;
}
if (!ScriptedEffect::supported()) {
qCDebug(KWIN_CORE) << "Effect is not supported: " << name;
return false;
}
ScriptedEffect *e = ScriptedEffect::create(effect);
if (!e) {
qCDebug(KWIN_CORE) << "Could not initialize scripted effect: " << name;

View file

@ -1505,6 +1505,16 @@ void EffectsHandlerImpl::doneOpenGLContextCurrent()
m_scene->doneOpenGLContextCurrent();
}
bool EffectsHandlerImpl::animationsSupported() const
{
static const QByteArray forceEnvVar = qgetenv("KWIN_EFFECTS_FORCE_ANIMATIONS");
if (!forceEnvVar.isEmpty()) {
static const int forceValue = forceEnvVar.toInt();
return forceValue == 1;
}
return m_scene->animationsSupported();
}
//****************************************
// EffectWindowImpl
//****************************************

View file

@ -226,6 +226,8 @@ public:
KWayland::Server::Display *waylandDisplay() const override;
bool animationsSupported() const override;
Scene *scene() const {
return m_scene;
}

View file

@ -80,7 +80,7 @@ CoverSwitchEffect::~CoverSwitchEffect()
bool CoverSwitchEffect::supported()
{
return effects->isOpenGLCompositing();
return effects->isOpenGLCompositing() && effects->animationsSupported();
}
void CoverSwitchEffect::reconfigure(ReconfigureFlags)

View file

@ -49,7 +49,7 @@ CubeSlideEffect::~CubeSlideEffect()
bool CubeSlideEffect::supported()
{
return effects->isOpenGLCompositing();
return effects->isOpenGLCompositing() && effects->animationsSupported();
}
void CubeSlideEffect::reconfigure(ReconfigureFlags)

View file

@ -28,7 +28,7 @@ namespace KWin
bool FallApartEffect::supported()
{
return effects->isOpenGLCompositing();
return effects->isOpenGLCompositing() && effects->animationsSupported();
}
FallApartEffect::FallApartEffect()

View file

@ -83,7 +83,7 @@ FlipSwitchEffect::~FlipSwitchEffect()
bool FlipSwitchEffect::supported()
{
return effects->isOpenGLCompositing();
return effects->isOpenGLCompositing() && effects->animationsSupported();
}
void FlipSwitchEffect::reconfigure(ReconfigureFlags)

View file

@ -55,7 +55,7 @@ GlideEffect::~GlideEffect()
bool GlideEffect::supported()
{
return effects->isOpenGLCompositing();
return effects->isOpenGLCompositing() && effects->animationsSupported();
}
void GlideEffect::reconfigure(ReconfigureFlags)

View file

@ -43,7 +43,7 @@ MagicLampEffect::MagicLampEffect()
bool MagicLampEffect::supported()
{
return effects->isOpenGLCompositing();
return effects->isOpenGLCompositing() && effects->animationsSupported();
}
void MagicLampEffect::reconfigure(ReconfigureFlags)

View file

@ -43,7 +43,7 @@ SheetEffect::SheetEffect()
bool SheetEffect::supported()
{
return effects->isOpenGLCompositing();
return effects->isOpenGLCompositing() && effects->animationsSupported();
}
void SheetEffect::reconfigure(ReconfigureFlags)

View file

@ -222,7 +222,7 @@ void WobblyWindowsEffect::reconfigure(ReconfigureFlags)
bool WobblyWindowsEffect::supported()
{
return effects->isOpenGLCompositing();
return effects->isOpenGLCompositing() && effects->animationsSupported();
}
void WobblyWindowsEffect::setParameterSet(const ParameterSet& pset)

View file

@ -5,7 +5,7 @@ ecm_setup_version(${PROJECT_VERSION}
VARIABLE_PREFIX KWINEFFECTS
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kwineffects_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KWinEffectsConfigVersion.cmake"
SOVERSION 8
SOVERSION 9
)
### xrenderutils lib ###

View file

@ -1101,6 +1101,16 @@ public:
*/
virtual KWayland::Server::Display *waylandDisplay() const = 0;
/**
* Whether animations are supported by the Scene.
* If this method returns @c false Effects are supposed to not
* animate transitions.
*
* @returns Whether the Scene can drive animations
* @since 5.8
**/
virtual bool animationsSupported() const = 0;
/**
* @return @ref KConfigGroup which holds given effect's config options
**/

View file

@ -149,6 +149,14 @@ public:
virtual Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *) = 0;
/**
* Whether the Scene is able to drive animations.
* This is used as a hint to the effects system which effects can be supported.
* If the Scene performs software rendering it is supposed to return @c false,
* if rendering is hardware accelerated it should return @c true.
**/
virtual bool animationsSupported() const = 0;
Q_SIGNALS:
void frameRendered();

View file

@ -956,6 +956,11 @@ Decoration::Renderer *SceneOpenGL::createDecorationRenderer(Decoration::Decorate
return new SceneOpenGLDecorationRenderer(impl);
}
bool SceneOpenGL::animationsSupported() const
{
return !GLPlatform::instance()->isSoftwareEmulation();
}
//****************************************
// SceneOpenGL2
//****************************************

View file

@ -63,6 +63,7 @@ public:
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
virtual void triggerFence() override;
virtual QMatrix4x4 projectionMatrix() const = 0;
bool animationsSupported() const override;
void insertWait();

View file

@ -119,6 +119,10 @@ public:
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
void screenGeometryChanged(const QSize &size) override;
bool animationsSupported() const override {
return false;
}
QPainter *painter();
QPainterBackend *backend() const {

View file

@ -169,6 +169,10 @@ public:
}
Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client);
bool animationsSupported() const override {
return true;
}
static SceneXrender *createScene(QObject *parent);
protected:
virtual Scene::Window *createWindow(Toplevel *toplevel);

View file

@ -450,6 +450,11 @@ ScriptedEffect *ScriptedEffect::create(const QString& effectName, const QString&
return effect;
}
bool ScriptedEffect::supported()
{
return effects->animationsSupported();
}
ScriptedEffect::ScriptedEffect()
: AnimationEffect()
, m_engine(new QScriptEngine(this))

View file

@ -67,6 +67,7 @@ public:
void setActiveConfig(const QString &name);
static ScriptedEffect *create(const QString &effectName, const QString &pathToScript, int chainPosition);
static ScriptedEffect *create(const KPluginMetaData &effect);
static bool supported();
virtual ~ScriptedEffect();
/**
* Whether another effect has grabbed the @p w with the given @p grabRole.