summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <sroedal@trolltech.com>2009-09-04 15:08:44 +0200
committerSamuel Rødal <sroedal@trolltech.com>2009-09-04 16:29:01 +0200
commitf0b0ab1291dec59ae2fe1e88a3b20d173772e175 (patch)
tree2d9e186581a7ece5fdd3e6a15b72796b6424b24b
parent57447242994a16e30d3cb199eefaf625f0088f9f (diff)
Added multiple frames to QPaintBuffer.
This lets us stream a single QPaintBuffer instead of one QPaintBuffer per frame in the trace graphicssystem, which leads to not streaming pixmaps / images once per frame. Performance when doing a trace is also a lot better for painting heavy applications. Reviewed-by: Trond
-rw-r--r--src/gui/painting/qpaintbuffer.cpp26
-rw-r--r--src/gui/painting/qpaintbuffer_p.h8
-rw-r--r--src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp60
-rw-r--r--tools/qttracereplay/main.cpp52
4 files changed, 74 insertions, 72 deletions
diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp
index 7de9063c71..f9cb1088e3 100644
--- a/src/gui/painting/qpaintbuffer.cpp
+++ b/src/gui/painting/qpaintbuffer.cpp
@@ -239,7 +239,7 @@ bool QPaintBuffer::isEmpty() const
-void QPaintBuffer::draw(QPainter *painter) const
+void QPaintBuffer::draw(QPainter *painter, int frame) const
{
#ifdef QPAINTBUFFER_DEBUG_DRAW
qDebug() << "QPaintBuffer::draw() --------------------------------";
@@ -270,10 +270,10 @@ void QPaintBuffer::draw(QPainter *painter) const
? (QPaintEngineEx *) painter->paintEngine() : 0;
if (xengine) {
QPaintEngineExReplayer player;
- player.draw(*this, painter);
+ player.draw(*this, painter, frame);
} else {
QPainterReplayer player;
- player.draw(*this, painter);
+ player.draw(*this, painter, frame);
}
#ifdef QPAINTBUFFER_DEBUG_DRAW
@@ -1035,17 +1035,31 @@ void QPainterReplayer::setupTransform(QPainter *_painter)
painter->setTransform(m_world_matrix);
}
-void QPainterReplayer::draw(const QPaintBuffer &buffer, QPainter *_painter)
+void QPainterReplayer::draw(const QPaintBuffer &buffer, QPainter *_painter, int frame)
{
d = buffer.d_ptr;
setupTransform(_painter);
- for (int cmdIndex=0; cmdIndex<d->commands.size(); ++cmdIndex) {
+ int frameStart = (frame == 0) ? 0 : d->frames.at(frame-1);
+ int frameEnd = (frame == d->frames.size()) ? d->commands.size() : d->frames.at(frame);
+
+ for (int cmdIndex=frameStart; cmdIndex<frameEnd; ++cmdIndex) {
const QPaintBufferCommand &cmd = d->commands.at(cmdIndex);
process(cmd);
}
}
+void QPaintBuffer::beginNewFrame()
+{
+ if (!d_ptr->commands.isEmpty())
+ d_ptr->frames << d_ptr->commands.size();
+}
+
+int QPaintBuffer::numFrames() const
+{
+ return d_ptr->frames.size() + 1;
+}
+
void QPainterReplayer::process(const QPaintBufferCommand &cmd)
{
switch (cmd.id) {
@@ -1783,6 +1797,7 @@ QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer)
stream << variants;
stream << buffer.d_ptr->commands;
stream << buffer.d_ptr->boundingRect;
+ stream << buffer.d_ptr->frames;
return stream;
}
@@ -1800,6 +1815,7 @@ QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer)
stream >> buffer.d_ptr->variants;
stream >> buffer.d_ptr->commands;
stream >> buffer.d_ptr->boundingRect;
+ stream >> buffer.d_ptr->frames;
QVector<QVariant> &variants = buffer.d_ptr->variants;
for (int i = 0; i < variants.size(); ++i) {
diff --git a/src/gui/painting/qpaintbuffer_p.h b/src/gui/painting/qpaintbuffer_p.h
index b3602796d4..2cb1d7c75c 100644
--- a/src/gui/painting/qpaintbuffer_p.h
+++ b/src/gui/painting/qpaintbuffer_p.h
@@ -71,7 +71,10 @@ public:
bool isEmpty() const;
- void draw(QPainter *painter) const;
+ void beginNewFrame();
+ int numFrames() const;
+
+ void draw(QPainter *painter, int frame = 0) const;
void setBoundingRect(const QRectF &rect);
QRectF boundingRect() const;
@@ -270,6 +273,7 @@ public:
QVector<QVariant> variants;
QVector<QPaintBufferCommand> commands;
+ QList<int> frames;
QPaintBufferEngine *engine;
QRectF boundingRect;
@@ -306,7 +310,7 @@ public:
void setupTransform(QPainter *painter);
void process(const QPaintBufferCommand &cmd);
- void draw(const QPaintBuffer &buffer, QPainter *painter);
+ void draw(const QPaintBuffer &buffer, QPainter *painter, int frame);
protected:
QPaintBufferPrivate *d;
diff --git a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp
index 36a8df1191..bbb65368e2 100644
--- a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp
+++ b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp
@@ -57,30 +57,35 @@ public:
~QTraceWindowSurface();
QPaintDevice *paintDevice();
+ void beginPaint(const QRegion &rgn);
void endPaint(const QRegion &rgn);
+ bool scroll(const QRegion &area, int dx, int dy);
+
private:
QPaintBuffer *buffer;
+ QList<QRegion> updates;
- QFile *outputFile;
- QDataStream *out;
-
- int frameId;
+ qulonglong winId;
};
QTraceWindowSurface::QTraceWindowSurface(QWidget *widget)
: QRasterWindowSurface(widget)
, buffer(0)
- , outputFile(0)
- , out(0)
- , frameId(0)
+ , winId(0)
{
}
QTraceWindowSurface::~QTraceWindowSurface()
{
- delete out;
- delete outputFile;
+ if (buffer) {
+ QFile outputFile(QString(QLatin1String("qtgraphics-%0.trace")).arg(winId));
+ if (outputFile.open(QIODevice::WriteOnly)) {
+ QDataStream out(&outputFile);
+ out << *buffer << updates;
+ }
+ delete buffer;
+ }
}
QPaintDevice *QTraceWindowSurface::paintDevice()
@@ -92,28 +97,33 @@ QPaintDevice *QTraceWindowSurface::paintDevice()
return buffer;
}
-void QTraceWindowSurface::endPaint(const QRegion &rgn)
+void QTraceWindowSurface::beginPaint(const QRegion &rgn)
{
- if (!out) {
- outputFile = new QFile(QString(QLatin1String("qtgraphics-%0.trace")).arg((qulonglong)window()->winId()));
- if (outputFile->open(QIODevice::WriteOnly))
- out = new QDataStream(outputFile);
- }
+ // ensure paint buffer is created
+ paintDevice();
+ buffer->beginNewFrame();
+
+ QRasterWindowSurface::beginPaint(rgn);
+}
+void QTraceWindowSurface::endPaint(const QRegion &rgn)
+{
QPainter p(QRasterWindowSurface::paintDevice());
- buffer->draw(&p);
+ buffer->draw(&p, buffer->numFrames()-1);
p.end();
- if (out) {
- *out << frameId++;
- *out << (qulonglong)window()->winId();
- *out << geometry();
- *out << rgn;
- *out << *buffer;
- }
+ winId = (qulonglong)window()->winId();
+
+ updates << rgn;
- delete buffer;
- buffer = 0;
+ QRasterWindowSurface::endPaint(rgn);
+}
+
+bool QTraceWindowSurface::scroll(const QRegion &, int, int)
+{
+ // TODO: scrolling should also be streamed and replayed
+ // to test scrolling performance
+ return false;
}
QTraceGraphicsSystem::QTraceGraphicsSystem()
diff --git a/tools/qttracereplay/main.cpp b/tools/qttracereplay/main.cpp
index 970531bba4..34508e234e 100644
--- a/tools/qttracereplay/main.cpp
+++ b/tools/qttracereplay/main.cpp
@@ -45,12 +45,6 @@
#include <private/qpaintengineex_p.h>
#include <private/qpaintbuffer_p.h>
-struct Frame
-{
- QRegion updateRegion;
- QPaintBuffer *buffer;
-};
-
class ReplayWidget : public QWidget
{
Q_OBJECT
@@ -63,7 +57,9 @@ public slots:
void updateRect();
private:
- QList<Frame> frames;
+ QList<QRegion> updates;
+ QPaintBuffer buffer;
+
int currentFrame;
int currentIteration;
QTime timer;
@@ -74,7 +70,7 @@ private:
void ReplayWidget::updateRect()
{
- update(frames.at(currentFrame).updateRegion);
+ update(updates.at(currentFrame));
}
void ReplayWidget::paintEvent(QPaintEvent *)
@@ -83,10 +79,10 @@ void ReplayWidget::paintEvent(QPaintEvent *)
// p.setClipRegion(frames.at(currentFrame).updateRegion);
- frames.at(currentFrame).buffer->draw(&p);
+ buffer.draw(&p, currentFrame);
++currentFrame;
- if (currentFrame >= frames.size()) {
+ if (currentFrame >= buffer.numFrames()) {
currentFrame = 0;
++currentIteration;
@@ -116,15 +112,13 @@ void ReplayWidget::paintEvent(QPaintEvent *)
stddev = qSqrt(stddev / iterationTimes.size());
qSort(iterationTimes.begin(), iterationTimes.end());
- qreal median = iterationTimes.at(iterationTimes.size() / 2);
- if ((iterationTimes.size() % 1) == 1)
- median = (median + iterationTimes.at(iterationTimes.size() / 2 - 1)) * 0.5;
+ uint median = iterationTimes.at(iterationTimes.size() / 2);
stddev = 100 * stddev / mean;
if (iterationTimes.size() >= 10 || stddev < 4) {
- printf("%s, iterations: %d, frames: %d, min(ms): %d, median(ms): %f, stddev: %f %%, max(fps): %f\n", qPrintable(filename),
- iterationTimes.size(), frames.size(), min, median, stddev, 1000. * frames.size() / min);
+ printf("%s, iterations: %d, frames: %d, min(ms): %d, median(ms): %d, stddev: %f %%, max(fps): %f\n", qPrintable(filename),
+ iterationTimes.size(), updates.size(), min, median, stddev, 1000. * updates.size() / min);
deleteLater();
return;
}
@@ -146,34 +140,12 @@ ReplayWidget::ReplayWidget(const QString &filename_)
QRect bounds;
if (file.open(QIODevice::ReadOnly)) {
QDataStream in(&file);
-
- while (true) {
- int frameId;
- in >> frameId;
-
- if (in.status() != QDataStream::Ok)
- break;
-
- qulonglong windowId;
- QRegion rgn;
-
- in >> windowId;
-
- Frame frame;
- frame.buffer = new QPaintBuffer;
-
- in >> bounds;
-
- in >> frame.updateRegion;
- in >> *frame.buffer;
-
- frames << frame;
- }
+ in >> buffer >> updates;
}
- qDebug() << "Read" << frames.size() << "frames";
+ qDebug() << "Read paint buffer with" << buffer.numFrames() << "frames";
- resize(bounds.size());
+ resize(buffer.boundingRect().size().toSize());
setAutoFillBackground(false);
setAttribute(Qt::WA_NoSystemBackground);