From f0b0ab1291dec59ae2fe1e88a3b20d173772e175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 4 Sep 2009 15:08:44 +0200 Subject: 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 --- src/gui/painting/qpaintbuffer.cpp | 26 ++++++++-- src/gui/painting/qpaintbuffer_p.h | 8 ++- .../trace/qgraphicssystem_trace.cpp | 60 +++++++++++++--------- tools/qttracereplay/main.cpp | 52 +++++-------------- 4 files changed, 74 insertions(+), 72 deletions(-) diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp index 7de9063..f9cb108 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; cmdIndexcommands.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; cmdIndexcommands.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 &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 b360279..2cb1d7c 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 variants; QVector commands; + QList 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 36a8df1..bbb6536 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 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 970531b..34508e2 100644 --- a/tools/qttracereplay/main.cpp +++ b/tools/qttracereplay/main.cpp @@ -45,12 +45,6 @@ #include #include -struct Frame -{ - QRegion updateRegion; - QPaintBuffer *buffer; -}; - class ReplayWidget : public QWidget { Q_OBJECT @@ -63,7 +57,9 @@ public slots: void updateRect(); private: - QList frames; + QList 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); -- cgit v0.12