This commit adds support to multiple render threads in Plasma::Wallpaper and rendering queuing support.

This commit will fix at least one bug (but it might fix more bugs as side effect).
http://reviewboard.kde.org/r/3092/

svn path=/trunk/KDE/kdelibs/; revision=1098658
This commit is contained in:
Davide Bettio 2010-03-04 01:33:19 +00:00
parent 3dff1d2d99
commit 3411b5c8cd
5 changed files with 90 additions and 13 deletions

View File

@ -21,6 +21,9 @@
#ifndef PLASMA_WALLPAPERPRIVATE_H
#define PLASMA_WALLPAPERPRIVATE_H
#include <QtCore/QQueue>
#include <QtCore/QWeakPointer>
#include "plasma/scripting/wallpaperscript.h"
#include "plasma/private/dataengineconsumer_p.h"
#include "plasma/private/wallpaperrenderthread_p.h"
@ -31,6 +34,16 @@ namespace Plasma
class WallpaperPrivate : public DataEngineConsumer
{
public:
class RenderRequest
{
public:
QWeakPointer<Wallpaper> parent;
QString file;
QSize size;
Wallpaper::ResizeMethod resizeMethod;
QColor color;
};
WallpaperPrivate(KService::Ptr service, Wallpaper *wallpaper);
QString cachePath(const QString &key) const;
@ -38,12 +51,13 @@ public:
int resizeMethod, const QColor &color) const;
void initScript();
void renderCompleted(int token, const QImage &image,
void renderCompleted(WallpaperRenderThread *renderer,int token, const QImage &image,
const QString &sourceImagePath, const QSize &size,
int resizeMethod, const QColor &color);
void setupScriptSupport();
static WallpaperRenderThread s_renderer;
static QList<WallpaperRenderThread *> s_renderers;
static QQueue<RenderRequest> s_renderQueue;
static PackageStructure::Ptr s_packageStructure;
Wallpaper *q;

View File

@ -116,7 +116,7 @@ void WallpaperRenderThread::run()
result.fill(color.rgba());
if (file.isEmpty() || !QFile::exists(file)) {
emit done(token, result, file, size, method, color);
emit done(this, token, result, file, size, method, color);
break;
}
@ -258,11 +258,16 @@ void WallpaperRenderThread::run()
}
// signal we're done
emit done(token, result, file, size, method, color);
emit done(this, token, result, file, size, method, color);
break;
}
}
int WallpaperRenderThread::currentToken()
{
return m_currentToken;
}
} // namespace Plasma
#include "wallpaperrenderthread_p.moc"

View File

@ -45,9 +45,10 @@ public:
void setSize(const QSize &size);
void setRatio(float ratio);
int currentToken();
Q_SIGNALS:
void done(int token, const QImage &pixmap,
void done(WallpaperRenderThread *renderer,int token, const QImage &pixmap,
const QString &sourceImagePath, const QSize &size,
int resizeMethod, const QColor &color);
protected:

View File

@ -25,6 +25,7 @@
#include <QFileInfo>
#include <QImage>
#include <QAction>
#include <QQueue>
#include <QTimer>
#include <kdebug.h>
@ -34,6 +35,9 @@
#include <kio/job.h>
#include <solid/device.h>
#include <solid/deviceinterface.h>
#include <version.h>
#include "plasma/package.h"
@ -60,15 +64,14 @@ public:
}
};
WallpaperRenderThread WallpaperPrivate::s_renderer;
QList<WallpaperRenderThread *> WallpaperPrivate::s_renderers;
QQueue<WallpaperPrivate::RenderRequest> WallpaperPrivate::s_renderQueue;
PackageStructure::Ptr WallpaperPrivate::s_packageStructure(0);
Wallpaper::Wallpaper(QObject * parentObject)
: d(new WallpaperPrivate(KService::serviceByStorageId(QString()), this))
{
setParent(parentObject);
connect(&WallpaperPrivate::s_renderer, SIGNAL(done(int,QImage,QString,QSize,int,QColor)),
this, SLOT(renderCompleted(int,QImage,QString,QSize,int,QColor)));
}
Wallpaper::Wallpaper(QObject *parentObject, const QVariantList &args)
@ -84,8 +87,6 @@ Wallpaper::Wallpaper(QObject *parentObject, const QVariantList &args)
}
setParent(parentObject);
connect(&WallpaperPrivate::s_renderer, SIGNAL(done(int,QImage,QString,QSize,int,QColor)),
this, SLOT(renderCompleted(int,QImage,QString,QSize,int,QColor)));
}
Wallpaper::~Wallpaper()
@ -386,7 +387,35 @@ void Wallpaper::render(const QString &sourceImagePath, const QSize &size,
}
}
d->renderToken = WallpaperPrivate::s_renderer.render(sourceImagePath, size, resizeMethod, color);
for (int i = 0; i < WallpaperPrivate::s_renderers.size(); i++) {
if (d->renderToken == WallpaperPrivate::s_renderers[i]->currentToken()) {
d->renderToken = WallpaperPrivate::s_renderers[i]->render(sourceImagePath, size, resizeMethod, color);
return;
}
}
if (WallpaperPrivate::s_renderers.size() < qMax(Solid::Device::listFromType(Solid::DeviceInterface::Processor).count(), 1)) {
WallpaperRenderThread *renderThread = new WallpaperRenderThread();
WallpaperPrivate::s_renderers.append(renderThread);
d->renderToken = renderThread->render(sourceImagePath, size, resizeMethod, color);
connect(renderThread, SIGNAL(done(WallpaperRenderThread*,int,QImage,QString,QSize,int,QColor)),
this, SLOT(renderCompleted(WallpaperRenderThread*,int,QImage,QString,QSize,int,QColor)), Qt::UniqueConnection);
} else {
WallpaperPrivate::RenderRequest request;
request.parent = this;
request.file = sourceImagePath;
request.size = size;
request.resizeMethod = resizeMethod;
request.color = color;
for (int i = 0; i < WallpaperPrivate::s_renderQueue.size(); i++) {
if (WallpaperPrivate::s_renderQueue[i].parent.data() == this){
WallpaperPrivate::s_renderQueue[i] = request;
return;
}
}
WallpaperPrivate::s_renderQueue.append(request);
}
//kDebug() << "rendering" << sourceImagePath << ", token is" << d->renderToken;
}
@ -438,10 +467,38 @@ QString WallpaperPrivate::cachePath(const QString &key) const
return KGlobal::dirs()->locateLocal("cache", "plasma-wallpapers/" + key + ".png");
}
void WallpaperPrivate::renderCompleted(int token, const QImage &image,
void WallpaperPrivate::renderCompleted(WallpaperRenderThread *currentRenderer, int token, const QImage &image,
const QString &sourceImagePath, const QSize &size,
int resizeMethod, const QColor &color)
{
q->disconnect(currentRenderer, SIGNAL(done(WallpaperRenderThread*,int,QImage,QString,QSize,int,QColor)),
q, SLOT(renderCompleted(WallpaperRenderThread*,int,QImage,QString,QSize,int,QColor)));
if (!s_renderQueue.isEmpty()) {
while (!s_renderQueue.isEmpty()) {
WallpaperPrivate::RenderRequest request = s_renderQueue.dequeue();
if (!request.parent) {
continue;
}
currentRenderer->wait();
request.parent.data()->d->renderToken = currentRenderer->render(request.file, request.size, request.resizeMethod, request.color);
QObject::connect(currentRenderer, SIGNAL(done(WallpaperRenderThread*,int,QImage,QString,QSize,int,QColor)),
request.parent.data(), SLOT(renderCompleted(WallpaperRenderThread*,int,QImage,QString,QSize,int,QColor)), Qt::UniqueConnection);
break;
}
} else {
for (int i = 0; i < s_renderers.size(); i++) {
if (s_renderers[i] == currentRenderer){
s_renderers.removeAt(i);
}
}
currentRenderer->deleteLater();
currentRenderer = 0;
}
if (token != renderToken) {
//kDebug() << "render token mismatch" << token << renderToken;
return;

View File

@ -477,7 +477,7 @@ class PLASMA_EXPORT Wallpaper : public QObject
QList<QAction*> contextActions;
private:
Q_PRIVATE_SLOT(d, void renderCompleted(int token, const QImage &image,
Q_PRIVATE_SLOT(d, void renderCompleted(WallpaperRenderThread *renderer, int token, const QImage &image,
const QString &sourceImagePath, const QSize &size,
int resizeMethod, const QColor &color))
Q_PRIVATE_SLOT(d, void initScript())