Keep KWin responsive while loading all effects

Loading all effects during startup can take some time[1] and during
that time the screen is frozen as the loading blocks the compositor.

This change doesn't load effects directly but puts them into a queue.
The loading is controlled by invoking the dequeue through a queued
connection. Thus we get a firing compositing timer in between and can
ensure that a frame is rendered when needed and also react to X events
during the loading.

[1] On my high-end system the set of effects I use take about 200 msec
    to load.

REVIEW: 115297
icc-effect-5.14.5
Martin Gräßlin 2014-01-24 15:42:40 +01:00
parent 1576c55cd2
commit 29af52fbf1
2 changed files with 59 additions and 3 deletions

View File

@ -167,6 +167,41 @@ void ScreenLockerWatcher::setLocked(bool activated)
emit locked(m_locked);
}
EffectLoader::EffectLoader(EffectsHandlerImpl *parent)
: QObject(parent)
, m_effects(parent)
, m_dequeueScheduled(false)
{
}
EffectLoader::~EffectLoader()
{
}
void EffectLoader::queue(const QString &effect, bool checkDefault)
{
m_queue.enqueue(qMakePair(effect, checkDefault));
scheduleDequeue();
}
void EffectLoader::dequeue()
{
Q_ASSERT(!m_queue.isEmpty());
m_dequeueScheduled = false;
const auto pair = m_queue.dequeue();
m_effects->loadEffect(pair.first, pair.second);
scheduleDequeue();
}
void EffectLoader::scheduleDequeue()
{
if (m_queue.isEmpty() || m_dequeueScheduled) {
return;
}
m_dequeueScheduled = true;
QMetaObject::invokeMethod(this, "dequeue", Qt::QueuedConnection);
}
//---------------------
// Static
@ -211,6 +246,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
, m_screenLockerWatcher(new ScreenLockerWatcher(this))
, m_desktopRendering(false)
, m_currentRenderedDesktop(0)
, m_effectLoader(new EffectLoader(this))
{
new EffectsAdaptor(this);
QDBusConnection dbus = QDBusConnection::sessionBus();
@ -354,8 +390,8 @@ void EffectsHandlerImpl::slotEffectsQueried()
// Then load those that should be loaded
for (const QString & effectName : effectsToBeLoaded) {
if (!isEffectLoaded(effectName)) {
if (loadEffect(effectName, checkDefault.contains(effectName)))
newLoaded.append(effectName);
m_effectLoader->queue(effectName, checkDefault.contains(effectName));
newLoaded.append(effectName);
}
}
for (const EffectPair & ep : loaded_effects) {
@ -1587,7 +1623,7 @@ void EffectsHandlerImpl::reloadEffect(Effect *effect)
}
if (!effectName.isNull()) {
unloadEffect(effectName);
loadEffect(effectName);
m_effectLoader->queue(effectName);
}
}

View File

@ -29,6 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QStack>
#include <QHash>
#include <QQueue>
#include <Plasma/FrameSvg>
namespace Plasma {
@ -51,6 +52,7 @@ class WindowThumbnailItem;
class Client;
class Compositor;
class Deleted;
class EffectLoader;
class Unmanaged;
class ScreenLockerWatcher;
@ -282,6 +284,7 @@ private:
int m_currentRenderedDesktop;
Xcb::Window m_mouseInterceptionWindow;
QList<Effect*> m_grabbedMouseEffects;
EffectLoader *m_effectLoader;
};
class EffectWindowImpl : public EffectWindow
@ -462,6 +465,23 @@ private:
bool m_locked;
};
class EffectLoader : public QObject
{
Q_OBJECT
public:
explicit EffectLoader(EffectsHandlerImpl *parent);
virtual ~EffectLoader();
void queue(const QString &effect, bool checkDefault = false);
private Q_SLOTS:
void dequeue();
private:
void scheduleDequeue();
EffectsHandlerImpl *m_effects;
QQueue<QPair<QString, bool>> m_queue;
bool m_dequeueScheduled;
};
inline
QList<EffectWindow*> EffectsHandlerImpl::elevatedWindows() const
{